diff options
author | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:38:33 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:38:33 +0000 |
commit | 1fd5e000ace55b323124c7e556a7a864b972a5c4 (patch) | |
tree | dc4fcf1e5e22a040716ef92c496b8d94959b2baa /winsup/cygwin/dlfcn.cc | |
parent | 369d8a8fd5e887eca547bf34bccfdf755c9e5397 (diff) | |
download | newlib-1fd5e000ace55b323124c7e556a7a864b972a5c4.zip newlib-1fd5e000ace55b323124c7e556a7a864b972a5c4.tar.gz newlib-1fd5e000ace55b323124c7e556a7a864b972a5c4.tar.bz2 |
import winsup-2000-02-17 snapshot
Diffstat (limited to 'winsup/cygwin/dlfcn.cc')
-rw-r--r-- | winsup/cygwin/dlfcn.cc | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc new file mode 100644 index 0000000..21c6e5b --- /dev/null +++ b/winsup/cygwin/dlfcn.cc @@ -0,0 +1,236 @@ +/* dlfcn.cc + + Copyright 1998, 2000 Cygnus Solutions + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "winsup.h" +#include <ctype.h> +#include "dlfcn.h" +#include "dll_init.h" + +#ifdef _MT_SAFE +#define _dl_error _reent_winsup()->_dl_error +#define _dl_buffer _reent_winsup()->_dl_buffer +#else +static int _dl_error = 0; +static char _dl_buffer[256]; +#endif + +static void __stdcall +set_dl_error (const char *str) +{ + __small_sprintf (_dl_buffer, "%s: %E", str); + _dl_error = 1; +} + +// +// this function checks for existence of a file specified by the +// directory and name components. If successful, return a pointer +// the full pathname (static buffer), or else return 0. +// +static const char * __stdcall +check_access (const char *dir, const char *name) +{ + static char buf[MAX_PATH]; + const char *ret = 0; + + buf[0] = 0; + strcpy (buf, dir); + strcat (buf, "\\"); + strcat (buf, name); + + if (!access (buf, F_OK)) + ret = buf; + return ret; +} + +// +// this function looks for an executable file given the name and the +// environment variable to use for searching (eg., PATH); returns +// the full pathname (static buffer) if found or NULL if not. +// +static const char * __stdcall +check_path_access (const char *mywinenv, const char *name) +{ + static char buf[MAX_PATH]; + return find_exec (name, buf, mywinenv, TRUE); +} + +// +// This function simulates the same search as LoadLibary + check +// environment variable LD_LIBRARY_PATH. If found, return the full +// pathname (static buffer); if illegal, return the input string +// unchanged and let the caller deal with it; return NULL otherwise. +// +// Note that this should never be called with a NULL string, since +// that is the introspective case, and the caller should not call +// this function at all. +// +static const char * __stdcall +get_full_path_of_dll (const char* str) +{ + int len = (str) ? strlen (str) : 0; + + // NULL or empty string or too long to be legal win32 pathname? + if (len == 0 || len >= MAX_PATH - 1) + return str; + + char buf[MAX_PATH]; + static char name[MAX_PATH]; + const char *ret = 0; + + strcpy (name, str); + + // add extension if necessary, but leave a trailing '.', if any, alone. + // Files with trailing '.'s are handled differently by win32 API. + if (str[len - 1] != '.') + { + // add .dll only if no extension provided. Handle various cases: + // + // ./shlib --> ./shlib.dll + // ./dir/shlib.so --> ./dir/shlib.so + // shlib --> shlib.dll + // shlib.dll --> shlib.dll + // shlib.so --> shlib.so + // + const char *p = strrchr (str, '.'); + if (!p || isdirsep (p[1])) + strcat (name, ".dll"); + } + + // deal with fully qualified filename right away. Do the actual + // conversion to win32 filename just before returning however. + if (isabspath (str)) + ret = name; + + // current directory + if (!ret) + { + if (GetCurrentDirectory (MAX_PATH, buf) == 0) + small_printf ("WARNING: get_full_path_of_dll can't get current directory win32 %E\n"); + else + ret = check_access (buf, name); + } + + // LD_LIBRARY_PATH + if (!ret) + ret = check_path_access ("LD_LIBRARY_PATH=", name); + + if (!ret) + { + // system directory + if (GetSystemDirectory (buf, MAX_PATH) == 0) + small_printf ("WARNING: get_full_path_of_dll can't get system directory win32 %E\n"); + else + ret = check_access (buf, name); + } + + // 16 bits system directory + if (!ret && (os_being_run == winNT)) + { + // we assume last dir was xxxxx\SYSTEM32, so we remove 32 + len = strlen (buf); + buf[len - 2] = 0; + ret = check_access (buf, name); + } + + // windows directory + if (!ret) + { + if (GetWindowsDirectory (buf, MAX_PATH) == 0) + small_printf ("WARNING: get_full_path_of_dll can't get Windows directory win32 %E\n"); + else + ret = check_access (buf, name); + } + + // PATH + if (!ret) + ret = check_path_access ("PATH=", name); + + // + // now do a final conversion to win32 pathname. This step is necessary + // to resolve symlinks etc so that win32 API finds the underlying file. + // + if (ret) + { + path_conv real_filename (ret, SYMLINK_FOLLOW, 1); + if (real_filename.error) + ret = 0; + else + { + strcpy (name, real_filename.get_win32 ()); + ret = name; + } + } + return ret; +} + +void * +dlopen (const char *name, int) +{ + SetResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlopen"); + + void *ret = 0; + + if (!name) + { + // handle for the current module + ret = (void *) GetModuleHandle (0); + } + else + { + // handle for the named library + const char *fullpath = get_full_path_of_dll (name); + DllList::the().currentDlOpenedLib (fullpath); + ret = (void *) LoadLibrary (fullpath); + } + + if (!ret) + set_dl_error ("dlopen"); + debug_printf ("ret %p", ret); + + ReleaseResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlopen"); + return ret; +} + +void * +dlsym (void *handle, const char *name) +{ + void *ret = (void *) GetProcAddress ((HMODULE) handle, name); + if (!ret) + set_dl_error ("dlsym"); + debug_printf ("ret %p", ret); + return ret; +} + +int +dlclose (void *handle) +{ + SetResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlclose"); + + int ret = -1; + if (FreeLibrary ((HMODULE) handle)) + ret = 0; + if (ret) + set_dl_error ("dlclose"); + + ReleaseResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlclose"); + return ret; +} + +char * +dlerror () +{ + char *ret = 0; + if (_dl_error) + ret = _dl_buffer; + return ret; +} |