Alexandre Julliard : libwine:
Use dladdr if supported to get the run-time path of libwine.so
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Feb 13 07:03:20 CST 2006
Module: wine
Branch: refs/heads/master
Commit: 0b34fb365657b9983a591610b2d80e298623d6f0
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=0b34fb365657b9983a591610b2d80e298623d6f0
Author: Alexandre Julliard <julliard at 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;
More information about the wine-cvs
mailing list