[PATCH 3/4] dlopen: on x/lib search x/bin if exe is in x/bin
Corinna Vinschen
corinna-cygwin@cygwin.com
Thu Sep 1 13:33:00 GMT 2016
Hi Michael,
On Aug 31 20:07, Michael Haubenwallner wrote:
> citing https://cygwin.com/ml/cygwin-developers/2016-08/msg00020.html
> > Consider the file /usr/bin/cygz.dll:
> > - dlopen (libz.so) success
> > - dlopen (/usr/bin/libz.so) success
> > - dlopen (/usr/lib/libz.so) fails
>
> * dlfcn.c (dlopen): For dlopen("x/lib/N"), when the application
> executable is in "x/bin/", search for "x/bin/N" before "x/lib/N".
> ---
> winsup/cygwin/dlfcn.cc | 36 +++++++++++++++++++++++++++++++++++-
> 1 file changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
> index e592512..f8b8743 100644
> --- a/winsup/cygwin/dlfcn.cc
> +++ b/winsup/cygwin/dlfcn.cc
> @@ -153,6 +153,25 @@ collect_basenames (pathfinder::basenamelist & basenames,
> basenames.appendv (basename, baselen, ext, extlen, NULL);
> }
>
> +/* Identify dir of current executable into exedirbuf using wpathbuf buffer.
> + Return length of exedirbuf on success, or zero on error. */
> +static int
> +get_exedir (char * exedirbuf, wchar_t * wpathbuf)
> +{
> + /* Unless we have a special cygwin loader, there is no such thing like
> + DT_RUNPATH on Windows we can use to search for dlls, except for the
> + directory of the main executable. */
> + GetModuleFileNameW (NULL, wpathbuf, NT_MAX_PATH);
> + wchar_t * lastwsep = wcsrchr (wpathbuf, L'\\');
> + if (!lastwsep)
> + return 0;
> + *lastwsep = L'\0';
> + *exedirbuf = '\0';
> + if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, wpathbuf, exedirbuf, NT_MAX_PATH))
> + return 0;
> + return strlen (exedirbuf);
> +}
You could just use the global variable program_invocation_name. If in
doubt, use the Windows path global_progname and convert it to full POSIX
via cygwin_conv_path.
> extern "C" void *
> dlopen (const char *name, int flags)
> {
> @@ -184,13 +203,28 @@ dlopen (const char *name, int flags)
> /* handle for the named library */
> path_conv real_filename;
> wchar_t *wpath = tp.w_get ();
> + char *cpath = tp.c_get ();
>
> pathfinder finder (allocator, basenames); /* eats basenames */
>
> if (have_dir)
> {
> + int dirlen = basename - 1 - name;
> +
> + /* if the specified dir is x/lib, and the current executable
> + dir is x/bin, do the /lib -> /bin mapping, which is the
> + same actually as adding the executable dir */
> + if (dirlen >= 4 && !strncmp (name + dirlen - 4, "/lib", 4))
> + {
> + int exedirlen = get_exedir (cpath, wpath);
> + if (exedirlen == dirlen &&
> + !strncmp (cpath, name, dirlen - 4) &&
> + !strcmp (cpath + dirlen - 4, "/bin"))
> + finder.add_searchdir (cpath, exedirlen);
> + }
> +
> /* search the specified dir */
> - finder.add_searchdir (name, basename - 1 - name);
> + finder.add_searchdir (name, dirlen);
> }
> else
> {
> --
> 2.7.3
Rest looks ok.
Thanks,
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin-patches/attachments/20160901/1685214e/attachment.sig>
More information about the Cygwin-patches
mailing list