Annotation of sql/pgsql/libltdl/ltdl.c, revision 1.4
1.1 parser 1: /* ltdl.c -- system independent dlopen wrapper
2:
1.4 ! moko 3: Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
! 4: 2007, 2008, 2011 Free Software Foundation, Inc.
! 5: Written by Thomas Tanner, 1998
1.2 paf 6:
1.4 ! moko 7: NOTE: The canonical source of this file is maintained with the
! 8: GNU Libtool package. Report bugs to bug-libtool@gnu.org.
1.2 paf 9:
1.4 ! moko 10: GNU Libltdl is free software; you can redistribute it and/or
! 11: modify it under the terms of the GNU Lesser General Public
! 12: License as published by the Free Software Foundation; either
! 13: version 2 of the License, or (at your option) any later version.
1.2 paf 14:
1.4 ! moko 15: As a special exception to the GNU Lesser General Public License,
! 16: if you distribute this file as part of a program or library that
! 17: is built using GNU Libtool, you may include this file under the
! 18: same distribution terms that you use for the rest of that program.
1.2 paf 19:
1.4 ! moko 20: GNU Libltdl is distributed in the hope that it will be useful,
! 21: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 22: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 23: GNU Lesser General Public License for more details.
1.2 paf 24:
1.4 ! moko 25: You should have received a copy of the GNU Lesser General Public
! 26: License along with GNU Libltdl; see the file COPYING.LIB. If not, a
! 27: copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
! 28: or obtained by writing to the Free Software Foundation, Inc.,
! 29: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
! 30: */
1.2 paf 31:
1.4 ! moko 32: #include "lt__private.h"
! 33: #include "lt_system.h"
! 34: #include "lt_dlloader.h"
1.2 paf 35:
36:
1.4 ! moko 37: /* --- MANIFEST CONSTANTS --- */
1.2 paf 38:
39:
1.4 ! moko 40: /* Standard libltdl search path environment variable name */
! 41: #undef LTDL_SEARCHPATH_VAR
! 42: #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
1.2 paf 43:
1.4 ! moko 44: /* Standard libtool archive file extension. */
! 45: #undef LT_ARCHIVE_EXT
! 46: #define LT_ARCHIVE_EXT ".la"
1.2 paf 47:
1.4 ! moko 48: /* max. filename length */
! 49: #if !defined(LT_FILENAME_MAX)
! 50: # define LT_FILENAME_MAX 1024
! 51: #endif
1.2 paf 52:
1.4 ! moko 53: #if !defined(LT_LIBEXT)
! 54: # define LT_LIBEXT "a"
! 55: #endif
1.2 paf 56:
1.4 ! moko 57: #if !defined(LT_LIBPREFIX)
! 58: # define LT_LIBPREFIX "lib"
! 59: #endif
1.2 paf 60:
1.4 ! moko 61: /* This is the maximum symbol size that won't require malloc/free */
! 62: #undef LT_SYMBOL_LENGTH
! 63: #define LT_SYMBOL_LENGTH 128
1.2 paf 64:
1.4 ! moko 65: /* This accounts for the _LTX_ separator */
! 66: #undef LT_SYMBOL_OVERHEAD
! 67: #define LT_SYMBOL_OVERHEAD 5
1.2 paf 68:
1.4 ! moko 69: /* Various boolean flags can be stored in the flags field of an
! 70: lt_dlhandle... */
! 71: #define LT_DLIS_RESIDENT(handle) ((handle)->info.is_resident)
! 72: #define LT_DLIS_SYMGLOBAL(handle) ((handle)->info.is_symglobal)
! 73: #define LT_DLIS_SYMLOCAL(handle) ((handle)->info.is_symlocal)
! 74:
! 75:
! 76: static const char objdir[] = LT_OBJDIR;
! 77: static const char archive_ext[] = LT_ARCHIVE_EXT;
! 78: static const char libext[] = LT_LIBEXT;
! 79: static const char libprefix[] = LT_LIBPREFIX;
! 80: #if defined(LT_MODULE_EXT)
! 81: static const char shlib_ext[] = LT_MODULE_EXT;
! 82: #endif
! 83: /* If the loadable module suffix is not the same as the linkable
! 84: * shared library suffix, this will be defined. */
! 85: #if defined(LT_SHARED_EXT)
! 86: static const char shared_ext[] = LT_SHARED_EXT;
! 87: #endif
! 88: #if defined(LT_DLSEARCH_PATH)
! 89: static const char sys_dlsearch_path[] = LT_DLSEARCH_PATH;
! 90: #endif
1.2 paf 91:
92:
93:
94:
1.4 ! moko 95: /* --- DYNAMIC MODULE LOADING --- */
1.2 paf 96:
97:
1.4 ! moko 98: /* The type of a function used at each iteration of foreach_dirinpath(). */
! 99: typedef int foreach_callback_func (char *filename, void *data1,
! 100: void *data2);
! 101: /* foreachfile_callback itself calls a function of this type: */
! 102: typedef int file_worker_func (const char *filename, void *data);
! 103:
! 104:
! 105: static int foreach_dirinpath (const char *search_path,
! 106: const char *base_name,
! 107: foreach_callback_func *func,
! 108: void *data1, void *data2);
! 109: static int find_file_callback (char *filename, void *data1,
! 110: void *data2);
! 111: static int find_handle_callback (char *filename, void *data,
! 112: void *ignored);
! 113: static int foreachfile_callback (char *filename, void *data1,
! 114: void *data2);
! 115:
! 116:
! 117: static int canonicalize_path (const char *path, char **pcanonical);
! 118: static int argzize_path (const char *path,
! 119: char **pargz, size_t *pargz_len);
! 120: static FILE *find_file (const char *search_path,
! 121: const char *base_name, char **pdir);
! 122: static lt_dlhandle *find_handle (const char *search_path,
! 123: const char *base_name,
! 124: lt_dlhandle *handle,
! 125: lt_dladvise advise);
! 126: static int find_module (lt_dlhandle *handle, const char *dir,
! 127: const char *libdir, const char *dlname,
! 128: const char *old_name, int installed,
! 129: lt_dladvise advise);
! 130: static int has_library_ext (const char *filename);
! 131: static int load_deplibs (lt_dlhandle handle, char *deplibs);
! 132: static int trim (char **dest, const char *str);
! 133: static int try_dlopen (lt_dlhandle *handle,
! 134: const char *filename, const char *ext,
! 135: lt_dladvise advise);
! 136: static int tryall_dlopen (lt_dlhandle *handle,
! 137: const char *filename,
! 138: lt_dladvise padvise,
! 139: const lt_dlvtable *vtable);
! 140: static int unload_deplibs (lt_dlhandle handle);
! 141: static int lt_argz_insert (char **pargz, size_t *pargz_len,
! 142: char *before, const char *entry);
! 143: static int lt_argz_insertinorder (char **pargz, size_t *pargz_len,
! 144: const char *entry);
! 145: static int lt_argz_insertdir (char **pargz, size_t *pargz_len,
! 146: const char *dirnam, struct dirent *dp);
! 147: static int lt_dlpath_insertdir (char **ppath, char *before,
! 148: const char *dir);
! 149: static int list_files_by_dir (const char *dirnam,
! 150: char **pargz, size_t *pargz_len);
! 151: static int file_not_found (void);
! 152:
! 153: #ifdef HAVE_LIBDLLOADER
! 154: static int loader_init_callback (lt_dlhandle handle);
! 155: #endif /* HAVE_LIBDLLOADER */
! 156:
! 157: static int loader_init (lt_get_vtable *vtable_func,
! 158: lt_user_data data);
! 159:
! 160: static char *user_search_path= 0;
! 161: static lt_dlhandle handles = 0;
! 162: static int initialized = 0;
! 163:
! 164: /* Our memory failure callback sets the error message to be passed back
! 165: up to the client, so we must be careful to return from mallocation
! 166: callers if allocation fails (as this callback returns!!). */
! 167: void
! 168: lt__alloc_die_callback (void)
! 169: {
! 170: LT__SETERROR (NO_MEMORY);
! 171: }
! 172:
! 173: #ifdef HAVE_LIBDLLOADER
! 174: /* This function is called to initialise each preloaded module loader,
! 175: and hook it into the list of loaders to be used when attempting to
! 176: dlopen an application module. */
! 177: static int
! 178: loader_init_callback (lt_dlhandle handle)
! 179: {
! 180: lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");
! 181: return loader_init (vtable_func, 0);
1.2 paf 182: }
1.4 ! moko 183: #endif /* HAVE_LIBDLLOADER */
1.2 paf 184:
185: static int
1.4 ! moko 186: loader_init (lt_get_vtable *vtable_func, lt_user_data data)
1.2 paf 187: {
1.4 ! moko 188: const lt_dlvtable *vtable = 0;
1.2 paf 189: int errors = 0;
190:
1.4 ! moko 191: if (vtable_func)
1.2 paf 192: {
1.4 ! moko 193: vtable = (*vtable_func) (data);
1.2 paf 194: }
195:
1.4 ! moko 196: /* lt_dlloader_add will LT__SETERROR if it fails. */
! 197: errors += lt_dlloader_add (vtable);
1.2 paf 198:
1.4 ! moko 199: assert (errors || vtable);
1.2 paf 200:
1.4 ! moko 201: if ((!errors) && vtable->dlloader_init)
1.2 paf 202: {
1.4 ! moko 203: if ((*vtable->dlloader_init) (vtable->dlloader_data))
1.2 paf 204: {
1.4 ! moko 205: LT__SETERROR (INIT_LOADER);
! 206: ++errors;
1.2 paf 207: }
208: }
209:
210: return errors;
211: }
212:
1.4 ! moko 213: /* Bootstrap the loader loading with the preopening loader. */
! 214: #define get_vtable preopen_LTX_get_vtable
! 215: #define preloaded_symbols LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)
! 216:
! 217: LT_BEGIN_C_DECLS
! 218: LT_SCOPE const lt_dlvtable * get_vtable (lt_user_data data);
! 219: LT_END_C_DECLS
! 220: #ifdef HAVE_LIBDLLOADER
! 221: extern LT_DLSYM_CONST lt_dlsymlist preloaded_symbols[];
! 222: #endif
1.2 paf 223:
224: /* Initialize libltdl. */
225: int
1.4 ! moko 226: lt_dlinit (void)
1.2 paf 227: {
1.4 ! moko 228: int errors = 0;
1.2 paf 229:
230: /* Initialize only at first call. */
231: if (++initialized == 1)
232: {
1.4 ! moko 233: lt__alloc_die = lt__alloc_die_callback;
! 234: handles = 0;
! 235: user_search_path = 0; /* empty search path */
1.2 paf 236:
1.4 ! moko 237: /* First set up the statically loaded preload module loader, so
! 238: we can use it to preopen the other loaders we linked in at
! 239: compile time. */
! 240: errors += loader_init (get_vtable, 0);
1.2 paf 241:
1.4 ! moko 242: /* Now open all the preloaded module loaders, so the application
! 243: can use _them_ to lt_dlopen its own modules. */
! 244: #ifdef HAVE_LIBDLLOADER
! 245: if (!errors)
1.2 paf 246: {
1.4 ! moko 247: errors += lt_dlpreload (preloaded_symbols);
1.2 paf 248: }
1.4 ! moko 249:
! 250: if (!errors)
1.2 paf 251: {
1.4 ! moko 252: errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
1.2 paf 253: }
1.4 ! moko 254: #endif /* HAVE_LIBDLLOADER */
1.2 paf 255: }
256:
1.4 ! moko 257: #ifdef LT_DEBUG_LOADERS
! 258: lt_dlloader_dump();
! 259: #endif
1.2 paf 260:
261: return errors;
262: }
263:
264: int
1.4 ! moko 265: lt_dlexit (void)
1.2 paf 266: {
267: /* shut down libltdl */
1.4 ! moko 268: lt_dlloader *loader = 0;
! 269: lt_dlhandle handle = handles;
1.2 paf 270: int errors = 0;
271:
272: if (!initialized)
273: {
1.4 ! moko 274: LT__SETERROR (SHUTDOWN);
1.2 paf 275: ++errors;
276: goto done;
277: }
278:
279: /* shut down only at last call. */
280: if (--initialized == 0)
281: {
282: int level;
283:
284: while (handles && LT_DLIS_RESIDENT (handles))
285: {
286: handles = handles->next;
287: }
288:
289: /* close all modules */
1.4 ! moko 290: for (level = 1; handle; ++level)
1.2 paf 291: {
292: lt_dlhandle cur = handles;
293: int saw_nonresident = 0;
294:
295: while (cur)
296: {
297: lt_dlhandle tmp = cur;
298: cur = cur->next;
299: if (!LT_DLIS_RESIDENT (tmp))
300: {
1.4 ! moko 301: saw_nonresident = 1;
! 302: if (tmp->info.ref_count <= level)
1.2 paf 303: {
1.4 ! moko 304: if (lt_dlclose (tmp))
! 305: {
! 306: ++errors;
! 307: }
! 308: /* Make sure that the handle pointed to by 'cur' still exists.
! 309: lt_dlclose recursively closes dependent libraries which removes
! 310: them from the linked list. One of these might be the one
! 311: pointed to by 'cur'. */
! 312: if (cur)
! 313: {
! 314: for (tmp = handles; tmp; tmp = tmp->next)
! 315: if (tmp == cur)
! 316: break;
! 317: if (! tmp)
! 318: cur = handles;
! 319: }
1.2 paf 320: }
321: }
322: }
323: /* done if only resident modules are left */
324: if (!saw_nonresident)
325: break;
326: }
1.4 ! moko 327:
! 328: /* When removing loaders, we can only find out failure by testing
! 329: the error string, so avoid a spurious one from an earlier
! 330: failed command. */
! 331: if (!errors)
! 332: LT__SETERRORSTR (0);
! 333:
! 334: /* close all loaders */
! 335: for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
! 336: {
! 337: lt_dlloader *next = (lt_dlloader *) lt_dlloader_next (loader);
! 338: lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);
! 339:
! 340: if ((vtable = lt_dlloader_remove ((char *) vtable->name)))
! 341: {
! 342: FREE (vtable);
! 343: }
! 344: else
1.2 paf 345: {
1.4 ! moko 346: /* ignore errors due to resident modules */
! 347: const char *err;
! 348: LT__GETERROR (err);
! 349: if (err)
! 350: ++errors;
1.2 paf 351: }
352:
1.4 ! moko 353: loader = next;
1.2 paf 354: }
1.4 ! moko 355:
! 356: FREE(user_search_path);
1.2 paf 357: }
358:
359: done:
360: return errors;
361: }
362:
1.4 ! moko 363:
! 364: /* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.
! 365: If the library is not successfully loaded, return non-zero. Otherwise,
! 366: the dlhandle is stored at the address given in PHANDLE. */
1.2 paf 367: static int
1.4 ! moko 368: tryall_dlopen (lt_dlhandle *phandle, const char *filename,
! 369: lt_dladvise advise, const lt_dlvtable *vtable)
! 370: {
! 371: lt_dlhandle handle = handles;
! 372: const char * saved_error = 0;
! 373: int errors = 0;
1.2 paf 374:
1.4 ! moko 375: #ifdef LT_DEBUG_LOADERS
! 376: fprintf (stderr, "tryall_dlopen (%s, %s)\n",
! 377: filename ? filename : "(null)",
! 378: vtable ? vtable->name : "(ALL)");
! 379: #endif
1.2 paf 380:
1.4 ! moko 381: LT__GETERROR (saved_error);
1.2 paf 382:
383: /* check whether the module was already opened */
1.4 ! moko 384: for (;handle; handle = handle->next)
1.2 paf 385: {
1.4 ! moko 386: if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
! 387: || (handle->info.filename && filename
! 388: && streq (handle->info.filename, filename)))
1.2 paf 389: {
390: break;
391: }
392: }
393:
1.4 ! moko 394: if (handle)
1.2 paf 395: {
1.4 ! moko 396: ++handle->info.ref_count;
! 397: *phandle = handle;
1.2 paf 398: goto done;
399: }
400:
1.4 ! moko 401: handle = *phandle;
1.2 paf 402: if (filename)
403: {
1.4 ! moko 404: /* Comment out the check of file permissions using access.
! 405: This call seems to always return -1 with error EACCES.
! 406: */
! 407: /* We need to catch missing file errors early so that
! 408: file_not_found() can detect what happened.
! 409: if (access (filename, R_OK) != 0)
! 410: {
! 411: LT__SETERROR (FILE_NOT_FOUND);
! 412: ++errors;
! 413: goto done;
! 414: } */
! 415:
! 416: handle->info.filename = lt__strdup (filename);
! 417: if (!handle->info.filename)
1.2 paf 418: {
419: ++errors;
420: goto done;
421: }
422: }
423: else
424: {
1.4 ! moko 425: handle->info.filename = 0;
1.2 paf 426: }
427:
1.4 ! moko 428: {
! 429: lt_dlloader loader = lt_dlloader_next (0);
! 430: const lt_dlvtable *loader_vtable;
! 431:
! 432: do
! 433: {
! 434: if (vtable)
! 435: loader_vtable = vtable;
! 436: else
! 437: loader_vtable = lt_dlloader_get (loader);
! 438:
! 439: #ifdef LT_DEBUG_LOADERS
! 440: fprintf (stderr, "Calling %s->module_open (%s)\n",
! 441: (loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",
! 442: filename ? filename : "(null)");
! 443: #endif
! 444: handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,
! 445: filename, advise);
! 446: #ifdef LT_DEBUG_LOADERS
! 447: fprintf (stderr, " Result: %s\n",
! 448: handle->module ? "Success" : "Failed");
! 449: #endif
1.2 paf 450:
1.4 ! moko 451: if (handle->module != 0)
! 452: {
! 453: if (advise)
! 454: {
! 455: handle->info.is_resident = advise->is_resident;
! 456: handle->info.is_symglobal = advise->is_symglobal;
! 457: handle->info.is_symlocal = advise->is_symlocal;
! 458: }
! 459: break;
! 460: }
! 461: }
! 462: while (!vtable && (loader = lt_dlloader_next (loader)));
1.2 paf 463:
1.4 ! moko 464: /* If VTABLE was given but couldn't open the module, or VTABLE wasn't
! 465: given but we exhausted all loaders without opening the module, bail
! 466: out! */
! 467: if ((vtable && !handle->module)
! 468: || (!vtable && !loader))
! 469: {
! 470: FREE (handle->info.filename);
! 471: ++errors;
! 472: goto done;
! 473: }
1.2 paf 474:
1.4 ! moko 475: handle->vtable = loader_vtable;
! 476: }
1.2 paf 477:
1.4 ! moko 478: LT__SETERRORSTR (saved_error);
1.2 paf 479:
480: done:
481: return errors;
482: }
483:
1.4 ! moko 484:
1.2 paf 485: static int
1.4 ! moko 486: tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
! 487: const char *dirname, const char *dlname,
! 488: lt_dladvise advise)
1.2 paf 489: {
490: int error = 0;
1.4 ! moko 491: char *filename = 0;
1.2 paf 492: size_t filename_len = 0;
493: size_t dirname_len = LT_STRLEN (dirname);
494:
495: assert (handle);
496: assert (dirname);
497: assert (dlname);
1.4 ! moko 498: #if defined(LT_DIRSEP_CHAR)
1.2 paf 499: /* Only canonicalized names (i.e. with DIRSEP chars already converted)
500: should make it into this function: */
1.4 ! moko 501: assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
1.2 paf 502: #endif
503:
1.4 ! moko 504: if (dirname_len > 0)
! 505: if (dirname[dirname_len -1] == '/')
! 506: --dirname_len;
1.2 paf 507: filename_len = dirname_len + 1 + LT_STRLEN (dlname);
508:
509: /* Allocate memory, and combine DIRNAME and MODULENAME into it.
510: The PREFIX (if any) is handled below. */
1.4 ! moko 511: filename = MALLOC (char, filename_len + 1);
1.2 paf 512: if (!filename)
513: return 1;
514:
515: sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
516:
517: /* Now that we have combined DIRNAME and MODULENAME, if there is
518: also a PREFIX to contend with, simply recurse with the arguments
519: shuffled. Otherwise, attempt to open FILENAME as a module. */
520: if (prefix)
521: {
1.4 ! moko 522: error += tryall_dlopen_module (handle, (const char *) 0,
! 523: prefix, filename, advise);
1.2 paf 524: }
1.4 ! moko 525: else if (tryall_dlopen (handle, filename, advise, 0) != 0)
1.2 paf 526: {
527: ++error;
528: }
529:
1.4 ! moko 530: FREE (filename);
1.2 paf 531: return error;
532: }
533:
534: static int
1.4 ! moko 535: find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
! 536: const char *dlname, const char *old_name, int installed,
! 537: lt_dladvise advise)
1.2 paf 538: {
539: /* Try to open the old library first; if it was dlpreopened,
540: we want the preopened version of it, even if a dlopenable
541: module is available. */
1.4 ! moko 542: if (old_name && tryall_dlopen (handle, old_name,
! 543: advise, lt_dlloader_find ("lt_preopen") ) == 0)
1.2 paf 544: {
545: return 0;
546: }
547:
548: /* Try to open the dynamic library. */
549: if (dlname)
550: {
551: /* try to open the installed module */
552: if (installed && libdir)
553: {
1.4 ! moko 554: if (tryall_dlopen_module (handle, (const char *) 0,
! 555: libdir, dlname, advise) == 0)
1.2 paf 556: return 0;
557: }
558:
559: /* try to open the not-installed module */
560: if (!installed)
561: {
1.4 ! moko 562: if (tryall_dlopen_module (handle, dir, objdir,
! 563: dlname, advise) == 0)
1.2 paf 564: return 0;
565: }
566:
567: /* maybe it was moved to another directory */
568: {
1.4 ! moko 569: if (dir && (tryall_dlopen_module (handle, (const char *) 0,
! 570: dir, dlname, advise) == 0))
1.2 paf 571: return 0;
572: }
573: }
574:
575: return 1;
576: }
577:
578:
579: static int
1.4 ! moko 580: canonicalize_path (const char *path, char **pcanonical)
1.2 paf 581: {
1.4 ! moko 582: char *canonical = 0;
1.2 paf 583:
584: assert (path && *path);
585: assert (pcanonical);
586:
1.4 ! moko 587: canonical = MALLOC (char, 1+ LT_STRLEN (path));
1.2 paf 588: if (!canonical)
589: return 1;
590:
591: {
592: size_t dest = 0;
593: size_t src;
594: for (src = 0; path[src] != LT_EOS_CHAR; ++src)
595: {
596: /* Path separators are not copied to the beginning or end of
597: the destination, or if another separator would follow
598: immediately. */
599: if (path[src] == LT_PATHSEP_CHAR)
600: {
601: if ((dest == 0)
602: || (path[1+ src] == LT_PATHSEP_CHAR)
603: || (path[1+ src] == LT_EOS_CHAR))
604: continue;
605: }
606:
607: /* Anything other than a directory separator is copied verbatim. */
608: if ((path[src] != '/')
1.4 ! moko 609: #if defined(LT_DIRSEP_CHAR)
1.2 paf 610: && (path[src] != LT_DIRSEP_CHAR)
611: #endif
612: )
613: {
614: canonical[dest++] = path[src];
615: }
616: /* Directory separators are converted and copied only if they are
617: not at the end of a path -- i.e. before a path separator or
618: NULL terminator. */
619: else if ((path[1+ src] != LT_PATHSEP_CHAR)
620: && (path[1+ src] != LT_EOS_CHAR)
1.4 ! moko 621: #if defined(LT_DIRSEP_CHAR)
1.2 paf 622: && (path[1+ src] != LT_DIRSEP_CHAR)
623: #endif
624: && (path[1+ src] != '/'))
625: {
626: canonical[dest++] = '/';
627: }
628: }
629:
630: /* Add an end-of-string marker at the end. */
631: canonical[dest] = LT_EOS_CHAR;
632: }
633:
634: /* Assign new value. */
635: *pcanonical = canonical;
636:
637: return 0;
638: }
639:
640: static int
1.4 ! moko 641: argzize_path (const char *path, char **pargz, size_t *pargz_len)
1.2 paf 642: {
643: error_t error;
644:
645: assert (path);
646: assert (pargz);
647: assert (pargz_len);
648:
649: if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
650: {
651: switch (error)
652: {
653: case ENOMEM:
1.4 ! moko 654: LT__SETERROR (NO_MEMORY);
1.2 paf 655: break;
656: default:
1.4 ! moko 657: LT__SETERROR (UNKNOWN);
1.2 paf 658: break;
659: }
660:
661: return 1;
662: }
663:
664: return 0;
665: }
666:
667: /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
668: of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
669: non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
670: it is appended to each SEARCH_PATH element before FUNC is called. */
671: static int
1.4 ! moko 672: foreach_dirinpath (const char *search_path, const char *base_name,
! 673: foreach_callback_func *func, void *data1, void *data2)
1.2 paf 674: {
675: int result = 0;
1.4 ! moko 676: size_t filenamesize = 0;
1.2 paf 677: size_t lenbase = LT_STRLEN (base_name);
678: size_t argz_len = 0;
1.4 ! moko 679: char *argz = 0;
! 680: char *filename = 0;
! 681: char *canonical = 0;
1.2 paf 682:
683: if (!search_path || !*search_path)
684: {
1.4 ! moko 685: LT__SETERROR (FILE_NOT_FOUND);
1.2 paf 686: goto cleanup;
687: }
688:
689: if (canonicalize_path (search_path, &canonical) != 0)
690: goto cleanup;
691:
692: if (argzize_path (canonical, &argz, &argz_len) != 0)
693: goto cleanup;
694:
695: {
1.4 ! moko 696: char *dir_name = 0;
1.2 paf 697: while ((dir_name = argz_next (argz, argz_len, dir_name)))
698: {
699: size_t lendir = LT_STRLEN (dir_name);
700:
1.4 ! moko 701: if (1+ lendir + lenbase >= filenamesize)
1.2 paf 702: {
1.4 ! moko 703: FREE (filename);
! 704: filenamesize = 1+ lendir + 1+ lenbase; /* "/d" + '/' + "f" + '\0' */
! 705: filename = MALLOC (char, filenamesize);
1.2 paf 706: if (!filename)
707: goto cleanup;
708: }
709:
710: assert (filenamesize > lendir);
711: strcpy (filename, dir_name);
712:
713: if (base_name && *base_name)
714: {
715: if (filename[lendir -1] != '/')
716: filename[lendir++] = '/';
717: strcpy (filename +lendir, base_name);
718: }
719:
720: if ((result = (*func) (filename, data1, data2)))
721: {
722: break;
723: }
724: }
725: }
726:
727: cleanup:
1.4 ! moko 728: FREE (argz);
! 729: FREE (canonical);
! 730: FREE (filename);
1.2 paf 731:
732: return result;
733: }
734:
735: /* If FILEPATH can be opened, store the name of the directory component
736: in DATA1, and the opened FILE* structure address in DATA2. Otherwise
737: DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
738: static int
1.4 ! moko 739: find_file_callback (char *filename, void *data1, void *data2)
1.2 paf 740: {
741: char **pdir = (char **) data1;
742: FILE **pfile = (FILE **) data2;
743: int is_done = 0;
744:
745: assert (filename && *filename);
746: assert (pdir);
747: assert (pfile);
748:
749: if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
750: {
751: char *dirend = strrchr (filename, '/');
752:
753: if (dirend > filename)
754: *dirend = LT_EOS_CHAR;
755:
1.4 ! moko 756: FREE (*pdir);
! 757: *pdir = lt__strdup (filename);
! 758: is_done = (*pdir == 0) ? -1 : 1;
1.2 paf 759: }
760:
761: return is_done;
762: }
763:
764: static FILE *
1.4 ! moko 765: find_file (const char *search_path, const char *base_name, char **pdir)
1.2 paf 766: {
1.4 ! moko 767: FILE *file = 0;
1.2 paf 768:
769: foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
770:
771: return file;
772: }
773:
774: static int
1.4 ! moko 775: find_handle_callback (char *filename, void *data, void *data2)
1.2 paf 776: {
1.4 ! moko 777: lt_dlhandle *phandle = (lt_dlhandle *) data;
1.2 paf 778: int notfound = access (filename, R_OK);
1.4 ! moko 779: lt_dladvise advise = (lt_dladvise) data2;
1.2 paf 780:
781: /* Bail out if file cannot be read... */
782: if (notfound)
783: return 0;
784:
785: /* Try to dlopen the file, but do not continue searching in any
786: case. */
1.4 ! moko 787: if (tryall_dlopen (phandle, filename, advise, 0) != 0)
! 788: *phandle = 0;
1.2 paf 789:
790: return 1;
791: }
792:
793: /* If HANDLE was found return it, otherwise return 0. If HANDLE was
794: found but could not be opened, *HANDLE will be set to 0. */
795: static lt_dlhandle *
1.4 ! moko 796: find_handle (const char *search_path, const char *base_name,
! 797: lt_dlhandle *phandle, lt_dladvise advise)
1.2 paf 798: {
799: if (!search_path)
800: return 0;
801:
802: if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
1.4 ! moko 803: phandle, advise))
1.2 paf 804: return 0;
805:
1.4 ! moko 806: return phandle;
! 807: }
! 808:
! 809: #if !defined(LTDL_DLOPEN_DEPLIBS)
! 810: static int
! 811: load_deplibs (lt_dlhandle handle, char * LT__UNUSED deplibs)
! 812: {
! 813: handle->depcount = 0;
! 814: return 0;
1.2 paf 815: }
816:
1.4 ! moko 817: #else /* defined(LTDL_DLOPEN_DEPLIBS) */
1.2 paf 818: static int
1.4 ! moko 819: load_deplibs (lt_dlhandle handle, char *deplibs)
1.2 paf 820: {
1.4 ! moko 821: char *p, *save_search_path = 0;
1.2 paf 822: int depcount = 0;
823: int i;
1.4 ! moko 824: char **names = 0;
1.2 paf 825: int errors = 0;
826:
827: handle->depcount = 0;
828:
829: if (!deplibs)
830: {
831: return errors;
832: }
833: ++errors;
834:
835: if (user_search_path)
836: {
1.4 ! moko 837: save_search_path = lt__strdup (user_search_path);
1.2 paf 838: if (!save_search_path)
839: goto cleanup;
840: }
841:
842: /* extract search paths and count deplibs */
843: p = deplibs;
844: while (*p)
845: {
1.4 ! moko 846: if (!isspace ((unsigned char) *p))
1.2 paf 847: {
848: char *end = p+1;
1.4 ! moko 849: while (*end && !isspace((unsigned char) *end))
1.2 paf 850: {
851: ++end;
852: }
853:
854: if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
855: {
856: char save = *end;
1.4 ! moko 857: *end = 0; /* set a temporary string terminator */
1.2 paf 858: if (lt_dladdsearchdir(p+2))
859: {
860: goto cleanup;
861: }
862: *end = save;
863: }
864: else
865: {
866: ++depcount;
867: }
868:
869: p = end;
870: }
871: else
872: {
873: ++p;
874: }
875: }
876:
877:
878: if (!depcount)
879: {
880: errors = 0;
881: goto cleanup;
882: }
883:
1.4 ! moko 884: names = MALLOC (char *, depcount);
1.2 paf 885: if (!names)
886: goto cleanup;
887:
888: /* now only extract the actual deplibs */
889: depcount = 0;
890: p = deplibs;
891: while (*p)
892: {
1.4 ! moko 893: if (isspace ((unsigned char) *p))
1.2 paf 894: {
895: ++p;
896: }
897: else
898: {
899: char *end = p+1;
1.4 ! moko 900: while (*end && !isspace ((unsigned char) *end))
1.2 paf 901: {
902: ++end;
903: }
904:
905: if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
906: {
907: char *name;
908: char save = *end;
1.4 ! moko 909: *end = 0; /* set a temporary string terminator */
1.2 paf 910: if (strncmp(p, "-l", 2) == 0)
911: {
912: size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
1.4 ! moko 913: name = MALLOC (char, 1+ name_len);
1.2 paf 914: if (name)
915: sprintf (name, "lib%s", p+2);
916: }
917: else
1.4 ! moko 918: name = lt__strdup(p);
1.2 paf 919:
920: if (!name)
921: goto cleanup_names;
922:
923: names[depcount++] = name;
924: *end = save;
925: }
926: p = end;
927: }
928: }
929:
930: /* load the deplibs (in reverse order)
931: At this stage, don't worry if the deplibs do not load correctly,
932: they may already be statically linked into the loading application
933: for instance. There will be a more enlightening error message
934: later on if the loaded module cannot resolve all of its symbols. */
935: if (depcount)
936: {
1.4 ! moko 937: lt_dlhandle cur = handle;
1.2 paf 938: int j = 0;
939:
1.4 ! moko 940: cur->deplibs = MALLOC (lt_dlhandle, depcount);
! 941: if (!cur->deplibs)
! 942: goto cleanup_names;
1.2 paf 943:
944: for (i = 0; i < depcount; ++i)
945: {
1.4 ! moko 946: cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
! 947: if (cur->deplibs[j])
1.2 paf 948: {
949: ++j;
950: }
951: }
952:
1.4 ! moko 953: cur->depcount = j; /* Number of successfully loaded deplibs */
1.2 paf 954: errors = 0;
955: }
956:
957: cleanup_names:
958: for (i = 0; i < depcount; ++i)
959: {
1.4 ! moko 960: FREE (names[i]);
1.2 paf 961: }
962:
963: cleanup:
1.4 ! moko 964: FREE (names);
! 965: /* restore the old search path */
! 966: if (save_search_path) {
! 967: MEMREASSIGN (user_search_path, save_search_path);
! 968: }
1.2 paf 969:
970: return errors;
971: }
1.4 ! moko 972: #endif /* defined(LTDL_DLOPEN_DEPLIBS) */
1.2 paf 973:
974: static int
1.4 ! moko 975: unload_deplibs (lt_dlhandle handle)
1.2 paf 976: {
977: int i;
978: int errors = 0;
1.4 ! moko 979: lt_dlhandle cur = handle;
1.2 paf 980:
1.4 ! moko 981: if (cur->depcount)
1.2 paf 982: {
1.4 ! moko 983: for (i = 0; i < cur->depcount; ++i)
1.2 paf 984: {
1.4 ! moko 985: if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
1.2 paf 986: {
1.4 ! moko 987: errors += lt_dlclose (cur->deplibs[i]);
1.2 paf 988: }
989: }
1.4 ! moko 990: FREE (cur->deplibs);
1.2 paf 991: }
992:
993: return errors;
994: }
995:
996: static int
1.4 ! moko 997: trim (char **dest, const char *str)
1.2 paf 998: {
999: /* remove the leading and trailing "'" from str
1000: and store the result in dest */
1001: const char *end = strrchr (str, '\'');
1002: size_t len = LT_STRLEN (str);
1003: char *tmp;
1004:
1.4 ! moko 1005: FREE (*dest);
! 1006:
! 1007: if (!end || end == str)
! 1008: return 1;
1.2 paf 1009:
1010: if (len > 3 && str[0] == '\'')
1011: {
1.4 ! moko 1012: tmp = MALLOC (char, end - str);
1.2 paf 1013: if (!tmp)
1014: return 1;
1015:
1.4 ! moko 1016: memcpy(tmp, &str[1], (end - str) - 1);
! 1017: tmp[(end - str) - 1] = LT_EOS_CHAR;
1.2 paf 1018: *dest = tmp;
1019: }
1020: else
1021: {
1.4 ! moko 1022: *dest = 0;
1.2 paf 1023: }
1024:
1025: return 0;
1026: }
1027:
1.4 ! moko 1028: /* Read the .la file FILE. */
1.2 paf 1029: static int
1.4 ! moko 1030: parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
! 1031: char **old_name, int *installed)
! 1032: {
! 1033: int errors = 0;
! 1034: size_t line_len = LT_FILENAME_MAX;
! 1035: char * line = MALLOC (char, line_len);
1.2 paf 1036:
1.4 ! moko 1037: if (!line)
! 1038: {
! 1039: LT__SETERROR (FILE_NOT_FOUND);
! 1040: return 1;
! 1041: }
! 1042:
! 1043: while (!feof (file))
! 1044: {
! 1045: line[line_len-2] = '\0';
! 1046: if (!fgets (line, (int) line_len, file))
! 1047: {
! 1048: break;
! 1049: }
! 1050:
! 1051: /* Handle the case where we occasionally need to read a line
! 1052: that is longer than the initial buffer size.
! 1053: Behave even if the file contains NUL bytes due to corruption. */
! 1054: while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
! 1055: {
! 1056: line = REALLOC (char, line, line_len *2);
! 1057: if (!line)
! 1058: {
! 1059: ++errors;
! 1060: goto cleanup;
! 1061: }
! 1062: line[line_len * 2 - 2] = '\0';
! 1063: if (!fgets (&line[line_len -1], (int) line_len +1, file))
! 1064: {
! 1065: break;
! 1066: }
! 1067: line_len *= 2;
! 1068: }
! 1069:
! 1070: if (line[0] == '\n' || line[0] == '#')
! 1071: {
! 1072: continue;
! 1073: }
! 1074:
! 1075: #undef STR_DLNAME
! 1076: #define STR_DLNAME "dlname="
! 1077: if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
! 1078: {
! 1079: errors += trim (dlname, &line[sizeof (STR_DLNAME) - 1]);
! 1080: }
! 1081:
! 1082: #undef STR_OLD_LIBRARY
! 1083: #define STR_OLD_LIBRARY "old_library="
! 1084: else if (strncmp (line, STR_OLD_LIBRARY,
! 1085: sizeof (STR_OLD_LIBRARY) - 1) == 0)
! 1086: {
! 1087: errors += trim (old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
! 1088: }
! 1089:
! 1090: /* Windows native tools do not understand the POSIX paths we store
! 1091: in libdir. */
! 1092: #undef STR_LIBDIR
! 1093: #define STR_LIBDIR "libdir="
! 1094: else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
! 1095: {
! 1096: errors += trim (libdir, &line[sizeof(STR_LIBDIR) - 1]);
! 1097: #ifdef __WINDOWS__
! 1098: /* Disallow following unix-style paths on MinGW. */
! 1099: if (*libdir && (**libdir == '/' || **libdir == '\\'))
! 1100: **libdir = '\0';
! 1101: #endif
! 1102: }
! 1103:
! 1104: #undef STR_DL_DEPLIBS
! 1105: #define STR_DL_DEPLIBS "dependency_libs="
! 1106: else if (strncmp (line, STR_DL_DEPLIBS,
! 1107: sizeof (STR_DL_DEPLIBS) - 1) == 0)
! 1108: {
! 1109: errors += trim (deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
! 1110: }
! 1111: else if (streq (line, "installed=yes\n"))
! 1112: {
! 1113: *installed = 1;
! 1114: }
! 1115: else if (streq (line, "installed=no\n"))
! 1116: {
! 1117: *installed = 0;
! 1118: }
! 1119:
! 1120: #undef STR_LIBRARY_NAMES
! 1121: #define STR_LIBRARY_NAMES "library_names="
! 1122: else if (!*dlname && strncmp (line, STR_LIBRARY_NAMES,
! 1123: sizeof (STR_LIBRARY_NAMES) - 1) == 0)
! 1124: {
! 1125: char *last_libname;
! 1126: errors += trim (dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
! 1127: if (!errors
! 1128: && *dlname
! 1129: && (last_libname = strrchr (*dlname, ' ')) != 0)
! 1130: {
! 1131: last_libname = lt__strdup (last_libname + 1);
! 1132: if (!last_libname)
! 1133: {
! 1134: ++errors;
! 1135: goto cleanup;
! 1136: }
! 1137: MEMREASSIGN (*dlname, last_libname);
! 1138: }
! 1139: }
! 1140:
! 1141: if (errors)
! 1142: break;
! 1143: }
! 1144: cleanup:
! 1145: FREE (line);
! 1146: return errors;
1.2 paf 1147: }
1148:
1.4 ! moko 1149:
! 1150: /* Try to open FILENAME as a module. */
1.2 paf 1151: static int
1.4 ! moko 1152: try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
! 1153: lt_dladvise advise)
! 1154: {
! 1155: const char * saved_error = 0;
! 1156: char * archive_name = 0;
! 1157: char * canonical = 0;
! 1158: char * base_name = 0;
! 1159: char * dir = 0;
! 1160: char * name = 0;
! 1161: char * attempt = 0;
1.2 paf 1162: int errors = 0;
1163: lt_dlhandle newhandle;
1164:
1165: assert (phandle);
1.4 ! moko 1166: assert (*phandle == 0);
1.2 paf 1167:
1.4 ! moko 1168: #ifdef LT_DEBUG_LOADERS
! 1169: fprintf (stderr, "try_dlopen (%s, %s)\n",
! 1170: filename ? filename : "(null)",
! 1171: ext ? ext : "(null)");
! 1172: #endif
! 1173:
! 1174: LT__GETERROR (saved_error);
1.2 paf 1175:
1176: /* dlopen self? */
1177: if (!filename)
1178: {
1.4 ! moko 1179: *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
! 1180: if (*phandle == 0)
1.2 paf 1181: return 1;
1182:
1183: newhandle = *phandle;
1184:
1185: /* lt_dlclose()ing yourself is very bad! Disallow it. */
1.4 ! moko 1186: newhandle->info.is_resident = 1;
1.2 paf 1187:
1.4 ! moko 1188: if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
1.2 paf 1189: {
1.4 ! moko 1190: FREE (*phandle);
1.2 paf 1191: return 1;
1192: }
1193:
1194: goto register_handle;
1195: }
1196:
1197: assert (filename && *filename);
1198:
1.4 ! moko 1199: if (ext)
! 1200: {
! 1201: attempt = MALLOC (char, LT_STRLEN (filename) + LT_STRLEN (ext) + 1);
! 1202: if (!attempt)
! 1203: return 1;
! 1204:
! 1205: sprintf(attempt, "%s%s", filename, ext);
! 1206: }
! 1207: else
! 1208: {
! 1209: attempt = lt__strdup (filename);
! 1210: if (!attempt)
! 1211: return 1;
! 1212: }
! 1213:
1.2 paf 1214: /* Doing this immediately allows internal functions to safely
1215: assume only canonicalized paths are passed. */
1.4 ! moko 1216: if (canonicalize_path (attempt, &canonical) != 0)
1.2 paf 1217: {
1218: ++errors;
1219: goto cleanup;
1220: }
1221:
1222: /* If the canonical module name is a path (relative or absolute)
1223: then split it into a directory part and a name part. */
1224: base_name = strrchr (canonical, '/');
1225: if (base_name)
1226: {
1227: size_t dirlen = (1+ base_name) - canonical;
1228:
1.4 ! moko 1229: dir = MALLOC (char, 1+ dirlen);
1.2 paf 1230: if (!dir)
1231: {
1232: ++errors;
1233: goto cleanup;
1234: }
1235:
1236: strncpy (dir, canonical, dirlen);
1237: dir[dirlen] = LT_EOS_CHAR;
1238:
1239: ++base_name;
1240: }
1241: else
1.4 ! moko 1242: MEMREASSIGN (base_name, canonical);
1.2 paf 1243:
1244: assert (base_name && *base_name);
1245:
1.4 ! moko 1246: ext = strrchr (base_name, '.');
! 1247: if (!ext)
! 1248: {
! 1249: ext = base_name + LT_STRLEN (base_name);
! 1250: }
! 1251:
! 1252: /* extract the module name from the file name */
! 1253: name = MALLOC (char, ext - base_name + 1);
! 1254: if (!name)
! 1255: {
! 1256: ++errors;
! 1257: goto cleanup;
! 1258: }
! 1259:
! 1260: /* canonicalize the module name */
! 1261: {
! 1262: int i;
! 1263: for (i = 0; i < ext - base_name; ++i)
! 1264: {
! 1265: if (isalnum ((unsigned char)(base_name[i])))
! 1266: {
! 1267: name[i] = base_name[i];
! 1268: }
! 1269: else
! 1270: {
! 1271: name[i] = '_';
! 1272: }
! 1273: }
! 1274: name[ext - base_name] = LT_EOS_CHAR;
! 1275: }
! 1276:
! 1277: /* Before trawling through the filesystem in search of a module,
! 1278: check whether we are opening a preloaded module. */
! 1279: if (!dir)
! 1280: {
! 1281: const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
! 1282:
! 1283: if (vtable)
! 1284: {
! 1285: /* libprefix + name + "." + libext + NULL */
! 1286: archive_name = MALLOC (char, strlen (libprefix) + LT_STRLEN (name) + strlen (libext) + 2);
! 1287: *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
! 1288:
! 1289: if ((*phandle == NULL) || (archive_name == NULL))
! 1290: {
! 1291: ++errors;
! 1292: goto cleanup;
! 1293: }
! 1294: newhandle = *phandle;
! 1295:
! 1296: /* Preloaded modules are always named according to their old
! 1297: archive name. */
! 1298: if (strncmp(name, "lib", 3) == 0)
! 1299: {
! 1300: sprintf (archive_name, "%s%s.%s", libprefix, name + 3, libext);
! 1301: }
! 1302: else
! 1303: {
! 1304: sprintf (archive_name, "%s.%s", name, libext);
! 1305: }
! 1306:
! 1307: if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
! 1308: {
! 1309: goto register_handle;
! 1310: }
! 1311:
! 1312: /* If we're still here, there was no matching preloaded module,
! 1313: so put things back as we found them, and continue searching. */
! 1314: FREE (*phandle);
! 1315: newhandle = NULL;
! 1316: }
! 1317: }
! 1318:
! 1319: /* If we are allowing only preloaded modules, and we didn't find
! 1320: anything yet, give up on the search here. */
! 1321: if (advise && advise->try_preload_only)
! 1322: {
! 1323: goto cleanup;
! 1324: }
! 1325:
1.2 paf 1326: /* Check whether we are opening a libtool module (.la extension). */
1.4 ! moko 1327: if (ext && streq (ext, archive_ext))
1.2 paf 1328: {
1329: /* this seems to be a libtool module */
1.4 ! moko 1330: FILE * file = 0;
! 1331: char * dlname = 0;
! 1332: char * old_name = 0;
! 1333: char * libdir = 0;
! 1334: char * deplibs = 0;
1.2 paf 1335:
1336: /* if we can't find the installed flag, it is probably an
1337: installed libtool archive, produced with an old version
1338: of libtool */
1339: int installed = 1;
1340:
1341: /* Now try to open the .la file. If there is no directory name
1.4 ! moko 1342: component, try to find it first in user_search_path and then other
! 1343: prescribed paths. Otherwise (or in any case if the module was not
! 1344: yet found) try opening just the module name as passed. */
1.2 paf 1345: if (!dir)
1346: {
1.4 ! moko 1347: const char *search_path = user_search_path;
1.2 paf 1348:
1349: if (search_path)
1350: file = find_file (user_search_path, base_name, &dir);
1351:
1352: if (!file)
1353: {
1354: search_path = getenv (LTDL_SEARCHPATH_VAR);
1355: if (search_path)
1356: file = find_file (search_path, base_name, &dir);
1357: }
1358:
1.4 ! moko 1359: #if defined(LT_MODULE_PATH_VAR)
1.2 paf 1360: if (!file)
1361: {
1.4 ! moko 1362: search_path = getenv (LT_MODULE_PATH_VAR);
1.2 paf 1363: if (search_path)
1364: file = find_file (search_path, base_name, &dir);
1365: }
1366: #endif
1.4 ! moko 1367: #if defined(LT_DLSEARCH_PATH)
! 1368: if (!file && *sys_dlsearch_path)
1.2 paf 1369: {
1.4 ! moko 1370: file = find_file (sys_dlsearch_path, base_name, &dir);
1.2 paf 1371: }
1372: #endif
1373: }
1.4 ! moko 1374: else
1.2 paf 1375: {
1.4 ! moko 1376: file = fopen (attempt, LT_READTEXT_MODE);
1.2 paf 1377: }
1378:
1379: /* If we didn't find the file by now, it really isn't there. Set
1380: the status flag, and bail out. */
1381: if (!file)
1382: {
1.4 ! moko 1383: LT__SETERROR (FILE_NOT_FOUND);
1.2 paf 1384: ++errors;
1385: goto cleanup;
1386: }
1387:
1388: /* read the .la file */
1.4 ! moko 1389: if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
! 1390: &old_name, &installed) != 0)
! 1391: ++errors;
1.2 paf 1392:
1393: fclose (file);
1394:
1395: /* allocate the handle */
1.4 ! moko 1396: *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
! 1397: if (*phandle == 0)
1.2 paf 1398: ++errors;
1399:
1400: if (errors)
1401: {
1.4 ! moko 1402: FREE (dlname);
! 1403: FREE (old_name);
! 1404: FREE (libdir);
! 1405: FREE (deplibs);
! 1406: FREE (*phandle);
1.2 paf 1407: goto cleanup;
1408: }
1409:
1410: assert (*phandle);
1411:
1412: if (load_deplibs (*phandle, deplibs) == 0)
1413: {
1414: newhandle = *phandle;
1415: /* find_module may replace newhandle */
1.4 ! moko 1416: if (find_module (&newhandle, dir, libdir, dlname, old_name,
! 1417: installed, advise))
1.2 paf 1418: {
1419: unload_deplibs (*phandle);
1420: ++errors;
1421: }
1422: }
1423: else
1424: {
1425: ++errors;
1426: }
1427:
1.4 ! moko 1428: FREE (dlname);
! 1429: FREE (old_name);
! 1430: FREE (libdir);
! 1431: FREE (deplibs);
! 1432:
1.2 paf 1433: if (errors)
1434: {
1.4 ! moko 1435: FREE (*phandle);
1.2 paf 1436: goto cleanup;
1437: }
1438:
1439: if (*phandle != newhandle)
1440: {
1441: unload_deplibs (*phandle);
1442: }
1443: }
1444: else
1445: {
1446: /* not a libtool module */
1.4 ! moko 1447: *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
! 1448: if (*phandle == 0)
1.2 paf 1449: {
1450: ++errors;
1451: goto cleanup;
1452: }
1453:
1454: newhandle = *phandle;
1455:
1456: /* If the module has no directory name component, try to find it
1457: first in user_search_path and then other prescribed paths.
1458: Otherwise (or in any case if the module was not yet found) try
1459: opening just the module name as passed. */
1.4 ! moko 1460: if ((dir || (!find_handle (user_search_path, base_name,
! 1461: &newhandle, advise)
1.2 paf 1462: && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
1.4 ! moko 1463: &newhandle, advise)
! 1464: #if defined(LT_MODULE_PATH_VAR)
! 1465: && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
! 1466: &newhandle, advise)
! 1467: #endif
! 1468: #if defined(LT_DLSEARCH_PATH)
! 1469: && !find_handle (sys_dlsearch_path, base_name,
! 1470: &newhandle, advise)
1.2 paf 1471: #endif
1472: )))
1473: {
1.4 ! moko 1474: if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
! 1475: {
! 1476: newhandle = NULL;
! 1477: }
1.2 paf 1478: }
1479:
1480: if (!newhandle)
1481: {
1.4 ! moko 1482: FREE (*phandle);
1.2 paf 1483: ++errors;
1484: goto cleanup;
1485: }
1486: }
1487:
1488: register_handle:
1.4 ! moko 1489: MEMREASSIGN (*phandle, newhandle);
1.2 paf 1490:
1491: if ((*phandle)->info.ref_count == 0)
1492: {
1493: (*phandle)->info.ref_count = 1;
1.4 ! moko 1494: MEMREASSIGN ((*phandle)->info.name, name);
1.2 paf 1495:
1.4 ! moko 1496: (*phandle)->next = handles;
! 1497: handles = *phandle;
1.2 paf 1498: }
1499:
1.4 ! moko 1500: LT__SETERRORSTR (saved_error);
1.2 paf 1501:
1502: cleanup:
1.4 ! moko 1503: FREE (dir);
! 1504: FREE (attempt);
! 1505: FREE (name);
! 1506: if (!canonical) /* was MEMREASSIGNed */
! 1507: FREE (base_name);
! 1508: FREE (canonical);
! 1509: FREE (archive_name);
1.2 paf 1510:
1511: return errors;
1512: }
1513:
1.4 ! moko 1514:
! 1515: /* If the last error message stored was `FILE_NOT_FOUND', then return
! 1516: non-zero. */
! 1517: static int
! 1518: file_not_found (void)
1.2 paf 1519: {
1.4 ! moko 1520: const char *error = 0;
1.1 parser 1521:
1.4 ! moko 1522: LT__GETERROR (error);
! 1523: if (error == LT__STRERROR (FILE_NOT_FOUND))
! 1524: return 1;
1.2 paf 1525:
1.4 ! moko 1526: return 0;
1.2 paf 1527: }
1528:
1.4 ! moko 1529:
! 1530: /* Unless FILENAME already bears a suitable library extension, then
! 1531: return 0. */
1.1 parser 1532: static int
1.4 ! moko 1533: has_library_ext (const char *filename)
! 1534: {
! 1535: const char * ext = 0;
! 1536:
! 1537: assert (filename);
! 1538:
! 1539: ext = strrchr (filename, '.');
! 1540:
! 1541: if (ext && ((streq (ext, archive_ext))
! 1542: #if defined(LT_MODULE_EXT)
! 1543: || (streq (ext, shlib_ext))
! 1544: #endif
! 1545: #if defined(LT_SHARED_EXT)
! 1546: || (streq (ext, shared_ext))
! 1547: #endif
! 1548: ))
! 1549: {
! 1550: return 1;
! 1551: }
! 1552:
! 1553: return 0;
! 1554: }
! 1555:
! 1556:
! 1557: /* Initialise and configure a user lt_dladvise opaque object. */
! 1558:
! 1559: int
! 1560: lt_dladvise_init (lt_dladvise *padvise)
! 1561: {
! 1562: lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
! 1563: *padvise = advise;
! 1564: return (advise ? 0 : 1);
! 1565: }
! 1566:
! 1567: int
! 1568: lt_dladvise_destroy (lt_dladvise *padvise)
! 1569: {
! 1570: if (padvise)
! 1571: FREE(*padvise);
! 1572: return 0;
! 1573: }
! 1574:
! 1575: int
! 1576: lt_dladvise_ext (lt_dladvise *padvise)
! 1577: {
! 1578: assert (padvise && *padvise);
! 1579: (*padvise)->try_ext = 1;
! 1580: return 0;
! 1581: }
! 1582:
! 1583: int
! 1584: lt_dladvise_resident (lt_dladvise *padvise)
! 1585: {
! 1586: assert (padvise && *padvise);
! 1587: (*padvise)->is_resident = 1;
! 1588: return 0;
! 1589: }
! 1590:
! 1591: int
! 1592: lt_dladvise_local (lt_dladvise *padvise)
1.2 paf 1593: {
1.4 ! moko 1594: assert (padvise && *padvise);
! 1595: (*padvise)->is_symlocal = 1;
! 1596: return 0;
! 1597: }
1.2 paf 1598:
1.4 ! moko 1599: int
! 1600: lt_dladvise_global (lt_dladvise *padvise)
! 1601: {
! 1602: assert (padvise && *padvise);
! 1603: (*padvise)->is_symglobal = 1;
! 1604: return 0;
! 1605: }
1.2 paf 1606:
1.4 ! moko 1607: int
! 1608: lt_dladvise_preload (lt_dladvise *padvise)
! 1609: {
! 1610: assert (padvise && *padvise);
! 1611: (*padvise)->try_preload_only = 1;
1.2 paf 1612: return 0;
1613: }
1614:
1.4 ! moko 1615: /* Libtool-1.5.x interface for loading a new module named FILENAME. */
! 1616: lt_dlhandle
! 1617: lt_dlopen (const char *filename)
! 1618: {
! 1619: return lt_dlopenadvise (filename, NULL);
! 1620: }
! 1621:
! 1622:
! 1623: /* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to
1.2 paf 1624: open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
1.4 ! moko 1625: and if a file is still not found try again with MODULE_EXT appended
1.2 paf 1626: instead. */
1627: lt_dlhandle
1.4 ! moko 1628: lt_dlopenext (const char *filename)
1.1 parser 1629: {
1.4 ! moko 1630: lt_dlhandle handle = 0;
! 1631: lt_dladvise advise;
1.2 paf 1632:
1.4 ! moko 1633: if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
! 1634: handle = lt_dlopenadvise (filename, advise);
1.2 paf 1635:
1.4 ! moko 1636: lt_dladvise_destroy (&advise);
! 1637: return handle;
! 1638: }
1.2 paf 1639:
1640:
1.4 ! moko 1641: lt_dlhandle
! 1642: lt_dlopenadvise (const char *filename, lt_dladvise advise)
! 1643: {
! 1644: lt_dlhandle handle = 0;
! 1645: int errors = 0;
! 1646: const char * saved_error = 0;
1.2 paf 1647:
1.4 ! moko 1648: LT__GETERROR (saved_error);
1.2 paf 1649:
1.4 ! moko 1650: /* Can't have symbols hidden and visible at the same time! */
! 1651: if (advise && advise->is_symlocal && advise->is_symglobal)
1.2 paf 1652: {
1.4 ! moko 1653: LT__SETERROR (CONFLICTING_FLAGS);
! 1654: return 0;
1.2 paf 1655: }
1656:
1.4 ! moko 1657: if (!filename
! 1658: || !advise
! 1659: || !advise->try_ext
! 1660: || has_library_ext (filename))
! 1661: {
! 1662: /* Just incase we missed a code path in try_dlopen() that reports
! 1663: an error, but forgot to reset handle... */
! 1664: if (try_dlopen (&handle, filename, NULL, advise) != 0)
1.1 parser 1665: return 0;
1.2 paf 1666:
1.4 ! moko 1667: return handle;
1.2 paf 1668: }
1.4 ! moko 1669: else if (filename && *filename)
1.2 paf 1670: {
1671:
1.4 ! moko 1672: /* First try appending ARCHIVE_EXT. */
! 1673: errors += try_dlopen (&handle, filename, archive_ext, advise);
1.2 paf 1674:
1.4 ! moko 1675: /* If we found FILENAME, stop searching -- whether we were able to
! 1676: load the file as a module or not. If the file exists but loading
! 1677: failed, it is better to return an error message here than to
! 1678: report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
! 1679: in the module search path. */
! 1680: if (handle || ((errors > 0) && !file_not_found ()))
! 1681: return handle;
! 1682:
! 1683: #if defined(LT_MODULE_EXT)
! 1684: /* Try appending SHLIB_EXT. */
! 1685: LT__SETERRORSTR (saved_error);
! 1686: errors = try_dlopen (&handle, filename, shlib_ext, advise);
! 1687:
! 1688: /* As before, if the file was found but loading failed, return now
! 1689: with the current error message. */
! 1690: if (handle || ((errors > 0) && !file_not_found ()))
! 1691: return handle;
! 1692: #endif
! 1693:
! 1694: #if defined(LT_SHARED_EXT)
! 1695: /* Try appending SHARED_EXT. */
! 1696: LT__SETERRORSTR (saved_error);
! 1697: errors = try_dlopen (&handle, filename, shared_ext, advise);
! 1698:
! 1699: /* As before, if the file was found but loading failed, return now
! 1700: with the current error message. */
! 1701: if (handle || ((errors > 0) && !file_not_found ()))
! 1702: return handle;
! 1703: #endif
1.2 paf 1704: }
1705:
1706: /* Still here? Then we really did fail to locate any of the file
1707: names we tried. */
1.4 ! moko 1708: LT__SETERROR (FILE_NOT_FOUND);
1.2 paf 1709: return 0;
1.1 parser 1710: }
1711:
1.2 paf 1712:
1.1 parser 1713: static int
1.4 ! moko 1714: lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
! 1715: const char *entry)
1.1 parser 1716: {
1.2 paf 1717: error_t error;
1718:
1.4 ! moko 1719: /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
! 1720: pargz_len, NULL, entry) failed with EINVAL. */
! 1721: if (before)
! 1722: error = argz_insert (pargz, pargz_len, before, entry);
! 1723: else
! 1724: error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
! 1725:
! 1726: if (error)
1.2 paf 1727: {
1728: switch (error)
1729: {
1730: case ENOMEM:
1.4 ! moko 1731: LT__SETERROR (NO_MEMORY);
1.2 paf 1732: break;
1733: default:
1.4 ! moko 1734: LT__SETERROR (UNKNOWN);
1.2 paf 1735: break;
1.1 parser 1736: }
1.2 paf 1737: return 1;
1738: }
1739:
1740: return 0;
1.1 parser 1741: }
1742:
1743: static int
1.4 ! moko 1744: lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1.1 parser 1745: {
1.4 ! moko 1746: char *before = 0;
1.2 paf 1747:
1748: assert (pargz);
1749: assert (pargz_len);
1750: assert (entry && *entry);
1751:
1752: if (*pargz)
1753: while ((before = argz_next (*pargz, *pargz_len, before)))
1754: {
1755: int cmp = strcmp (entry, before);
1756:
1757: if (cmp < 0) break;
1758: if (cmp == 0) return 0; /* No duplicates! */
1759: }
1760:
1761: return lt_argz_insert (pargz, pargz_len, before, entry);
1.1 parser 1762: }
1763:
1764: static int
1.4 ! moko 1765: lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
! 1766: struct dirent *dp)
1.1 parser 1767: {
1.4 ! moko 1768: char *buf = 0;
1.2 paf 1769: size_t buf_len = 0;
1.4 ! moko 1770: char *end = 0;
1.2 paf 1771: size_t end_offset = 0;
1772: size_t dir_len = 0;
1773: int errors = 0;
1774:
1775: assert (pargz);
1776: assert (pargz_len);
1777: assert (dp);
1778:
1779: dir_len = LT_STRLEN (dirnam);
1.4 ! moko 1780: end = dp->d_name + D_NAMLEN(dp);
1.2 paf 1781:
1782: /* Ignore version numbers. */
1783: {
1784: char *p;
1785: for (p = end; p -1 > dp->d_name; --p)
1786: if (strchr (".0123456789", p[-1]) == 0)
1787: break;
1788:
1789: if (*p == '.')
1790: end = p;
1791: }
1792:
1793: /* Ignore filename extension. */
1794: {
1795: char *p;
1796: for (p = end -1; p > dp->d_name; --p)
1797: if (*p == '.')
1798: {
1799: end = p;
1800: break;
1.1 parser 1801: }
1.2 paf 1802: }
1803:
1804: /* Prepend the directory name. */
1805: end_offset = end - dp->d_name;
1806: buf_len = dir_len + 1+ end_offset;
1.4 ! moko 1807: buf = MALLOC (char, 1+ buf_len);
1.2 paf 1808: if (!buf)
1809: return ++errors;
1810:
1811: assert (buf);
1812:
1813: strcpy (buf, dirnam);
1814: strcat (buf, "/");
1815: strncat (buf, dp->d_name, end_offset);
1816: buf[buf_len] = LT_EOS_CHAR;
1817:
1818: /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
1819: if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1820: ++errors;
1821:
1.4 ! moko 1822: FREE (buf);
1.2 paf 1823:
1824: return errors;
1.1 parser 1825: }
1826:
1827: static int
1.4 ! moko 1828: list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1.2 paf 1829: {
1.4 ! moko 1830: DIR *dirp = 0;
1.2 paf 1831: int errors = 0;
1832:
1833: assert (dirnam && *dirnam);
1834: assert (pargz);
1835: assert (pargz_len);
1836: assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
1837:
1838: dirp = opendir (dirnam);
1839: if (dirp)
1840: {
1.4 ! moko 1841: struct dirent *dp = 0;
1.2 paf 1842:
1843: while ((dp = readdir (dirp)))
1844: if (dp->d_name[0] != '.')
1845: if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
1846: {
1847: ++errors;
1848: break;
1849: }
1850:
1851: closedir (dirp);
1852: }
1853: else
1854: ++errors;
1855:
1856: return errors;
1.1 parser 1857: }
1858:
1.2 paf 1859:
1860: /* If there are any files in DIRNAME, call the function passed in
1861: DATA1 (with the name of each file and DATA2 as arguments). */
1.1 parser 1862: static int
1.4 ! moko 1863: foreachfile_callback (char *dirname, void *data1, void *data2)
1.1 parser 1864: {
1.4 ! moko 1865: file_worker_func *func = *(file_worker_func **) data1;
1.2 paf 1866:
1867: int is_done = 0;
1.4 ! moko 1868: char *argz = 0;
1.2 paf 1869: size_t argz_len = 0;
1870:
1871: if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
1872: goto cleanup;
1873: if (!argz)
1874: goto cleanup;
1875:
1876: {
1.4 ! moko 1877: char *filename = 0;
1.2 paf 1878: while ((filename = argz_next (argz, argz_len, filename)))
1879: if ((is_done = (*func) (filename, data2)))
1880: break;
1881: }
1882:
1883: cleanup:
1.4 ! moko 1884: FREE (argz);
1.2 paf 1885:
1886: return is_done;
1.1 parser 1887: }
1888:
1.2 paf 1889:
1890: /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
1891: with DATA. The filenames passed to FUNC would be suitable for
1892: passing to lt_dlopenext. The extensions are stripped so that
1893: individual modules do not generate several entries (e.g. libfoo.la,
1894: libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
1895: then the same directories that lt_dlopen would search are examined. */
1896: int
1.4 ! moko 1897: lt_dlforeachfile (const char *search_path,
! 1898: int (*func) (const char *filename, void *data),
! 1899: void *data)
1.2 paf 1900: {
1901: int is_done = 0;
1.4 ! moko 1902: file_worker_func **fpptr = &func;
1.2 paf 1903:
1904: if (search_path)
1905: {
1906: /* If a specific path was passed, search only the directories
1907: listed in it. */
1908: is_done = foreach_dirinpath (search_path, 0,
1.4 ! moko 1909: foreachfile_callback, fpptr, data);
1.2 paf 1910: }
1911: else
1912: {
1913: /* Otherwise search the default paths. */
1914: is_done = foreach_dirinpath (user_search_path, 0,
1.4 ! moko 1915: foreachfile_callback, fpptr, data);
1.2 paf 1916: if (!is_done)
1917: {
1.4 ! moko 1918: is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
! 1919: foreachfile_callback, fpptr, data);
1.1 parser 1920: }
1921:
1.4 ! moko 1922: #if defined(LT_MODULE_PATH_VAR)
1.2 paf 1923: if (!is_done)
1924: {
1.4 ! moko 1925: is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
! 1926: foreachfile_callback, fpptr, data);
1.2 paf 1927: }
1928: #endif
1.4 ! moko 1929: #if defined(LT_DLSEARCH_PATH)
! 1930: if (!is_done && *sys_dlsearch_path)
1.2 paf 1931: {
1.4 ! moko 1932: is_done = foreach_dirinpath (sys_dlsearch_path, 0,
! 1933: foreachfile_callback, fpptr, data);
1.2 paf 1934: }
1935: #endif
1936: }
1.1 parser 1937:
1.2 paf 1938: return is_done;
1939: }
1.1 parser 1940:
1941: int
1.4 ! moko 1942: lt_dlclose (lt_dlhandle handle)
1.1 parser 1943: {
1.2 paf 1944: lt_dlhandle cur, last;
1945: int errors = 0;
1946:
1947: /* check whether the handle is valid */
1948: last = cur = handles;
1949: while (cur && handle != cur)
1950: {
1951: last = cur;
1952: cur = cur->next;
1953: }
1954:
1955: if (!cur)
1956: {
1.4 ! moko 1957: LT__SETERROR (INVALID_HANDLE);
1.2 paf 1958: ++errors;
1959: goto done;
1960: }
1961:
1.4 ! moko 1962: cur = handle;
! 1963: cur->info.ref_count--;
1.2 paf 1964:
1965: /* Note that even with resident modules, we must track the ref_count
1966: correctly incase the user decides to reset the residency flag
1967: later (even though the API makes no provision for that at the
1968: moment). */
1.4 ! moko 1969: if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1.2 paf 1970: {
1.4 ! moko 1971: lt_user_data data = cur->vtable->dlloader_data;
1.2 paf 1972:
1.4 ! moko 1973: if (cur != handles)
1.2 paf 1974: {
1.4 ! moko 1975: last->next = cur->next;
1.1 parser 1976: }
1.2 paf 1977: else
1978: {
1.4 ! moko 1979: handles = cur->next;
1.1 parser 1980: }
1.2 paf 1981:
1.4 ! moko 1982: errors += cur->vtable->module_close (data, cur->module);
! 1983: errors += unload_deplibs (handle);
1.2 paf 1984:
1985: /* It is up to the callers to free the data itself. */
1.4 ! moko 1986: FREE (cur->interface_data);
1.2 paf 1987:
1.4 ! moko 1988: FREE (cur->info.filename);
! 1989: FREE (cur->info.name);
! 1990: FREE (cur);
1.2 paf 1991:
1992: goto done;
1993: }
1994:
1995: if (LT_DLIS_RESIDENT (handle))
1996: {
1.4 ! moko 1997: LT__SETERROR (CLOSE_RESIDENT_MODULE);
1.2 paf 1998: ++errors;
1999: }
2000:
2001: done:
2002: return errors;
1.1 parser 2003: }
2004:
1.4 ! moko 2005: void *
! 2006: lt_dlsym (lt_dlhandle place, const char *symbol)
1.1 parser 2007: {
1.2 paf 2008: size_t lensym;
2009: char lsym[LT_SYMBOL_LENGTH];
2010: char *sym;
1.4 ! moko 2011: void *address;
1.2 paf 2012: lt_user_data data;
1.4 ! moko 2013: lt_dlhandle handle;
1.2 paf 2014:
1.4 ! moko 2015: if (!place)
1.2 paf 2016: {
1.4 ! moko 2017: LT__SETERROR (INVALID_HANDLE);
1.2 paf 2018: return 0;
2019: }
2020:
1.4 ! moko 2021: handle = place;
! 2022:
1.2 paf 2023: if (!symbol)
2024: {
1.4 ! moko 2025: LT__SETERROR (SYMBOL_NOT_FOUND);
1.2 paf 2026: return 0;
2027: }
2028:
1.4 ! moko 2029: lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
1.2 paf 2030: + LT_STRLEN (handle->info.name);
2031:
2032: if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
2033: {
2034: sym = lsym;
2035: }
2036: else
2037: {
1.4 ! moko 2038: sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
1.2 paf 2039: if (!sym)
2040: {
1.4 ! moko 2041: LT__SETERROR (BUFFER_OVERFLOW);
1.2 paf 2042: return 0;
2043: }
2044: }
2045:
1.4 ! moko 2046: data = handle->vtable->dlloader_data;
1.2 paf 2047: if (handle->info.name)
2048: {
2049: const char *saved_error;
2050:
1.4 ! moko 2051: LT__GETERROR (saved_error);
1.2 paf 2052:
2053: /* this is a libtool module */
1.4 ! moko 2054: if (handle->vtable->sym_prefix)
1.2 paf 2055: {
1.4 ! moko 2056: strcpy(sym, handle->vtable->sym_prefix);
1.2 paf 2057: strcat(sym, handle->info.name);
2058: }
2059: else
2060: {
2061: strcpy(sym, handle->info.name);
2062: }
2063:
2064: strcat(sym, "_LTX_");
2065: strcat(sym, symbol);
2066:
2067: /* try "modulename_LTX_symbol" */
1.4 ! moko 2068: address = handle->vtable->find_sym (data, handle->module, sym);
1.2 paf 2069: if (address)
2070: {
2071: if (sym != lsym)
2072: {
1.4 ! moko 2073: FREE (sym);
1.2 paf 2074: }
2075: return address;
2076: }
1.4 ! moko 2077: LT__SETERRORSTR (saved_error);
1.2 paf 2078: }
2079:
2080: /* otherwise try "symbol" */
1.4 ! moko 2081: if (handle->vtable->sym_prefix)
1.2 paf 2082: {
1.4 ! moko 2083: strcpy(sym, handle->vtable->sym_prefix);
1.2 paf 2084: strcat(sym, symbol);
2085: }
2086: else
2087: {
2088: strcpy(sym, symbol);
2089: }
2090:
1.4 ! moko 2091: address = handle->vtable->find_sym (data, handle->module, sym);
1.2 paf 2092: if (sym != lsym)
2093: {
1.4 ! moko 2094: FREE (sym);
1.2 paf 2095: }
2096:
2097: return address;
1.1 parser 2098: }
2099:
1.2 paf 2100: const char *
1.4 ! moko 2101: lt_dlerror (void)
1.1 parser 2102: {
1.2 paf 2103: const char *error;
2104:
1.4 ! moko 2105: LT__GETERROR (error);
! 2106: LT__SETERRORSTR (0);
1.2 paf 2107:
1.4 ! moko 2108: return error;
1.1 parser 2109: }
2110:
1.2 paf 2111: static int
1.4 ! moko 2112: lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
1.1 parser 2113: {
1.2 paf 2114: int errors = 0;
1.4 ! moko 2115: char *canonical = 0;
! 2116: char *argz = 0;
1.2 paf 2117: size_t argz_len = 0;
2118:
2119: assert (ppath);
2120: assert (dir && *dir);
2121:
2122: if (canonicalize_path (dir, &canonical) != 0)
2123: {
2124: ++errors;
2125: goto cleanup;
2126: }
2127:
2128: assert (canonical && *canonical);
2129:
2130: /* If *PPATH is empty, set it to DIR. */
1.4 ! moko 2131: if (*ppath == 0)
1.2 paf 2132: {
2133: assert (!before); /* BEFORE cannot be set without PPATH. */
2134: assert (dir); /* Without DIR, don't call this function! */
2135:
1.4 ! moko 2136: *ppath = lt__strdup (dir);
! 2137: if (*ppath == 0)
1.2 paf 2138: ++errors;
2139:
1.4 ! moko 2140: goto cleanup;
1.2 paf 2141: }
2142:
2143: assert (ppath && *ppath);
2144:
2145: if (argzize_path (*ppath, &argz, &argz_len) != 0)
2146: {
2147: ++errors;
2148: goto cleanup;
2149: }
2150:
2151: /* Convert BEFORE into an equivalent offset into ARGZ. This only works
2152: if *PPATH is already canonicalized, and hence does not change length
2153: with respect to ARGZ. We canonicalize each entry as it is added to
2154: the search path, and don't call this function with (uncanonicalized)
2155: user paths, so this is a fair assumption. */
2156: if (before)
2157: {
2158: assert (*ppath <= before);
1.4 ! moko 2159: assert ((int) (before - *ppath) <= (int) strlen (*ppath));
1.2 paf 2160:
2161: before = before - *ppath + argz;
2162: }
2163:
2164: if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2165: {
2166: ++errors;
2167: goto cleanup;
2168: }
2169:
2170: argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
1.4 ! moko 2171: MEMREASSIGN(*ppath, argz);
1.2 paf 2172:
2173: cleanup:
1.4 ! moko 2174: FREE (argz);
! 2175: FREE (canonical);
1.2 paf 2176:
2177: return errors;
1.1 parser 2178: }
2179:
1.2 paf 2180: int
1.4 ! moko 2181: lt_dladdsearchdir (const char *search_dir)
1.1 parser 2182: {
1.2 paf 2183: int errors = 0;
2184:
2185: if (search_dir && *search_dir)
2186: {
2187: if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2188: ++errors;
2189: }
2190:
2191: return errors;
1.1 parser 2192: }
2193:
1.2 paf 2194: int
1.4 ! moko 2195: lt_dlinsertsearchdir (const char *before, const char *search_dir)
1.2 paf 2196: {
2197: int errors = 0;
2198:
2199: if (before)
2200: {
2201: if ((before < user_search_path)
2202: || (before >= user_search_path + LT_STRLEN (user_search_path)))
2203: {
1.4 ! moko 2204: LT__SETERROR (INVALID_POSITION);
1.2 paf 2205: return 1;
2206: }
2207: }
2208:
2209: if (search_dir && *search_dir)
2210: {
2211: if (lt_dlpath_insertdir (&user_search_path,
2212: (char *) before, search_dir) != 0)
2213: {
2214: ++errors;
1.1 parser 2215: }
1.2 paf 2216: }
2217:
2218: return errors;
1.1 parser 2219: }
2220:
1.2 paf 2221: int
1.4 ! moko 2222: lt_dlsetsearchpath (const char *search_path)
1.2 paf 2223: {
2224: int errors = 0;
2225:
1.4 ! moko 2226: FREE (user_search_path);
1.2 paf 2227:
2228: if (!search_path || !LT_STRLEN (search_path))
2229: {
2230: return errors;
2231: }
2232:
2233: if (canonicalize_path (search_path, &user_search_path) != 0)
2234: ++errors;
2235:
2236: return errors;
1.1 parser 2237: }
2238:
1.2 paf 2239: const char *
1.4 ! moko 2240: lt_dlgetsearchpath (void)
1.2 paf 2241: {
2242: const char *saved_path;
2243:
2244: saved_path = user_search_path;
2245:
2246: return saved_path;
1.1 parser 2247: }
2248:
1.2 paf 2249: int
1.4 ! moko 2250: lt_dlmakeresident (lt_dlhandle handle)
1.1 parser 2251: {
1.2 paf 2252: int errors = 0;
2253:
2254: if (!handle)
2255: {
1.4 ! moko 2256: LT__SETERROR (INVALID_HANDLE);
1.2 paf 2257: ++errors;
2258: }
2259: else
2260: {
1.4 ! moko 2261: handle->info.is_resident = 1;
1.2 paf 2262: }
2263:
2264: return errors;
1.1 parser 2265: }
2266:
1.2 paf 2267: int
1.4 ! moko 2268: lt_dlisresident (lt_dlhandle handle)
1.1 parser 2269: {
1.2 paf 2270: if (!handle)
2271: {
1.4 ! moko 2272: LT__SETERROR (INVALID_HANDLE);
1.2 paf 2273: return -1;
2274: }
2275:
2276: return LT_DLIS_RESIDENT (handle);
1.1 parser 2277: }
2278:
1.2 paf 2279:
2280:
2281: /* --- MODULE INFORMATION --- */
2282:
1.4 ! moko 2283: typedef struct {
! 2284: const char *id_string;
! 2285: lt_dlhandle_interface *iface;
! 2286: } lt__interface_id;
! 2287:
! 2288: lt_dlinterface_id
! 2289: lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
! 2290: {
! 2291: lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
! 2292:
! 2293: /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
! 2294: can then be detected with lt_dlerror() if we return 0. */
! 2295: if (interface_id)
! 2296: {
! 2297: interface_id->id_string = lt__strdup (id_string);
! 2298: if (!interface_id->id_string)
! 2299: FREE (interface_id);
! 2300: else
! 2301: interface_id->iface = iface;
1.2 paf 2302: }
2303:
1.4 ! moko 2304: return (lt_dlinterface_id) interface_id;
1.1 parser 2305: }
2306:
1.4 ! moko 2307: void lt_dlinterface_free (lt_dlinterface_id key)
1.1 parser 2308: {
1.4 ! moko 2309: lt__interface_id *interface_id = (lt__interface_id *)key;
! 2310: FREE (interface_id->id_string);
! 2311: FREE (interface_id);
1.1 parser 2312: }
2313:
1.4 ! moko 2314: void *
! 2315: lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
1.1 parser 2316: {
1.2 paf 2317: int n_elements = 0;
1.4 ! moko 2318: void *stale = (void *) 0;
! 2319: lt_dlhandle cur = handle;
1.2 paf 2320: int i;
2321:
1.4 ! moko 2322: if (cur->interface_data)
! 2323: while (cur->interface_data[n_elements].key)
1.2 paf 2324: ++n_elements;
2325:
2326: for (i = 0; i < n_elements; ++i)
2327: {
1.4 ! moko 2328: if (cur->interface_data[i].key == key)
1.2 paf 2329: {
1.4 ! moko 2330: stale = cur->interface_data[i].data;
1.2 paf 2331: break;
2332: }
2333: }
2334:
1.4 ! moko 2335: /* Ensure that there is enough room in this handle's interface_data
1.2 paf 2336: array to accept a new element (and an empty end marker). */
2337: if (i == n_elements)
2338: {
1.4 ! moko 2339: lt_interface_data *temp
! 2340: = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
1.2 paf 2341:
2342: if (!temp)
2343: {
1.4 ! moko 2344: stale = 0;
1.2 paf 2345: goto done;
1.1 parser 2346: }
1.2 paf 2347:
1.4 ! moko 2348: cur->interface_data = temp;
1.2 paf 2349:
1.4 ! moko 2350: /* We only need this if we needed to allocate a new interface_data. */
! 2351: cur->interface_data[i].key = key;
! 2352: cur->interface_data[1+ i].key = 0;
1.2 paf 2353: }
2354:
1.4 ! moko 2355: cur->interface_data[i].data = data;
1.2 paf 2356:
2357: done:
2358: return stale;
1.1 parser 2359: }
2360:
1.4 ! moko 2361: void *
! 2362: lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
! 2363: {
! 2364: void *result = (void *) 0;
! 2365: lt_dlhandle cur = handle;
1.2 paf 2366:
2367: /* Locate the index of the element with a matching KEY. */
1.4 ! moko 2368: if (cur->interface_data)
! 2369: {
! 2370: int i;
! 2371: for (i = 0; cur->interface_data[i].key; ++i)
! 2372: {
! 2373: if (cur->interface_data[i].key == key)
! 2374: {
! 2375: result = cur->interface_data[i].data;
! 2376: break;
! 2377: }
! 2378: }
! 2379: }
1.2 paf 2380:
2381: return result;
1.1 parser 2382: }
2383:
1.4 ! moko 2384: const lt_dlinfo *
! 2385: lt_dlgetinfo (lt_dlhandle handle)
1.2 paf 2386: {
1.4 ! moko 2387: if (!handle)
1.2 paf 2388: {
1.4 ! moko 2389: LT__SETERROR (INVALID_HANDLE);
! 2390: return 0;
1.2 paf 2391: }
2392:
1.4 ! moko 2393: return &(handle->info);
! 2394: }
1.2 paf 2395:
2396:
1.4 ! moko 2397: lt_dlhandle
! 2398: lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
1.1 parser 2399: {
1.4 ! moko 2400: lt_dlhandle handle = place;
! 2401: lt__interface_id *iterator = (lt__interface_id *) iface;
1.2 paf 2402:
1.4 ! moko 2403: assert (iface); /* iface is a required argument */
1.2 paf 2404:
1.4 ! moko 2405: if (!handle)
! 2406: handle = handles;
1.2 paf 2407: else
1.4 ! moko 2408: handle = handle->next;
1.2 paf 2409:
1.4 ! moko 2410: /* advance while the interface check fails */
! 2411: while (handle && iterator->iface
! 2412: && ((*iterator->iface) (handle, iterator->id_string) != 0))
1.2 paf 2413: {
1.4 ! moko 2414: handle = handle->next;
1.2 paf 2415: }
2416:
1.4 ! moko 2417: return handle;
! 2418: }
1.2 paf 2419:
2420:
1.4 ! moko 2421: lt_dlhandle
! 2422: lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
1.2 paf 2423: {
1.4 ! moko 2424: lt_dlhandle handle = 0;
1.1 parser 2425:
1.4 ! moko 2426: assert (iface); /* iface is a required argument */
1.2 paf 2427:
1.4 ! moko 2428: while ((handle = lt_dlhandle_iterate (iface, handle)))
1.2 paf 2429: {
1.4 ! moko 2430: lt_dlhandle cur = handle;
! 2431: if (cur && cur->info.name && streq (cur->info.name, module_name))
! 2432: break;
1.2 paf 2433: }
2434:
1.4 ! moko 2435: return handle;
1.2 paf 2436: }
2437:
1.4 ! moko 2438:
! 2439: int
! 2440: lt_dlhandle_map (lt_dlinterface_id iface,
! 2441: int (*func) (lt_dlhandle handle, void *data), void *data)
1.2 paf 2442: {
1.4 ! moko 2443: lt__interface_id *iterator = (lt__interface_id *) iface;
! 2444: lt_dlhandle cur = handles;
1.2 paf 2445:
1.4 ! moko 2446: assert (iface); /* iface is a required argument */
! 2447:
! 2448: while (cur)
1.2 paf 2449: {
1.4 ! moko 2450: int errorcode = 0;
1.2 paf 2451:
1.4 ! moko 2452: /* advance while the interface check fails */
! 2453: while (cur && iterator->iface
! 2454: && ((*iterator->iface) (cur, iterator->id_string) != 0))
1.2 paf 2455: {
1.4 ! moko 2456: cur = cur->next;
1.2 paf 2457: }
1.4 ! moko 2458:
! 2459: if ((errorcode = (*func) (cur, data)) != 0)
! 2460: return errorcode;
1.2 paf 2461: }
2462:
1.4 ! moko 2463: return 0;
1.1 parser 2464: }
E-mail: