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