Binary relocatability part 2
Mike Hearn
mike at navi.cx
Sat Aug 28 06:50:07 CDT 2004
It might be worth putting read_symlink into libwine, rather than
duplicate the code.
On systems that don't use the standard FHS layout this will lead to a
useless dll path entry, but it should be harmless and for everybody who
does use the default layout it means you can place the wine binaries
anywhere at runtime.
I think these two patches do it a lot more cleanly than my previous
attempt back before WineConf, but let me know if it's got any more
problems.
thanks -mike
Mike Hearn <mike at navi.cx>
Allow relocatability on systems that support /proc/self/exe when using
the default directory layout.
-------------- next part --------------
--- libs/wine/loader.c.~1.21.~ 2004-06-14 18:07:30.000000000 +0100
+++ libs/wine/loader.c 2004-08-22 22:46:03.778222560 +0100
@@ -80,12 +80,44 @@
extern void mmap_init(void);
+static char *read_symlink( char *path )
+{
+ int size = 256;
+ char *buffer = NULL;
+
+ while (TRUE)
+ {
+ int nchars;
+
+ buffer = (char *) realloc( buffer, size );
+ nchars = readlink( path, buffer, size );
+
+ if (nchars < 0)
+ {
+ free( buffer );
+ return NULL;
+ }
+
+ if (nchars < size) return buffer;
+ size *= 2;
+ }
+}
+
+static int isdir( char *path )
+{
+ struct stat buf;
+ if (stat( path, &buf ) == 0) return S_ISDIR( buf );
+
+ return 0;
+}
+
/* build the dll load path from the WINEDLLPATH variable */
static void build_dll_path(void)
{
static const char * const dlldir = DLLDIR;
int len, count = 0;
char *p, *path = getenv( "WINEDLLPATH" );
+ char *selfpath = read_symlink( "/proc/self/exe" );
if (path)
{
@@ -101,7 +133,10 @@
}
}
- dll_paths = malloc( (count+1) * sizeof(*dll_paths) );
+ if (selfpath)
+ dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
+ else
+ dll_paths = malloc( (count+1) * sizeof(*dll_paths) );
if (count)
{
@@ -125,6 +160,33 @@
if (len > dll_path_maxlen) dll_path_maxlen = len;
dll_paths[nb_dll_paths++] = dlldir;
}
+
+ /* on Linux we can dynamically discover our own DLL path */
+ if (selfpath)
+ {
+ /* strip /bin/wine from our executable path */
+ char *marker = strrchr( selfpath, '/' );
+ static const char *libwinepath = "/lib/wine";
+
+ if (!marker) goto end;
+
+ marker = strrchr( marker, '/' );
+ if (!marker) goto end;
+
+ *marker = '\0';
+
+ selfpath = realloc( selfpath, strlen(selfpath) + strlen(libwinepath) + 1 );
+ strcat( selfpath, libwinepath );
+
+ if (!isdir( selfpath )) goto end;
+
+ len = strlen( selfpath );
+ if (len > dll_path_maxlen) dll_path_maxlen = len;
+ dllpaths[nb_dll_paths++] = selfpath;
+ }
+
+end:
+ if (selfpath) free( selfpath );
}
/* check if a given file can be opened */
--- dlls/ntdll/server.c.~1.17.~ 2004-08-22 13:57:22.000000000 +0100
+++ dlls/ntdll/server.c 2004-08-22 23:51:56.136372792 +0100
@@ -709,6 +709,29 @@
errno = err;
}
+static char *read_symlink( char *path )
+{
+ int size = 256;
+ char *buffer = NULL;
+
+ while (TRUE)
+ {
+ int nchars;
+
+ buffer = (char *) realloc( buffer, size );
+ nchars = readlink( path, buffer, size );
+
+ if (nchars < 0)
+ {
+ free( buffer );
+ return NULL;
+ }
+
+ if (nchars < size) return buffer;
+ size *= 2;
+ }
+}
+
/***********************************************************************
* create_config_dir
@@ -743,12 +766,26 @@
if (!pid)
{
const char *argv[5];
+ char *selfpath = read_symlink( "/proc/self/exe" );
argv[0] = "wineprefixcreate";
argv[1] = "--quiet";
argv[2] = "--prefix";
argv[3] = tmp_dir;
argv[4] = NULL;
+
+ /* set WINELOADER/WINESERVER to absolute path if not already in environment */
+ if (selfpath)
+ {
+ char *marker = strrchr( selfpath, '/' );
+ if (!strcmp( marker, "/wine-preloader" )) *strrchr( selfpath, '-' ) = '\0';
+ setenv( "WINELOADER", selfpath, 0 );
+
+ /* wine-preloader/wine-[pk]thread are long enough that we can just overwrite here */
+ strcpy( marker, "/wineserver" );
+ setenv( "WINESERVER", selfpath, 0 );
+ }
+
wine_exec_wine_binary( argv[0], (char **)argv, NULL, FALSE );
rmdir( tmp_dir );
fatal_perror( "could not exec wineprefixcreate" );
More information about the wine-patches
mailing list