libwine: Determine the bin directory independently from the lib directory if possible.

Prefer the bin directory when getting the data dir location.
This commit is contained in:
Alexandre Julliard 2009-08-25 12:47:50 +02:00
parent b3fb793b52
commit 995e553715
2 changed files with 91 additions and 65 deletions

View File

@ -111,7 +111,6 @@ CONFIGDIRS = \
-DLIB_TO_BINDIR=\"`$(RELPATH) $(libdir) $(bindir)`\" \ -DLIB_TO_BINDIR=\"`$(RELPATH) $(libdir) $(bindir)`\" \
-DLIB_TO_DLLDIR=\"`$(RELPATH) $(libdir) $(dlldir)`\" \ -DLIB_TO_DLLDIR=\"`$(RELPATH) $(libdir) $(dlldir)`\" \
-DBIN_TO_DLLDIR=\"`$(RELPATH) $(bindir) $(dlldir)`\" \ -DBIN_TO_DLLDIR=\"`$(RELPATH) $(bindir) $(dlldir)`\" \
-DLIB_TO_DATADIR=\"`$(RELPATH) $(libdir) $(datadir)/wine`\" \
-DBIN_TO_DATADIR=\"`$(RELPATH) $(bindir) $(datadir)/wine`\" -DBIN_TO_DATADIR=\"`$(RELPATH) $(bindir) $(datadir)/wine`\"
config.o: config.c $(RELPATH) config.o: config.c $(RELPATH)

View File

@ -137,6 +137,63 @@ static char *get_runtime_libdir(void)
return NULL; return NULL;
} }
/* return the directory that contains the main exe at run-time */
static char *get_runtime_bindir( const char *argv0 )
{
char *p, *bindir, *cwd;
size_t len, size;
#ifdef linux
for (size = 256; ; size *= 2)
{
int ret;
if (!(bindir = malloc( size ))) break;
if ((ret = readlink( "/proc/self/exe", bindir, size )) == -1) break;
if (ret != size)
{
if (!(p = memrchr( bindir, '/', ret ))) break;
if (p == bindir) p++;
*p = 0;
return bindir;
}
free( bindir );
}
free( bindir );
#endif
if (!(p = strrchr( argv0, '/' ))) return NULL;
len = p - argv0;
if (!len) len++; /* include leading slash */
if (argv0[0] == '/') /* absolute path */
{
bindir = xmalloc( len + 1 );
memcpy( bindir, argv0, len );
bindir[len] = 0;
}
else
{
/* relative path, make it absolute */
for (size = 256 + len; ; size *= 2)
{
if (!(cwd = malloc( size ))) return NULL;
if (getcwd( cwd, size - len ))
{
bindir = cwd;
cwd += strlen(cwd);
*cwd++ = '/';
memcpy( cwd, argv0, len );
cwd[len] = 0;
break;
}
free( cwd );
if (errno != ERANGE) return NULL;
}
}
return bindir;
}
/* initialize the server directory value */ /* initialize the server directory value */
static void init_server_dir( dev_t dev, ino_t ino ) static void init_server_dir( dev_t dev, ino_t ino )
{ {
@ -235,6 +292,16 @@ static void init_paths(void)
init_server_dir( st.st_dev, st.st_ino ); init_server_dir( st.st_dev, st.st_ino );
} }
/* check if bindir is valid by checking for wineserver */
static int is_valid_bindir( const char *bindir )
{
struct stat st;
char *path = build_path( bindir, "wineserver" );
int ret = (stat( path, &st ) != -1);
free( path );
return ret;
}
/* check if basedir is a valid build dir by checking for wineserver and ntdll */ /* check if basedir is a valid build dir by checking for wineserver and ntdll */
/* helper for running_from_build_dir */ /* helper for running_from_build_dir */
static inline int is_valid_build_dir( char *basedir, int baselen ) static inline int is_valid_build_dir( char *basedir, int baselen )
@ -252,17 +319,10 @@ static inline int is_valid_build_dir( char *basedir, int baselen )
} }
/* check if we are running from the build directory */ /* check if we are running from the build directory */
static char *running_from_build_dir( const char *basedir, const char *bindir ) static char *running_from_build_dir( const char *basedir )
{ {
struct stat st;
const char *p; const char *p;
char *path; char *path;
int res;
if (!(path = build_path( bindir, "wineserver" ))) return NULL;
res = stat( path, &st );
free( path );
if (res != -1) return NULL; /* the real bindir is valid */
/* remove last component from basedir */ /* remove last component from basedir */
p = basedir + strlen(basedir) - 1; p = basedir + strlen(basedir) - 1;
@ -289,73 +349,40 @@ static char *running_from_build_dir( const char *basedir, const char *bindir )
/* initialize the argv0 path */ /* initialize the argv0 path */
void wine_init_argv0_path( const char *argv0 ) void wine_init_argv0_path( const char *argv0 )
{ {
size_t size, len; const char *basename;
const char *p, *basename; char *libdir;
char *cwd, *libdir;
if (!(p = strrchr( argv0, '/' ))) if (!(basename = strrchr( argv0, '/' ))) basename = argv0;
basename = argv0; else basename++;
else
basename = p + 1;
argv0_name = xstrdup( basename ); bindir = get_runtime_bindir( argv0 );
libdir = get_runtime_libdir();
if ((libdir = get_runtime_libdir())) if (bindir && !is_valid_bindir( bindir ))
{ {
bindir = build_path( libdir, LIB_TO_BINDIR ); build_dir = running_from_build_dir( bindir );
if ((build_dir = running_from_build_dir( libdir, bindir ))) free( bindir );
{ bindir = NULL;
free( libdir ); }
goto in_build_dir; if (libdir && !bindir && !build_dir)
} {
dlldir = build_path( libdir, LIB_TO_DLLDIR ); build_dir = running_from_build_dir( libdir );
datadir = build_path( libdir, LIB_TO_DATADIR ); if (!build_dir) bindir = build_path( libdir, LIB_TO_BINDIR );
free( libdir );
return;
} }
if (!p) return; /* if argv0 doesn't contain a path, don't store anything */ if (build_dir)
len = p - argv0;
if (!len) len++; /* include leading slash */
if (argv0[0] == '/') /* absolute path */
{ {
bindir = xmalloc( len + 1 ); argv0_name = build_path( "loader/", basename );
memcpy( bindir, argv0, len );
bindir[len] = 0;
} }
else else
{ {
/* relative path, make it absolute */ if (libdir) dlldir = build_path( libdir, LIB_TO_DLLDIR );
for (size = 256 + len; ; size *= 2) else if (bindir) dlldir = build_path( bindir, BIN_TO_DLLDIR );
{
if (!(cwd = malloc( size ))) return; if (bindir) datadir = build_path( bindir, BIN_TO_DATADIR );
if (getcwd( cwd, size - len )) argv0_name = xstrdup( basename );
{
bindir = cwd;
cwd += strlen(cwd);
*cwd++ = '/';
memcpy( cwd, argv0, len );
cwd[len] = 0;
break;
}
free( cwd );
if (errno != ERANGE) return;
}
} }
free( libdir );
if ((build_dir = running_from_build_dir( bindir, bindir ))) goto in_build_dir;
dlldir = build_path( bindir, BIN_TO_DLLDIR );
datadir = build_path( bindir, BIN_TO_DATADIR );
return;
in_build_dir:
free( bindir );
free( argv0_name );
bindir = NULL;
argv0_name = build_path( "loader/", basename );
} }
/* return the configuration directory ($WINEPREFIX or $HOME/.wine) */ /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */