mirror of
git://git.savannah.gnu.org/libtool.git
synced 2025-03-25 16:00:24 +08:00
* libltdl/ltdl.c: major rewrite to avoid almost all fixed-size
buffers; only `tmp' in lt_dlopen remained. But the code got ugly :-(
This commit is contained in:
parent
81df2fb6e3
commit
24c33318ba
@ -1,5 +1,9 @@
|
||||
1999-01-21 Alexandre Oliva <oliva@dcc.unicamp.br>
|
||||
|
||||
* libltdl/ltdl.c: major rewrite to avoid almost all fixed-size
|
||||
buffers; only `tmp' in lt_dlopen remained. But the code got ugly
|
||||
:-(
|
||||
|
||||
* ltconfig.in (linux-gnu*, finish_cmds): remove erroneous backslash
|
||||
|
||||
* demo/configure.in: set DLPREOPEN to -dlopen if we don't have
|
||||
|
380
libltdl/ltdl.c
380
libltdl/ltdl.c
@ -59,10 +59,6 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef LTDL_SEARCHPATH_MAX
|
||||
#define LTDL_SEARCHPATH_MAX 4096
|
||||
#endif
|
||||
|
||||
#undef LTDL_READTEXT_MODE
|
||||
/* fopen() mode flags for reading a text file */
|
||||
#ifdef _WIN32
|
||||
@ -73,7 +69,7 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#undef LTDL_SYMBOL_LENGTH
|
||||
/* This is the maximum symbol size that won't require malloc/free */
|
||||
#define LTDL_SYMBOL_LENGTH 256
|
||||
#define LTDL_SYMBOL_LENGTH 128
|
||||
|
||||
#undef LTDL_SYMBOL_OVERHEAD
|
||||
/* This accounts for the _LTX_ separator and the string terminator */
|
||||
@ -662,7 +658,8 @@ presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit,
|
||||
#undef LTDL_TYPE_TOP
|
||||
#define LTDL_TYPE_TOP &presym
|
||||
|
||||
static char usr_search_path[LTDL_SEARCHPATH_MAX];
|
||||
static char *usr_search_path;
|
||||
static int usr_search_path_size = 0;
|
||||
static lt_dlhandle handles = 0;
|
||||
static int initialized = 0;
|
||||
|
||||
@ -681,7 +678,9 @@ lt_dlinit ()
|
||||
return 0;
|
||||
}
|
||||
handles = 0;
|
||||
usr_search_path[0] = '\0'; /* empty search path */
|
||||
if (usr_search_path)
|
||||
free(usr_search_path);
|
||||
usr_search_path = 0; /* empty search path */
|
||||
|
||||
while (*type) {
|
||||
if ((*type)->mod_init())
|
||||
@ -756,22 +755,6 @@ lt_dlexit ()
|
||||
return errors;
|
||||
}
|
||||
|
||||
static int /* not all compilers support void */
|
||||
trim (dest, s)
|
||||
char *dest;
|
||||
const char *s;
|
||||
{
|
||||
char *i = strrchr(s, '\'');
|
||||
int len = strlen(s);
|
||||
|
||||
if (len > 3 && s[0] == '\'') {
|
||||
strncpy(dest, &s[1], (i - s) - 1);
|
||||
dest[len-3] = '\0';
|
||||
} else
|
||||
*dest = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tryall_dlopen (handle, filename)
|
||||
lt_dlhandle *handle;
|
||||
@ -816,116 +799,140 @@ find_module (handle, dir, dlname, old_name)
|
||||
const char *dlname;
|
||||
const char *old_name;
|
||||
{
|
||||
char filename[LTDL_FILENAME_MAX];
|
||||
|
||||
/* search for old library first; if it was dlpreopened, we
|
||||
want the preopened version of it, even if a dlopenable
|
||||
module is available */
|
||||
if (*old_name && tryall_dlopen(handle, old_name) == 0)
|
||||
if (old_name && tryall_dlopen(handle, old_name) == 0)
|
||||
return 0;
|
||||
|
||||
/* search a module */
|
||||
if (*dlname) {
|
||||
/* hmm, maybe it was moved to another directory */
|
||||
if (strlen(dir)+1+strlen(dlname) < LTDL_FILENAME_MAX) {
|
||||
strcpy(filename, dir);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, dlname);
|
||||
if (tryall_dlopen(handle, filename) == 0)
|
||||
return 0;
|
||||
if (dlname) {
|
||||
char *filename = malloc(strlen(dir)+1+strlen(dlname)+1);
|
||||
|
||||
if (!filename) {
|
||||
last_error = memory_error;
|
||||
return 1;
|
||||
}
|
||||
strcpy(filename, dir);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, dlname);
|
||||
if (tryall_dlopen(handle, filename) == 0) {
|
||||
free(filename);
|
||||
return 0;
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
last_error = file_not_found_error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef LTDL_CHECK_SIZE
|
||||
#define LTDL_CHECK_SIZE(buf_, size_, need_, ret) do { \
|
||||
char **pbuf = &buf_; int *psize = &size_, need = need_; \
|
||||
if (need > *psize) { \
|
||||
if (*pbuf) \
|
||||
free(*pbuf); \
|
||||
*pbuf = malloc(need); \
|
||||
if (!*pbuf) { \
|
||||
last_error = memory_error; \
|
||||
return ret; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static int
|
||||
find_library (handle, basename, search_path)
|
||||
lt_dlhandle *handle;
|
||||
const char *basename;
|
||||
const char *search_path;
|
||||
{
|
||||
char filename[LTDL_FILENAME_MAX];
|
||||
char *filename = 0;
|
||||
int size = 0;
|
||||
const char *cur, *next;
|
||||
int baselen;
|
||||
|
||||
if (!search_path || !strlen(search_path)) {
|
||||
last_error = file_not_found_error;
|
||||
return 1;
|
||||
}
|
||||
cur = search_path;
|
||||
baselen = strlen(basename);
|
||||
while (cur) {
|
||||
int lendir;
|
||||
next = strchr(cur, ':');
|
||||
if (next) {
|
||||
if (next - cur + 1 >= LTDL_FILENAME_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
return 1;
|
||||
}
|
||||
strncpy(filename, cur, next - cur);
|
||||
filename[next - cur] = '\0';
|
||||
cur = next+1;
|
||||
} else {
|
||||
if (strlen(cur)+1 >= LTDL_FILENAME_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
return 1;
|
||||
}
|
||||
strcpy(filename, cur);
|
||||
cur = 0;
|
||||
}
|
||||
if (!*filename)
|
||||
if (next)
|
||||
lendir = next-cur;
|
||||
else
|
||||
lendir = strlen(cur);
|
||||
if (lendir == 0)
|
||||
continue;
|
||||
strcat(filename, "/");
|
||||
if (strlen(filename)+strlen(basename) < LTDL_FILENAME_MAX) {
|
||||
strcat(filename, basename);
|
||||
if (tryall_dlopen(handle, filename) == 0)
|
||||
return 0;
|
||||
LTDL_CHECK_SIZE(filename, size, \
|
||||
lendir + 1 + baselen + 1, 1);
|
||||
strncpy(filename, cur, lendir);
|
||||
if (next)
|
||||
cur = next+1;
|
||||
else
|
||||
cur = 0;
|
||||
filename[lendir] = '/';
|
||||
strncpy(filename+lendir+1, basename, baselen+1);
|
||||
if (tryall_dlopen(handle, filename) == 0) {
|
||||
free(filename);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
last_error = file_not_found_error;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static FILE *
|
||||
find_file (basename, search_path)
|
||||
find_file (basename, search_path, pdir)
|
||||
const char *basename;
|
||||
const char *search_path;
|
||||
const char **pdir;
|
||||
{
|
||||
char filename[LTDL_FILENAME_MAX];
|
||||
char *filename = 0;
|
||||
int size = 0;
|
||||
const char *cur, *next;
|
||||
FILE *file;
|
||||
|
||||
int baselen;
|
||||
int overhead;
|
||||
|
||||
if (!search_path || !strlen(search_path)) {
|
||||
last_error = file_not_found_error;
|
||||
return 0;
|
||||
}
|
||||
cur = search_path;
|
||||
baselen = strlen(basename);
|
||||
overhead = strlen(LTDL_OBJDIR)+1;
|
||||
if (baselen > overhead)
|
||||
overhead = baselen;
|
||||
while (cur) {
|
||||
int lendir;
|
||||
next = strchr(cur, ':');
|
||||
if (next) {
|
||||
if (next - cur + 1 >= LTDL_FILENAME_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
return 0;
|
||||
}
|
||||
strncpy(filename, cur, next - cur);
|
||||
filename[next - cur] = '\0';
|
||||
cur = next+1;
|
||||
} else {
|
||||
if (strlen(cur)+1 >= LTDL_FILENAME_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
return 0;
|
||||
}
|
||||
strcpy(filename, cur);
|
||||
cur = 0;
|
||||
}
|
||||
if (!*filename)
|
||||
if (next)
|
||||
lendir = next-cur;
|
||||
else
|
||||
lendir = strlen(cur);
|
||||
if (lendir == 0)
|
||||
continue;
|
||||
strcat(filename, "/");
|
||||
if (strlen(filename)+strlen(basename) < LTDL_FILENAME_MAX) {
|
||||
strcat(filename, basename);
|
||||
file = fopen(filename, LTDL_READTEXT_MODE);
|
||||
if (file)
|
||||
return file;
|
||||
LTDL_CHECK_SIZE(filename, size, \
|
||||
lendir + 1 + overhead + 1, 0);
|
||||
strncpy(filename, cur, lendir);
|
||||
if (next)
|
||||
cur = next+1;
|
||||
else
|
||||
cur = 0;
|
||||
filename[lendir] = '/';
|
||||
strncpy(filename+lendir+1, basename, baselen+1);
|
||||
file = fopen(filename, LTDL_READTEXT_MODE);
|
||||
if (file) {
|
||||
filename[lendir+1] = '\0';
|
||||
*pdir = filename;
|
||||
return file;
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
last_error = file_not_found_error;
|
||||
return 0;
|
||||
}
|
||||
@ -949,38 +956,53 @@ unload_deplibs(handle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef LTDL_TRIM
|
||||
#define LTDL_TRIM(dest_, s_) do { \
|
||||
char **dest = &(dest_); \
|
||||
char *s = (s_); \
|
||||
int len = strlen(s); \
|
||||
\
|
||||
if (*dest) \
|
||||
free(*dest); \
|
||||
*dest = 0; \
|
||||
\
|
||||
if (len > 3 && s[0] == '\'' \
|
||||
&& s[len-1] == '\n' && s[len-2] == '\'') { \
|
||||
*dest = malloc(len-2); \
|
||||
if (!*dest) \
|
||||
goto trim_raise_memory_error; \
|
||||
strncpy(*dest, &s[1], len - 3); \
|
||||
(*dest)[len-3] = '\0'; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
lt_dlhandle
|
||||
lt_dlopen (filename)
|
||||
const char *filename;
|
||||
{
|
||||
lt_dlhandle handle;
|
||||
char dir[LTDL_FILENAME_MAX];
|
||||
const char *basename, *ext, *search_path;
|
||||
#ifdef LTDL_SHLIBPATH_VAR
|
||||
const char *sys_search_path;
|
||||
#endif
|
||||
lt_dlhandle handle = 0;
|
||||
char *dir = 0;
|
||||
const char *basename, *ext;
|
||||
const char *saved_error = last_error;
|
||||
|
||||
basename = strrchr(filename, '/');
|
||||
if (basename)
|
||||
if (basename) {
|
||||
basename++;
|
||||
else
|
||||
dir = malloc(basename - filename + strlen(LTDL_OBJDIR) + 1);
|
||||
if (!dir) {
|
||||
last_error = memory_error;
|
||||
return 0;
|
||||
}
|
||||
strncpy(dir, filename, basename-filename);
|
||||
dir[basename-filename] = '\0';
|
||||
} else
|
||||
basename = filename;
|
||||
if (basename - filename >= LTDL_FILENAME_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
return 0;
|
||||
}
|
||||
strncpy(dir, filename, basename - filename);
|
||||
dir[basename - filename] = '\0';
|
||||
search_path = getenv("LTDL_LIBRARY_PATH"); /* get the search path */
|
||||
#ifdef LTDL_SHLIBPATH_VAR
|
||||
sys_search_path = getenv(LTDL_SHLIBPATH_VAR);
|
||||
#endif
|
||||
|
||||
/* check whether we open a libtool module (.la extension) */
|
||||
ext = strrchr(basename, '.');
|
||||
if (ext && strcmp(ext, ".la") == 0) {
|
||||
char dlname[LTDL_FILENAME_MAX], old_name[LTDL_FILENAME_MAX];
|
||||
char libdir[LTDL_FILENAME_MAX], deplibs[LTDL_FILENAME_MAX];
|
||||
char *dlname = 0, *old_name = 0;
|
||||
char *libdir = 0, *deplibs = 0;
|
||||
char tmp[LTDL_FILENAME_MAX];
|
||||
char *name;
|
||||
FILE *file;
|
||||
@ -990,10 +1012,8 @@ lt_dlopen (filename)
|
||||
of libtool */
|
||||
int installed=1;
|
||||
|
||||
dlname[0] = old_name[0] = libdir[0] = deplibs[0] = '\0';
|
||||
|
||||
/* extract the module name from the file name */
|
||||
if (strlen(basename) >= LTDL_FILENAME_MAX) {
|
||||
if (strlen(basename) >= sizeof(tmp)) {
|
||||
last_error = buffer_overflow_error;
|
||||
return 0;
|
||||
}
|
||||
@ -1009,96 +1029,119 @@ lt_dlopen (filename)
|
||||
return 0;
|
||||
}
|
||||
file = fopen(filename, LTDL_READTEXT_MODE);
|
||||
if (!file && !*dir) {
|
||||
if (!file && !dir) {
|
||||
/* try other directories */
|
||||
file = find_file(basename, usr_search_path);
|
||||
file = find_file(basename, usr_search_path, &dir);
|
||||
if (!file)
|
||||
file = find_file(basename, search_path);
|
||||
file = find_file(basename,
|
||||
getenv("LTDL_LIBRARY_PATH"),
|
||||
&dir);
|
||||
#ifdef LTDL_SHLIBPATH_VAR
|
||||
if (!file)
|
||||
file = find_file(basename, sys_search_path);
|
||||
file = find_file(basename,
|
||||
getenv(LTDL_SHLIBPATH_VAR),
|
||||
&dir);
|
||||
#endif
|
||||
}
|
||||
if (!file) {
|
||||
clean_up_name:
|
||||
free(name);
|
||||
return 0;
|
||||
goto clean_up_dir;
|
||||
}
|
||||
while (!feof(file)) {
|
||||
if (!fgets(tmp, LTDL_FILENAME_MAX, file))
|
||||
if (!fgets(tmp, sizeof(tmp), file))
|
||||
break;
|
||||
if (tmp[0] == '\n' || tmp[0] == '#')
|
||||
;
|
||||
else
|
||||
if (strncmp(tmp, "dlname=", 7) == 0)
|
||||
trim(dlname, &tmp[7]);
|
||||
LTDL_TRIM(dlname, &tmp[7]);
|
||||
else
|
||||
if (strncmp(tmp, "old_library=", 12) == 0)
|
||||
trim(old_name, &tmp[12]);
|
||||
LTDL_TRIM(old_name, &tmp[12]);
|
||||
else
|
||||
if (strncmp(tmp, "libdir=", 7) == 0)
|
||||
trim(libdir, &tmp[7]);
|
||||
LTDL_TRIM(libdir, &tmp[7]);
|
||||
else
|
||||
if (strncmp(tmp, "dl_dependency_libs=", 20) == 0)
|
||||
trim(deplibs, &tmp[20]);
|
||||
LTDL_TRIM(deplibs, &tmp[20]);
|
||||
else
|
||||
if (strcmp(tmp, "installed=yes\n") == 0)
|
||||
installed = 1;
|
||||
else
|
||||
if (strcmp(tmp, "installed=no\n") == 0)
|
||||
installed = 0;
|
||||
else
|
||||
if (0) {
|
||||
trim_raise_memory_error:
|
||||
fclose(file);
|
||||
goto handle_raise_memory_error;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
|
||||
if (!handle) {
|
||||
handle_raise_memory_error:
|
||||
last_error = memory_error;
|
||||
free(name);
|
||||
return 0;
|
||||
goto clean_up_vars;
|
||||
}
|
||||
if (load_deplibs(handle, deplibs)) {
|
||||
if (deplibs && load_deplibs(handle, deplibs)) {
|
||||
clean_up_handle:
|
||||
free(handle);
|
||||
free(name);
|
||||
return 0;
|
||||
handle = 0;
|
||||
goto clean_up_vars;
|
||||
}
|
||||
if (installed) {
|
||||
if (find_module(&handle, libdir, dlname, old_name)) {
|
||||
clean_up_deplibs:
|
||||
unload_deplibs(handle);
|
||||
free(handle);
|
||||
free(name);
|
||||
return 0;
|
||||
goto clean_up_handle;
|
||||
}
|
||||
} else {
|
||||
if (strlen(dir) + strlen(LTDL_OBJDIR)
|
||||
>= LTDL_FILENAME_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
unload_deplibs(handle);
|
||||
free(handle);
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
strcat(dir, LTDL_OBJDIR);
|
||||
if (find_module(&handle, dir, dlname, old_name)) {
|
||||
unload_deplibs(handle);
|
||||
free(handle);
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
/* We dir is non-NULL, it has enough space for
|
||||
LTDL_OBJDIR: it was reserved in the
|
||||
beginning of the function or within
|
||||
find_file */
|
||||
if (dir)
|
||||
strcat(dir, LTDL_OBJDIR);
|
||||
if (find_module(&handle,
|
||||
dir ? dir : LTDL_OBJDIR,
|
||||
dlname, old_name))
|
||||
goto clean_up_deplibs;
|
||||
}
|
||||
handle->name = name;
|
||||
clean_up_vars:
|
||||
if (dlname)
|
||||
free(dlname);
|
||||
if (old_name)
|
||||
free(old_name);
|
||||
if (libdir)
|
||||
free(libdir);
|
||||
if (deplibs)
|
||||
free(deplibs);
|
||||
if (!handle)
|
||||
goto clean_up_name;
|
||||
} else {
|
||||
/* not a libtool module */
|
||||
handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
|
||||
if (!handle) {
|
||||
last_error = memory_error;
|
||||
return 0;
|
||||
goto clean_up_dir;
|
||||
}
|
||||
if (tryall_dlopen(&handle, filename)
|
||||
&& (*dir
|
||||
&& (dir
|
||||
|| (find_library(&handle, basename, usr_search_path)
|
||||
&& find_library(&handle, basename, search_path)
|
||||
&& find_library(&handle, basename,
|
||||
getenv("LTDL_LIBRARY_PATH"))
|
||||
#ifdef LTDL_SHLIBPATH_VAR
|
||||
&& find_library(&handle, basename, sys_search_path)
|
||||
&& find_library(&handle, basename,
|
||||
getenv(LTDL_SHLIBPATH_VAR))
|
||||
#endif
|
||||
))) {
|
||||
free(handle);
|
||||
return 0;
|
||||
handle = 0;
|
||||
goto clean_up_dir;
|
||||
}
|
||||
handle->name = 0;
|
||||
}
|
||||
@ -1106,6 +1149,9 @@ lt_dlopen (filename)
|
||||
handle->next = handles;
|
||||
handles = handle;
|
||||
last_error = saved_error;
|
||||
clean_up_dir:
|
||||
if (dir)
|
||||
free(dir);
|
||||
return handle;
|
||||
}
|
||||
|
||||
@ -1218,19 +1264,33 @@ lt_dladdsearchdir (search_dir)
|
||||
const char *search_dir;
|
||||
{
|
||||
if (!search_dir) {
|
||||
usr_search_path[0] = '\0'; /* reset the search path */
|
||||
if (usr_search_path)
|
||||
free(usr_search_path);
|
||||
usr_search_path = 0; /* reset the search path */
|
||||
return 0;
|
||||
}
|
||||
if (!strlen(search_dir))
|
||||
return 0;
|
||||
if (strlen(usr_search_path) + strlen(search_dir) + 1
|
||||
>= LTDL_SEARCHPATH_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
return 1;
|
||||
}
|
||||
if (usr_search_path[0] != '\0')
|
||||
if (!usr_search_path) {
|
||||
usr_search_path_size = strlen(search_dir)+1;
|
||||
usr_search_path = malloc(usr_search_path_size);
|
||||
if (!usr_search_path) {
|
||||
last_error = memory_error;
|
||||
return 1;
|
||||
}
|
||||
strcpy(usr_search_path, search_dir);
|
||||
} else {
|
||||
int new_size = usr_search_path_size + strlen(search_dir) + 1;
|
||||
char *new_search_path = realloc(usr_search_path, new_size);
|
||||
if (!new_search_path) {
|
||||
last_error = memory_error;
|
||||
return 1;
|
||||
}
|
||||
usr_search_path = new_search_path;
|
||||
usr_search_path_size = new_size;
|
||||
strcat(usr_search_path, ":");
|
||||
strcat(usr_search_path, search_dir);
|
||||
strcat(usr_search_path, search_dir);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1238,17 +1298,17 @@ int
|
||||
lt_dlsetsearchpath (search_path)
|
||||
const char *search_path;
|
||||
{
|
||||
if (!search_path) {
|
||||
usr_search_path[0] = '\0'; /* reset the search path */
|
||||
if (usr_search_path)
|
||||
free(usr_search_path);
|
||||
usr_search_path = 0; /* reset the search path */
|
||||
if (!search_path || !strlen(search_path)) {
|
||||
return 0;
|
||||
}
|
||||
if (!strlen(search_path))
|
||||
return 0;
|
||||
if (strlen(search_path) >= LTDL_SEARCHPATH_MAX) {
|
||||
last_error = buffer_overflow_error;
|
||||
usr_search_path = strdup(search_path);
|
||||
if (usr_search_path)
|
||||
usr_search_path_size = strlen(usr_search_path)+1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
strcpy(usr_search_path, search_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user