Module: wine Branch: refs/heads/master Commit: 0b34fb365657b9983a591610b2d80e298623d6f0 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=0b34fb365657b9983a591610...
Author: Alexandre Julliard julliard@winehq.org Date: Sat Feb 11 22:38:44 2006 +0100
libwine: Use dladdr if supported to get the run-time path of libwine.so and define the default dll and bin directories relative to it.
---
libs/wine/Makefile.in | 2 - libs/wine/config.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++- libs/wine/loader.c | 6 ++- 3 files changed, 112 insertions(+), 6 deletions(-)
diff --git a/libs/wine/Makefile.in b/libs/wine/Makefile.in index b9ddf42..34b6400 100644 --- a/libs/wine/Makefile.in +++ b/libs/wine/Makefile.in @@ -5,7 +5,7 @@ VPATH = @srcdir@ LIBRARY = wine SOVERSION = 1 VERSCRIPT = $(SRCDIR)/wine.map -EXTRADEFS = -D__WINESRC__ -DBINDIR=""$(bindir)"" -DDLLDIR=""$(dlldir)"" +EXTRADEFS = -D__WINESRC__ -DBINDIR=""$(bindir)"" -DLIBDIR=""$(libdir)"" -DDLLDIR=""$(dlldir)"" EXTRALIBS = $(LIBPORT) @DLLIBS@ @CRTLIBS@ @LDLIBWINEFLAGS@
C_SRCS = \ diff --git a/libs/wine/config.c b/libs/wine/config.c index b2b039c..33aa87a 100644 --- a/libs/wine/config.c +++ b/libs/wine/config.c @@ -101,6 +101,103 @@ inline static void remove_trailing_slash while (len > 1 && path[len-1] == '/') path[--len] = 0; }
+/* determine where the destination path is located relative to the 'from' path */ +inline static const char *get_relative_path( const char *from, const char *dest, unsigned int *dotdots ) +{ +#define DIR_END(p) (*(p) == 0 || *(p) == '/') + const char *start; + + *dotdots = 0; + for (;;) + { + while (*from == '/') from++; + while (*dest == '/') dest++; + start = dest; /* save start of next path element */ + if (!*from) break; + + while (!DIR_END(from) && *from == *dest) { from++; dest++; } + if (DIR_END(from) && DIR_END(dest)) continue; + + /* count remaining elements in 'from' */ + do + { + (*dotdots)++; + while (!DIR_END(from)) from++; + while (*from == '/') from++; + } + while (*from); + break; + } + return start; +#undef DIR_END +} + +/* return the directory that contains the library at run-time */ +static const char *get_runtime_libdir(void) +{ + static char *libdir; + +#ifdef HAVE_DLADDR + Dl_info info; + char *p; + + if (!libdir && dladdr( get_runtime_libdir, &info ) && (p = strrchr( info.dli_fname, '/' ))) + { + unsigned int len = p - info.dli_fname; + if (!len) len++; /* include initial slash */ + libdir = xmalloc( len + 1 ); + memcpy( libdir, info.dli_fname, len ); + libdir[len] = 0; + } +#endif /* HAVE_DLADDR */ + return libdir; +} + +/* determine the proper location of the given path based on the current libdir */ +static char *get_path_from_libdir( const char *path, const char *filename ) +{ + char *p, *ret; + const char *libdir = get_runtime_libdir(); + + /* retrieve the library load path */ + + if (libdir) + { + unsigned int dotdots = 0; + const char *start = get_relative_path( LIBDIR, path, &dotdots ); + + ret = xmalloc( strlen(libdir) + 3 * dotdots + strlen(start) + strlen(filename) + 3 ); + strcpy( ret, libdir ); + p = ret + strlen(libdir); + if (p[-1] != '/') *p++ = '/'; + + while (dotdots--) + { + p[0] = '.'; + p[1] = '.'; + p[2] = '/'; + p += 3; + } + + strcpy( p, start ); + p += strlen(p); + } + else + { + ret = xmalloc( strlen(path) + strlen(filename) + 2 ); + strcpy( ret, path ); + p = ret + strlen(ret); + } + + if (*filename) + { + if (p[-1] != '/') *p++ = '/'; + strcpy( p, filename ); + } + else if (p[-1] == '/') p[-1] = 0; + return ret; +} + /* initialize the server directory value */ static void init_server_dir( dev_t dev, ino_t ino ) { @@ -127,6 +224,15 @@ static void init_server_dir( dev_t dev, sprintf( p, "%lx", (unsigned long)ino ); }
+/* retrieve the default dll dir */ +const char *get_default_dlldir(void) +{ + static const char *dlldir; + + if (!dlldir) dlldir = get_path_from_libdir( DLLDIR, "" ); + return dlldir; +} + /* initialize all the paths values */ static void init_paths(void) { @@ -314,9 +420,7 @@ void wine_exec_wine_binary( const char * else if (!name) name = argv0_name;
/* first, try bin directory */ - argv[0] = xmalloc( sizeof(BINDIR "/") + strlen(name) ); - strcpy( argv[0], BINDIR "/" ); - strcat( argv[0], name ); + argv[0] = get_path_from_libdir( BINDIR, name ); preloader_exec( argv, envp, use_preloader ); free( argv[0] );
diff --git a/libs/wine/loader.c b/libs/wine/loader.c index 50ab544..e58ab7c 100644 --- a/libs/wine/loader.c +++ b/libs/wine/loader.c @@ -74,13 +74,14 @@ static const IMAGE_NT_HEADERS *main_exe;
static load_dll_callback_t load_dll_callback;
-static const char default_dlldir[] = DLLDIR; +static const char *default_dlldir; static const char **dll_paths; static int nb_dll_paths; static int dll_path_maxlen;
extern void mmap_init(void); extern void debug_init(void); +extern const char *get_default_dlldir(void);
/* build the dll load path from the WINEDLLPATH variable */ static void build_dll_path(void) @@ -121,7 +122,8 @@ static void build_dll_path(void) }
/* append default dll dir (if not empty) to path */ - if ((len = sizeof(default_dlldir)-1)) + default_dlldir = get_default_dlldir(); + if ((len = strlen(default_dlldir)) > 0) { if (len > dll_path_maxlen) dll_path_maxlen = len; dll_paths[nb_dll_paths++] = default_dlldir;