* 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:
Alexandre Oliva 1999-01-21 04:27:26 +00:00 committed by Alexandre Oliva
parent 81df2fb6e3
commit 24c33318ba
2 changed files with 224 additions and 160 deletions

View File

@ -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

View File

@ -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;
}