From: Gary V. Vaughan Date: Tue, 26 Jun 2001 00:50:39 +0000 (+0000) Subject: * ltdl.m4: Bump serial number to 3. X-Git-Tag: release-1-4b~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c7f7fe214c9931ec9a7bb40587923d3d3c094d1;p=thirdparty%2Flibtool.git * ltdl.m4: Bump serial number to 3. (AC_LIB_LTDL): Require AC_HEADER_DIRENT for ltdl.c. * libltdl/ltdl.h (lt_dlforeachfile): Prototype for new function. * libltdl/ltdl.c: Include an appropriate header for the opendir/dirent api. (foreach_dirinpath): Visit each file in a list of directories. (find_file_callback): Factor out the core of find_file() to make use of foreach_dirinpath(). (find_file): Use it! (find_handle_callback, find_handle): Ditto. (lt_dlforeachfile): New function to find files in a searchpath.,, (foreachfile_callback): ...using this callback. * doc/libtool.texi (Libltdl interface): Document new lt_dlforeachfile api call. --- diff --git a/ChangeLog b/ChangeLog index f325c68f4..faf15e47e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2001-06-26 Gary V. Vaughan + + * ltdl.m4: Bump serial number to 3. + (AC_LIB_LTDL): Require AC_HEADER_DIRENT for ltdl.c. + * libltdl/ltdl.h (lt_dlforeachfile): Prototype for new function. + * libltdl/ltdl.c: Include an appropriate header for the + opendir/dirent api. + (foreach_dirinpath): Visit each file in a list of directories. + (find_file_callback): Factor out the core of find_file() to make + use of foreach_dirinpath(). + (find_file): Use it! + (find_handle_callback, find_handle): Ditto. + (lt_dlforeachfile): New function to find files in a searchpath.,, + (foreachfile_callback): ...using this callback. + * doc/libtool.texi (Libltdl interface): Document new + lt_dlforeachfile api call. + 2001-06-25 Gary V. Vaughan * THANKS: Aded Albert Chin-A-Young. diff --git a/doc/libtool.texi b/doc/libtool.texi index 5a252dc26..0ac9c65f9 100644 --- a/doc/libtool.texi +++ b/doc/libtool.texi @@ -2841,6 +2841,25 @@ directories. Return 0 on success. Return the current user-defined library search path. @end deftypefun +@deftypefun int lt_dlforeachfile (@w{const char *@var{search_path}}, @w{int (*@var{func}) (const char *@var{filename}, lt_ptr @var{data})}, @w{lt_ptr @var{data}}) +In some applications you may not want to load individual modules with +known names, but rather find all of the modules in a set of +directories and load them all during initialisation. With this function +you can have libltdl scan the colon delimited directory list in +@var{search_path} for candidates, and pass them, along with @var{data} +to your own callback function, @var{func}. If @var{seach_path} is +@samp{NULL}, then search all of the standard locations that +@code{lt_dlopen} would examine. This function will continue to make +calls to @var{func} for each file that it discovers in @var{search_path} +until one of these calls returns non-zero, or until the files are +exhausted. @samp{lt_dlforeachfile} returns value returned by the last +call made to @var{func}. + +For example you could define @var{func} to build an ordered +@dfn{argv}-like vector of files using @var{data} to hold the address of +the start of the vector. +@end deftypefun + @deftypefun int lt_dlmakeresident (lt_dlhandle @var{handle}) Mark a module so that it cannot be @samp{lt_dlclose}d. This can be useful if a module implements some core functionality in your project, diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c index 872a5701d..7cb048406 100644 --- a/libltdl/ltdl.c +++ b/libltdl/ltdl.c @@ -57,6 +57,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # include #endif +#if HAVE_DIRENT_H +# include +# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) +#else +# define dirent direct +# define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + #include "ltdl.h" @@ -1262,6 +1279,10 @@ static struct lt_user_dlloader presym = { /* --- DYNAMIC MODULE LOADING --- */ +/* The type of a function used at each iteration of foreach_dirinpath(). */ +typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, + lt_ptr data2)); + static char *user_search_path= 0; static lt_dlloader *loaders = 0; static lt_dlhandle handles = 0; @@ -1616,7 +1637,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed) return 1; } -static char* +static char * canonicalize_path (path) const char *path; { @@ -1639,22 +1660,23 @@ canonicalize_path (path) return canonical; } -static lt_ptr -find_file (basename, search_path, pdir, handle) - const char *basename; +/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element + of SEARCH_PATH and a copy of DATA, until FUNC returns non-zero or + all elements are exhausted. If BASE_NAME is non-NULL, it is appended + to each SEARCH_PATH element (with a separating '/' added if + necessary) before FUNC is called. */ +static int +foreach_dirinpath (search_path, base_name, func, data1, data2) const char *search_path; - char **pdir; - lt_dlhandle *handle; + const char *base_name; + foreach_callback_func *func; + lt_ptr data1; + lt_ptr data2; { - /* When handle != NULL search a library, otherwise a file - return NULL on failure, otherwise the file/handle. */ - - lt_ptr result = 0; - char *filename = 0; - int filenamesize= 0; - int lenbase = strlen (basename); - char *canonical = 0; - char *next = 0; + int result = 0; + int filenamesize = 0; + int lenbase = base_name ? strlen (base_name) : 0; + char *filename, *canonical, *next; MUTEX_LOCK (); @@ -1674,35 +1696,27 @@ find_file (basename, search_path, pdir, handle) next = canonical; while (next) { - int lendir; - char *cur = next; + char *cur = next; + int lendir; next = strchr (cur, LT_PATHSEP_CHAR); if (!next) - { - next = cur + strlen (cur); - } + next = cur + strlen (cur); lendir = next - cur; if (*next == LT_PATHSEP_CHAR) - { - ++next; - } + ++next; else - { - next = 0; - } + next = 0; if (lendir == 0) - { - continue; - } + continue; - if (lendir + 1 + lenbase >= filenamesize) + if (lendir +1 +lenbase >= filenamesize) { LT_DLFREE (filename); - filenamesize = lendir + 1 + lenbase + 1; - filename = LT_DLMALLOC (char, filenamesize); + filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ + filename = LT_DLMALLOC (char, filenamesize); if (!filename) { @@ -1711,56 +1725,108 @@ find_file (basename, search_path, pdir, handle) } } - strncpy(filename, cur, lendir); - if (filename[lendir-1] != '/') - { - filename[lendir++] = '/'; - } - strcpy(filename+lendir, basename); - if (handle) + strncpy (filename, cur, lendir); + if (filename[lendir -1] != '/') + filename[lendir++] = '/'; + if (base_name && *base_name) + strcpy (filename +lendir, base_name); + + if ((result = (*func) (filename, data1, data2))) { - if (tryall_dlopen (handle, filename) == 0) - { - result = (lt_ptr) handle; - goto cleanup; - } + break; } - else - { - FILE *file = fopen (filename, LT_READTEXT_MODE); - if (file) - { - LT_DLFREE (*pdir); + } - filename[lendir] = '\0'; - *pdir = strdup(filename); - if (!*pdir) - { - /* We could have even avoided the strdup, - but there would be some memory overhead. */ - *pdir = filename; - filename = 0; - } + cleanup: + LT_DLFREE (canonical); + LT_DLFREE (filename); - result = (lt_ptr) file; - goto cleanup; - } + MUTEX_UNLOCK (); + + return result; +} + +/* If FILEPATH can be opened, store the name of the directory component + in DATA1, and the opened FILE* structure address in DATA2. Otherwise + DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ +static int +find_file_callback (filename, data1, data2) + char *filename; + lt_ptr data1; + lt_ptr data2; +{ + char **pdir = (char **) data1; + FILE **pfile = (FILE **) data2; + int is_done = 0; + + *pfile = fopen (filename, LT_READTEXT_MODE); + + if (*pfile) + { + char *dirend = strrchr (filename, '/'); + + LT_DLFREE (*pdir); + *dirend = '\0'; + *pdir = strdup (filename); + if (!*pdir) + { + /* We could have even avoided the strdup, + but there would be some memory overhead. */ + *pdir = filename; + filename = 0; /* prevent the foreach function from freeing */ } + is_done = 1; + } + else + { + MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); } - MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); + return is_done; +} - cleanup: - LT_DLFREE (filename); - LT_DLFREE (canonical); +static FILE * +find_file (search_path, base_name, pdir) + const char *search_path; + const char *base_name; + char **pdir; +{ + FILE *file = 0; - MUTEX_UNLOCK (); + foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); - return result; + return file; +} + +static int +find_handle_callback (filename, data, ignored) + char *filename; + lt_ptr data; + lt_ptr ignored; +{ + lt_dlhandle *handle = (lt_dlhandle *) data; + int is_done = 0; + + if (tryall_dlopen (handle, filename) == 0) + { + is_done = 1; + } + + return is_done; +} + +static lt_dlhandle * +find_handle (search_path, base_name, handle) + const char *search_path; + const char *base_name; + lt_dlhandle *handle; +{ + foreach_dirinpath (search_path, base_name, find_handle_callback, handle, 0); + return handle; } static int -load_deplibs(handle, deplibs) +load_deplibs (handle, deplibs) lt_dlhandle handle; char *deplibs; { @@ -1933,7 +1999,7 @@ load_deplibs(handle, deplibs) } static int -unload_deplibs(handle) +unload_deplibs (handle) lt_dlhandle handle; { int i; @@ -2009,7 +2075,7 @@ lt_dlopen (filename) lt_dlhandle handle = 0, newhandle; const char *ext; const char *saved_error; - char *canonical = 0, *basename = 0, *dir = 0, *name = 0; + char *canonical = 0, *base_name = 0, *dir = 0, *name = 0; MUTEX_GETERROR (saved_error); @@ -2050,11 +2116,11 @@ lt_dlopen (filename) /* If the canonical module name is a path (relative or absolute) then split it into a directory part and a name part. */ - basename = strrchr (canonical, '/'); - if (basename) + base_name = strrchr (canonical, '/'); + if (base_name) { - ++basename; - dir = LT_DLMALLOC (char, basename - canonical + 1); + ++base_name; + dir = LT_DLMALLOC (char, base_name - canonical + 1); if (!dir) { MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); @@ -2062,16 +2128,16 @@ lt_dlopen (filename) goto cleanup; } - strncpy (dir, canonical, basename - canonical); - dir[basename - canonical] = '\0'; + strncpy (dir, canonical, base_name - canonical); + dir[base_name - canonical] = '\0'; } else { - basename = canonical; + base_name = canonical; } /* Check whether we are opening a libtool module (.la extension). */ - ext = strrchr(basename, '.'); + ext = strrchr(base_name, '.'); if (ext && strcmp(ext, ".la") == 0) { /* this seems to be a libtool module */ @@ -2089,7 +2155,7 @@ lt_dlopen (filename) int installed = 1; /* extract the module name from the file name */ - name = LT_DLMALLOC (char, ext - basename + 1); + name = LT_DLMALLOC (char, ext - base_name + 1); if (!name) { MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); @@ -2098,11 +2164,11 @@ lt_dlopen (filename) } /* canonicalize the module name */ - for (i = 0; i < ext - basename; ++i) + for (i = 0; i < ext - base_name; ++i) { - if (isalnum ((int)(basename[i]))) + if (isalnum ((int)(base_name[i]))) { - name[i] = basename[i]; + name[i] = base_name[i]; } else { @@ -2110,7 +2176,7 @@ lt_dlopen (filename) } } - name[ext - basename] = '\0'; + name[ext - base_name] = '\0'; /* Now try to open the .la file. If there is no directory name component, try to find it first in user_search_path and then other @@ -2118,24 +2184,22 @@ lt_dlopen (filename) yet found) try opening just the module name as passed. */ if (!dir) { - file = (FILE*) find_file(basename, user_search_path, &dir, 0); + file = find_file (user_search_path, base_name, &dir); if (!file) { - file = (FILE*) find_file(basename, getenv("LTDL_LIBRARY_PATH"), - &dir, 0); + file = find_file (getenv("LTDL_LIBRARY_PATH"), base_name, &dir); } #ifdef LTDL_SHLIBPATH_VAR if (!file) { - file = (FILE*) find_file(basename, getenv(LTDL_SHLIBPATH_VAR), - &dir, 0); + file = find_file (getenv(LTDL_SHLIBPATH_VAR), base_name, &dir); } #endif #ifdef LTDL_SYSSEARCHPATH if (!file) { - file = (FILE*) find_file(basename, sys_search_path, &dir, 0); + file = find_file (sys_search_path, base_name, &dir); } #endif } @@ -2314,15 +2378,15 @@ lt_dlopen (filename) first in user_search_path and then other prescribed paths. Otherwise (or in any case if the module was not yet found) try opening just the module name as passed. */ - if ((dir || (!find_file (basename, user_search_path, 0, &newhandle) - && !find_file (basename, getenv ("LTDL_LIBRARY_PATH"), - 0, &newhandle) + if ((dir || (!find_handle (user_search_path, base_name, &newhandle) + && !find_handle (getenv ("LTDL_LIBRARY_PATH"), base_name, + &newhandle) #ifdef LTDL_SHLIBPATH_VAR - && !find_file (basename, getenv (LTDL_SHLIBPATH_VAR), - 0, &newhandle) + && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, + &newhandle) #endif #ifdef LTDL_SYSSEARCHPATH - && !find_file (basename, sys_search_path, 0, &newhandle) + && !find_handle (sys_search_path, base_name, &newhandle) #endif )) && tryall_dlopen (&newhandle, filename)) { @@ -2437,6 +2501,120 @@ lt_dlopenext (filename) return 0; } +/* If there are any files in DIRNAME, try to load them as modules, and if + successful call the verify function passed as DATA1 (with the loaded + module handle and DATA2 as arguments). If that function returns + non-zero, then unload that module, otherwise leave it loaded. */ +static int +foreachfile_callback (dirname, data1, data2) + char *dirname; + lt_ptr data1; + lt_ptr data2; +{ + int (*func) LT_PARAMS((const char *filename, lt_ptr data2)) + = (int (*) LT_PARAMS((const char *filename, lt_ptr data2))) data1; + + char *filename = 0; + int filenamesize = 0; + int lendir = strlen (dirname); + DIR *dirp = opendir (dirname); + struct dirent *direntp; + + if (!dirp) + return 0; + + MUTEX_LOCK (); + + rewinddir (dirp); + while ((direntp = readdir (dirp))) + { + /* Don't try to use `.' or `..' as useful filenames. */ + if ((direntp->d_name[0] == '.') + && (((direntp->d_name[1] == '.') && (direntp->d_name[2] == '\0')) + || (direntp->d_name[1] == '\0'))) + { + continue; + } + + if (lendir +1 +LT_D_NAMLEN(direntp) >= filenamesize) + { + LT_DLFREE (filename); + filenamesize = lendir +1 + LT_D_NAMLEN(direntp) +1; + filename = LT_DLMALLOC (char, filenamesize); + + if (!filename) + { + MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); + goto cleanup; + } + } + + strcpy (filename, dirname); + if (filename[lendir -1] != '/') + filename[lendir++] = '/'; + strcpy (filename +lendir, direntp->d_name); + + /* Call the user function for this FILENAME. */ + if ((*func) (filename, data2)) + { + break; + } + } + + cleanup: + LT_DLFREE (filename); + closedir (dirp); + + MUTEX_UNLOCK (); + + return 0; +} + +int +lt_dlforeachfile (search_path, func, data) + const char *search_path; + int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); + lt_ptr data; +{ + int is_done = 0; + + if (search_path) + { + /* If a specific path was passed, search only the directories + listed in it. */ + is_done = foreach_dirinpath (search_path, 0, + foreachfile_callback, func, data); + } + else + { + /* Otherwise search the default paths. */ + is_done = foreach_dirinpath (user_search_path, 0, + foreachfile_callback, func, data); + if (!is_done) + { + is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, + foreachfile_callback, func, data); + } + +#ifdef LTDL_SHLIBPATH_VAR + if (!is_done) + { + is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, + foreachfile_callback, func, data); + } +#endif +#ifdef LTDL_SYSSEARCHPATH + if (!is_done) + { + is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, + foreachfile_callback, func, data); + } +#endif + } + + return is_done; +} + int lt_dlclose (handle) lt_dlhandle handle; diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h index 28606c114..1ec0d1a0b 100644 --- a/libltdl/ltdl.h +++ b/libltdl/ltdl.h @@ -146,10 +146,14 @@ typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ extern int lt_dlinit LT_PARAMS((void)); extern int lt_dlexit LT_PARAMS((void)); -/* Module search path manipultation. */ +/* Module search path manipulation. */ extern int lt_dladdsearchdir LT_PARAMS((const char *search_dir)); extern int lt_dlsetsearchpath LT_PARAMS((const char *search_path)); extern const char *lt_dlgetsearchpath LT_PARAMS((void)); +extern int lt_dlforeachfile LT_PARAMS(( + const char *search_path, + int (*func) (const char *filename, lt_ptr data), + lt_ptr data)); /* Portable libltdl versions of the system dlopen() API. */ extern lt_dlhandle lt_dlopen LT_PARAMS((const char *filename)); @@ -275,8 +279,8 @@ extern lt_dlloader *lt_dlloader_find LT_PARAMS(( extern const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place)); extern lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place)); extern int lt_dlloader_add LT_PARAMS((lt_dlloader *place, - const struct lt_user_dlloader *dlloader, - const char *loader_name)); + const struct lt_user_dlloader *dlloader, + const char *loader_name)); extern int lt_dlloader_remove LT_PARAMS(( const char *loader_name)); diff --git a/ltdl.m4 b/ltdl.m4 index d3ee60269..27bdb3d6a 100644 --- a/ltdl.m4 +++ b/ltdl.m4 @@ -20,7 +20,7 @@ ## configuration script generated by Autoconf, you may include it under ## the same distribution terms that you use for the rest of that program. -# serial 2 AC_LIB_LTDL +# serial 3 AC_LIB_LTDL # AC_LIB_LTDL # ----------- @@ -32,6 +32,7 @@ AC_REQUIRE([AC_C_CONST])dnl # Perform all the checks necessary for compilation of the ltdl objects # -- including compiler checks (above) and header checks (below). AC_REQUIRE([AC_HEADER_STDC])dnl +AC_REQUIRE([AC_HEADER_DIRENT])dnl AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl AC_CHECK_HEADERS(malloc.h memory.h stdlib.h stdio.h ctype.h dl.h sys/dl.h dld.h)