This source file includes following definitions.
- lt__alloc_die_callback
- loader_init_callback
- loader_init
- lt_dlinit
- lt_dlexit
- tryall_dlopen
- tryall_dlopen_module
- find_module
- canonicalize_path
- argzize_path
- foreach_dirinpath
- find_file_callback
- find_file
- find_handle_callback
- find_handle
- load_deplibs
- load_deplibs
- unload_deplibs
- trim
- parse_dotla_file
- try_dlopen
- file_not_found
- has_library_ext
- lt_dladvise_init
- lt_dladvise_destroy
- lt_dladvise_ext
- lt_dladvise_resident
- lt_dladvise_local
- lt_dladvise_global
- lt_dladvise_preload
- lt_dlopen
- lt_dlopenext
- lt_dlopenadvise
- lt_argz_insert
- lt_argz_insertinorder
- lt_argz_insertdir
- list_files_by_dir
- foreachfile_callback
- lt_dlforeachfile
- lt_dlclose
- lt_dlsym
- lt_dlerror
- lt_dlpath_insertdir
- lt_dladdsearchdir
- lt_dlinsertsearchdir
- lt_dlsetsearchpath
- lt_dlgetsearchpath
- lt_dlmakeresident
- lt_dlisresident
- lt_dlinterface_register
- lt_dlinterface_free
- lt_dlcaller_set_data
- lt_dlcaller_get_data
- lt_dlgetinfo
- lt_dlhandle_iterate
- lt_dlhandle_fetch
- lt_dlhandle_map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include "lt__private.h"
33 #include "lt_system.h"
34 #include "lt_dlloader.h"
35
36
37
38
39
40
41 #undef LTDL_SEARCHPATH_VAR
42 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
43
44
45 #undef LT_ARCHIVE_EXT
46 #define LT_ARCHIVE_EXT ".la"
47
48
49 #if !defined(LT_FILENAME_MAX)
50 # define LT_FILENAME_MAX 1024
51 #endif
52
53 #if !defined(LT_LIBEXT)
54 # define LT_LIBEXT "a"
55 #endif
56
57 #if !defined(LT_LIBPREFIX)
58 # define LT_LIBPREFIX "lib"
59 #endif
60
61
62 #undef LT_SYMBOL_LENGTH
63 #define LT_SYMBOL_LENGTH 128
64
65
66 #undef LT_SYMBOL_OVERHEAD
67 #define LT_SYMBOL_OVERHEAD 5
68
69
70
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
84
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
91
92
93
94
95
96
97
98
99 typedef int foreach_callback_func (char *filename, void *data1,
100 void *data2);
101
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
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
165
166
167 void
168 lt__alloc_die_callback (void)
169 {
170 LT__SETERROR (NO_MEMORY);
171 }
172
173 #ifdef HAVE_LIBDLLOADER
174
175
176
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);
182 }
183 #endif
184
185 static int
186 loader_init (lt_get_vtable *vtable_func, lt_user_data data)
187 {
188 const lt_dlvtable *vtable = 0;
189 int errors = 0;
190
191 if (vtable_func)
192 {
193 vtable = (*vtable_func) (data);
194 }
195
196
197 errors += lt_dlloader_add (vtable);
198
199 assert (errors || vtable);
200
201 if ((!errors) && vtable->dlloader_init)
202 {
203 if ((*vtable->dlloader_init) (vtable->dlloader_data))
204 {
205 LT__SETERROR (INIT_LOADER);
206 ++errors;
207 }
208 }
209
210 return errors;
211 }
212
213
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
223
224
225 int
226 lt_dlinit (void)
227 {
228 int errors = 0;
229
230
231 if (++initialized == 1)
232 {
233 lt__alloc_die = lt__alloc_die_callback;
234 handles = 0;
235 user_search_path = 0;
236
237
238
239
240 errors += loader_init (get_vtable, 0);
241
242
243
244 #ifdef HAVE_LIBDLLOADER
245 if (!errors)
246 {
247 errors += lt_dlpreload (preloaded_symbols);
248 }
249
250 if (!errors)
251 {
252 errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
253 }
254 #endif
255 }
256
257 #ifdef LT_DEBUG_LOADERS
258 lt_dlloader_dump();
259 #endif
260
261 return errors;
262 }
263
264 int
265 lt_dlexit (void)
266 {
267
268 lt_dlloader *loader = 0;
269 lt_dlhandle handle = handles;
270 int errors = 0;
271
272 if (!initialized)
273 {
274 LT__SETERROR (SHUTDOWN);
275 ++errors;
276 goto done;
277 }
278
279
280 if (--initialized == 0)
281 {
282 int level;
283
284 while (handles && LT_DLIS_RESIDENT (handles))
285 {
286 handles = handles->next;
287 }
288
289
290 for (level = 1; handle; ++level)
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 {
301 saw_nonresident = 1;
302 if (tmp->info.ref_count <= level)
303 {
304 if (lt_dlclose (tmp))
305 {
306 ++errors;
307 }
308
309
310
311
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 }
320 }
321 }
322 }
323
324 if (!saw_nonresident)
325 break;
326 }
327
328
329
330
331 if (!errors)
332 LT__SETERRORSTR (0);
333
334
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
345 {
346
347 const char *err;
348 LT__GETERROR (err);
349 if (err)
350 ++errors;
351 }
352
353 loader = next;
354 }
355
356 FREE(user_search_path);
357 }
358
359 done:
360 return errors;
361 }
362
363
364
365
366
367 static int
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;
374
375 #ifdef LT_DEBUG_LOADERS
376 fprintf (stderr, "tryall_dlopen (%s, %s)\n",
377 filename ? filename : "(null)",
378 vtable ? vtable->name : "(ALL)");
379 #endif
380
381 LT__GETERROR (saved_error);
382
383
384 for (;handle; handle = handle->next)
385 {
386 if ((handle->info.filename == filename)
387 || (handle->info.filename && filename
388 && streq (handle->info.filename, filename)))
389 {
390 break;
391 }
392 }
393
394 if (handle)
395 {
396 ++handle->info.ref_count;
397 *phandle = handle;
398 goto done;
399 }
400
401 handle = *phandle;
402 if (filename)
403 {
404
405
406
407
408
409
410
411
412
413
414
415
416 handle->info.filename = lt__strdup (filename);
417 if (!handle->info.filename)
418 {
419 ++errors;
420 goto done;
421 }
422 }
423 else
424 {
425 handle->info.filename = 0;
426 }
427
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
450
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)));
463
464
465
466
467 if ((vtable && !handle->module)
468 || (!vtable && !loader))
469 {
470 FREE (handle->info.filename);
471 ++errors;
472 goto done;
473 }
474
475 handle->vtable = loader_vtable;
476 }
477
478 LT__SETERRORSTR (saved_error);
479
480 done:
481 return errors;
482 }
483
484
485 static int
486 tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
487 const char *dirname, const char *dlname,
488 lt_dladvise advise)
489 {
490 int error = 0;
491 char *filename = 0;
492 size_t filename_len = 0;
493 size_t dirname_len = LT_STRLEN (dirname);
494
495 assert (handle);
496 assert (dirname);
497 assert (dlname);
498 #if defined(LT_DIRSEP_CHAR)
499
500
501 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
502 #endif
503
504 if (dirname_len > 0)
505 if (dirname[dirname_len -1] == '/')
506 --dirname_len;
507 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
508
509
510
511 filename = MALLOC (char, filename_len + 1);
512 if (!filename)
513 return 1;
514
515 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
516
517
518
519
520 if (prefix)
521 {
522 error += tryall_dlopen_module (handle, (const char *) 0,
523 prefix, filename, advise);
524 }
525 else if (tryall_dlopen (handle, filename, advise, 0) != 0)
526 {
527 ++error;
528 }
529
530 FREE (filename);
531 return error;
532 }
533
534 static int
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)
538 {
539
540
541
542 if (old_name && tryall_dlopen (handle, old_name,
543 advise, lt_dlloader_find ("lt_preopen") ) == 0)
544 {
545 return 0;
546 }
547
548
549 if (dlname)
550 {
551
552 if (installed && libdir)
553 {
554 if (tryall_dlopen_module (handle, (const char *) 0,
555 libdir, dlname, advise) == 0)
556 return 0;
557 }
558
559
560 if (!installed)
561 {
562 if (tryall_dlopen_module (handle, dir, objdir,
563 dlname, advise) == 0)
564 return 0;
565 }
566
567
568 {
569 if (dir && (tryall_dlopen_module (handle, (const char *) 0,
570 dir, dlname, advise) == 0))
571 return 0;
572 }
573 }
574
575 return 1;
576 }
577
578
579 static int
580 canonicalize_path (const char *path, char **pcanonical)
581 {
582 char *canonical = 0;
583
584 assert (path && *path);
585 assert (pcanonical);
586
587 canonical = MALLOC (char, 1+ LT_STRLEN (path));
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
597
598
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
608 if ((path[src] != '/')
609 #if defined(LT_DIRSEP_CHAR)
610 && (path[src] != LT_DIRSEP_CHAR)
611 #endif
612 )
613 {
614 canonical[dest++] = path[src];
615 }
616
617
618
619 else if ((path[1+ src] != LT_PATHSEP_CHAR)
620 && (path[1+ src] != LT_EOS_CHAR)
621 #if defined(LT_DIRSEP_CHAR)
622 && (path[1+ src] != LT_DIRSEP_CHAR)
623 #endif
624 && (path[1+ src] != '/'))
625 {
626 canonical[dest++] = '/';
627 }
628 }
629
630
631 canonical[dest] = LT_EOS_CHAR;
632 }
633
634
635 *pcanonical = canonical;
636
637 return 0;
638 }
639
640 static int
641 argzize_path (const char *path, char **pargz, size_t *pargz_len)
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:
654 LT__SETERROR (NO_MEMORY);
655 break;
656 default:
657 LT__SETERROR (UNKNOWN);
658 break;
659 }
660
661 return 1;
662 }
663
664 return 0;
665 }
666
667
668
669
670
671 static int
672 foreach_dirinpath (const char *search_path, const char *base_name,
673 foreach_callback_func *func, void *data1, void *data2)
674 {
675 int result = 0;
676 size_t filenamesize = 0;
677 size_t lenbase = LT_STRLEN (base_name);
678 size_t argz_len = 0;
679 char *argz = 0;
680 char *filename = 0;
681 char *canonical = 0;
682
683 if (!search_path || !*search_path)
684 {
685 LT__SETERROR (FILE_NOT_FOUND);
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 {
696 char *dir_name = 0;
697 while ((dir_name = argz_next (argz, argz_len, dir_name)))
698 {
699 size_t lendir = LT_STRLEN (dir_name);
700
701 if (1+ lendir + lenbase >= filenamesize)
702 {
703 FREE (filename);
704 filenamesize = 1+ lendir + 1+ lenbase;
705 filename = MALLOC (char, filenamesize);
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:
728 FREE (argz);
729 FREE (canonical);
730 FREE (filename);
731
732 return result;
733 }
734
735
736
737
738 static int
739 find_file_callback (char *filename, void *data1, void *data2)
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
756 FREE (*pdir);
757 *pdir = lt__strdup (filename);
758 is_done = (*pdir == 0) ? -1 : 1;
759 }
760
761 return is_done;
762 }
763
764 static FILE *
765 find_file (const char *search_path, const char *base_name, char **pdir)
766 {
767 FILE *file = 0;
768
769 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
770
771 return file;
772 }
773
774 static int
775 find_handle_callback (char *filename, void *data, void *data2)
776 {
777 lt_dlhandle *phandle = (lt_dlhandle *) data;
778 int notfound = access (filename, R_OK);
779 lt_dladvise advise = (lt_dladvise) data2;
780
781
782 if (notfound)
783 return 0;
784
785
786
787 if (tryall_dlopen (phandle, filename, advise, 0) != 0)
788 *phandle = 0;
789
790 return 1;
791 }
792
793
794
795 static lt_dlhandle *
796 find_handle (const char *search_path, const char *base_name,
797 lt_dlhandle *phandle, lt_dladvise advise)
798 {
799 if (!search_path)
800 return 0;
801
802 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
803 phandle, advise))
804 return 0;
805
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;
815 }
816
817 #else
818 static int
819 load_deplibs (lt_dlhandle handle, char *deplibs)
820 {
821 char *p, *save_search_path = 0;
822 int depcount = 0;
823 int i;
824 char **names = 0;
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 {
837 save_search_path = lt__strdup (user_search_path);
838 if (!save_search_path)
839 goto cleanup;
840 }
841
842
843 p = deplibs;
844 while (*p)
845 {
846 if (!isspace ((unsigned char) *p))
847 {
848 char *end = p+1;
849 while (*end && !isspace((unsigned char) *end))
850 {
851 ++end;
852 }
853
854 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
855 {
856 char save = *end;
857 *end = 0;
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
884 names = MALLOC (char *, depcount);
885 if (!names)
886 goto cleanup;
887
888
889 depcount = 0;
890 p = deplibs;
891 while (*p)
892 {
893 if (isspace ((unsigned char) *p))
894 {
895 ++p;
896 }
897 else
898 {
899 char *end = p+1;
900 while (*end && !isspace ((unsigned char) *end))
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;
909 *end = 0;
910 if (strncmp(p, "-l", 2) == 0)
911 {
912 size_t name_len = 3+ LT_STRLEN (p + 2);
913 name = MALLOC (char, 1+ name_len);
914 if (name)
915 sprintf (name, "lib%s", p+2);
916 }
917 else
918 name = lt__strdup(p);
919
920 if (!name)
921 goto cleanup_names;
922
923 names[depcount++] = name;
924 *end = save;
925 }
926 p = end;
927 }
928 }
929
930
931
932
933
934
935 if (depcount)
936 {
937 lt_dlhandle cur = handle;
938 int j = 0;
939
940 cur->deplibs = MALLOC (lt_dlhandle, depcount);
941 if (!cur->deplibs)
942 goto cleanup_names;
943
944 for (i = 0; i < depcount; ++i)
945 {
946 cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
947 if (cur->deplibs[j])
948 {
949 ++j;
950 }
951 }
952
953 cur->depcount = j;
954 errors = 0;
955 }
956
957 cleanup_names:
958 for (i = 0; i < depcount; ++i)
959 {
960 FREE (names[i]);
961 }
962
963 cleanup:
964 FREE (names);
965
966 if (save_search_path) {
967 MEMREASSIGN (user_search_path, save_search_path);
968 }
969
970 return errors;
971 }
972 #endif
973
974 static int
975 unload_deplibs (lt_dlhandle handle)
976 {
977 int i;
978 int errors = 0;
979 lt_dlhandle cur = handle;
980
981 if (cur->depcount)
982 {
983 for (i = 0; i < cur->depcount; ++i)
984 {
985 if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
986 {
987 errors += lt_dlclose (cur->deplibs[i]);
988 }
989 }
990 FREE (cur->deplibs);
991 }
992
993 return errors;
994 }
995
996 static int
997 trim (char **dest, const char *str)
998 {
999
1000
1001 const char *end = strrchr (str, '\'');
1002 size_t len = LT_STRLEN (str);
1003 char *tmp;
1004
1005 FREE (*dest);
1006
1007 if (!end || end == str)
1008 return 1;
1009
1010 if (len > 3 && str[0] == '\'')
1011 {
1012 tmp = MALLOC (char, end - str);
1013 if (!tmp)
1014 return 1;
1015
1016 memcpy(tmp, &str[1], (end - str) - 1);
1017 tmp[(end - str) - 1] = LT_EOS_CHAR;
1018 *dest = tmp;
1019 }
1020 else
1021 {
1022 *dest = 0;
1023 }
1024
1025 return 0;
1026 }
1027
1028
1029 static int
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);
1036
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
1052
1053
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
1091
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
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;
1147 }
1148
1149
1150
1151 static int
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;
1162 int errors = 0;
1163 lt_dlhandle newhandle;
1164
1165 assert (phandle);
1166 assert (*phandle == 0);
1167
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);
1175
1176
1177 if (!filename)
1178 {
1179 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1180 if (*phandle == 0)
1181 return 1;
1182
1183 newhandle = *phandle;
1184
1185
1186 newhandle->info.is_resident = 1;
1187
1188 if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
1189 {
1190 FREE (*phandle);
1191 return 1;
1192 }
1193
1194 goto register_handle;
1195 }
1196
1197 assert (filename && *filename);
1198
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
1214
1215
1216 if (canonicalize_path (attempt, &canonical) != 0)
1217 {
1218 ++errors;
1219 goto cleanup;
1220 }
1221
1222
1223
1224 base_name = strrchr (canonical, '/');
1225 if (base_name)
1226 {
1227 size_t dirlen = (1+ base_name) - canonical;
1228
1229 dir = MALLOC (char, 1+ dirlen);
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
1242 MEMREASSIGN (base_name, canonical);
1243
1244 assert (base_name && *base_name);
1245
1246 ext = strrchr (base_name, '.');
1247 if (!ext)
1248 {
1249 ext = base_name + LT_STRLEN (base_name);
1250 }
1251
1252
1253 name = MALLOC (char, ext - base_name + 1);
1254 if (!name)
1255 {
1256 ++errors;
1257 goto cleanup;
1258 }
1259
1260
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
1278
1279 if (!dir)
1280 {
1281 const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
1282
1283 if (vtable)
1284 {
1285
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
1297
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
1313
1314 FREE (*phandle);
1315 newhandle = NULL;
1316 }
1317 }
1318
1319
1320
1321 if (advise && advise->try_preload_only)
1322 {
1323 goto cleanup;
1324 }
1325
1326
1327 if (ext && streq (ext, archive_ext))
1328 {
1329
1330 FILE * file = 0;
1331 char * dlname = 0;
1332 char * old_name = 0;
1333 char * libdir = 0;
1334 char * deplibs = 0;
1335
1336
1337
1338
1339 int installed = 1;
1340
1341
1342
1343
1344
1345 if (!dir)
1346 {
1347 const char *search_path = user_search_path;
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
1359 #if defined(LT_MODULE_PATH_VAR)
1360 if (!file)
1361 {
1362 search_path = getenv (LT_MODULE_PATH_VAR);
1363 if (search_path)
1364 file = find_file (search_path, base_name, &dir);
1365 }
1366 #endif
1367 #if defined(LT_DLSEARCH_PATH)
1368 if (!file && *sys_dlsearch_path)
1369 {
1370 file = find_file (sys_dlsearch_path, base_name, &dir);
1371 }
1372 #endif
1373 }
1374 else
1375 {
1376 file = fopen (attempt, LT_READTEXT_MODE);
1377 }
1378
1379
1380
1381 if (!file)
1382 {
1383 LT__SETERROR (FILE_NOT_FOUND);
1384 ++errors;
1385 goto cleanup;
1386 }
1387
1388
1389 if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1390 &old_name, &installed) != 0)
1391 ++errors;
1392
1393 fclose (file);
1394
1395
1396 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1397 if (*phandle == 0)
1398 ++errors;
1399
1400 if (errors)
1401 {
1402 FREE (dlname);
1403 FREE (old_name);
1404 FREE (libdir);
1405 FREE (deplibs);
1406 FREE (*phandle);
1407 goto cleanup;
1408 }
1409
1410 assert (*phandle);
1411
1412 if (load_deplibs (*phandle, deplibs) == 0)
1413 {
1414 newhandle = *phandle;
1415
1416 if (find_module (&newhandle, dir, libdir, dlname, old_name,
1417 installed, advise))
1418 {
1419 unload_deplibs (*phandle);
1420 ++errors;
1421 }
1422 }
1423 else
1424 {
1425 ++errors;
1426 }
1427
1428 FREE (dlname);
1429 FREE (old_name);
1430 FREE (libdir);
1431 FREE (deplibs);
1432
1433 if (errors)
1434 {
1435 FREE (*phandle);
1436 goto cleanup;
1437 }
1438
1439 if (*phandle != newhandle)
1440 {
1441 unload_deplibs (*phandle);
1442 }
1443 }
1444 else
1445 {
1446
1447 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1448 if (*phandle == 0)
1449 {
1450 ++errors;
1451 goto cleanup;
1452 }
1453
1454 newhandle = *phandle;
1455
1456
1457
1458
1459
1460 if ((dir || (!find_handle (user_search_path, base_name,
1461 &newhandle, advise)
1462 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
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)
1471 #endif
1472 )))
1473 {
1474 if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1475 {
1476 newhandle = NULL;
1477 }
1478 }
1479
1480 if (!newhandle)
1481 {
1482 FREE (*phandle);
1483 ++errors;
1484 goto cleanup;
1485 }
1486 }
1487
1488 register_handle:
1489 MEMREASSIGN (*phandle, newhandle);
1490
1491 if ((*phandle)->info.ref_count == 0)
1492 {
1493 (*phandle)->info.ref_count = 1;
1494 MEMREASSIGN ((*phandle)->info.name, name);
1495
1496 (*phandle)->next = handles;
1497 handles = *phandle;
1498 }
1499
1500 LT__SETERRORSTR (saved_error);
1501
1502 cleanup:
1503 FREE (dir);
1504 FREE (attempt);
1505 FREE (name);
1506 if (!canonical)
1507 FREE (base_name);
1508 FREE (canonical);
1509 FREE (archive_name);
1510
1511 return errors;
1512 }
1513
1514
1515
1516
1517 static int
1518 file_not_found (void)
1519 {
1520 const char *error = 0;
1521
1522 LT__GETERROR (error);
1523 if (error == LT__STRERROR (FILE_NOT_FOUND))
1524 return 1;
1525
1526 return 0;
1527 }
1528
1529
1530
1531
1532 static int
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
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)
1593 {
1594 assert (padvise && *padvise);
1595 (*padvise)->is_symlocal = 1;
1596 return 0;
1597 }
1598
1599 int
1600 lt_dladvise_global (lt_dladvise *padvise)
1601 {
1602 assert (padvise && *padvise);
1603 (*padvise)->is_symglobal = 1;
1604 return 0;
1605 }
1606
1607 int
1608 lt_dladvise_preload (lt_dladvise *padvise)
1609 {
1610 assert (padvise && *padvise);
1611 (*padvise)->try_preload_only = 1;
1612 return 0;
1613 }
1614
1615
1616 lt_dlhandle
1617 lt_dlopen (const char *filename)
1618 {
1619 return lt_dlopenadvise (filename, NULL);
1620 }
1621
1622
1623
1624
1625
1626
1627 lt_dlhandle
1628 lt_dlopenext (const char *filename)
1629 {
1630 lt_dlhandle handle = 0;
1631 lt_dladvise advise;
1632
1633 if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
1634 handle = lt_dlopenadvise (filename, advise);
1635
1636 lt_dladvise_destroy (&advise);
1637 return handle;
1638 }
1639
1640
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;
1647
1648 LT__GETERROR (saved_error);
1649
1650
1651 if (advise && advise->is_symlocal && advise->is_symglobal)
1652 {
1653 LT__SETERROR (CONFLICTING_FLAGS);
1654 return 0;
1655 }
1656
1657 if (!filename
1658 || !advise
1659 || !advise->try_ext
1660 || has_library_ext (filename))
1661 {
1662
1663
1664 if (try_dlopen (&handle, filename, NULL, advise) != 0)
1665 return 0;
1666
1667 return handle;
1668 }
1669 else if (filename && *filename)
1670 {
1671
1672
1673 errors += try_dlopen (&handle, filename, archive_ext, advise);
1674
1675
1676
1677
1678
1679
1680 if (handle || ((errors > 0) && !file_not_found ()))
1681 return handle;
1682
1683 #if defined(LT_MODULE_EXT)
1684
1685 LT__SETERRORSTR (saved_error);
1686 errors = try_dlopen (&handle, filename, shlib_ext, advise);
1687
1688
1689
1690 if (handle || ((errors > 0) && !file_not_found ()))
1691 return handle;
1692 #endif
1693
1694 #if defined(LT_SHARED_EXT)
1695
1696 LT__SETERRORSTR (saved_error);
1697 errors = try_dlopen (&handle, filename, shared_ext, advise);
1698
1699
1700
1701 if (handle || ((errors > 0) && !file_not_found ()))
1702 return handle;
1703 #endif
1704 }
1705
1706
1707
1708 LT__SETERROR (FILE_NOT_FOUND);
1709 return 0;
1710 }
1711
1712
1713 static int
1714 lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1715 const char *entry)
1716 {
1717 error_t error;
1718
1719
1720
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)
1727 {
1728 switch (error)
1729 {
1730 case ENOMEM:
1731 LT__SETERROR (NO_MEMORY);
1732 break;
1733 default:
1734 LT__SETERROR (UNKNOWN);
1735 break;
1736 }
1737 return 1;
1738 }
1739
1740 return 0;
1741 }
1742
1743 static int
1744 lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1745 {
1746 char *before = 0;
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;
1759 }
1760
1761 return lt_argz_insert (pargz, pargz_len, before, entry);
1762 }
1763
1764 static int
1765 lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1766 struct dirent *dp)
1767 {
1768 char *buf = 0;
1769 size_t buf_len = 0;
1770 char *end = 0;
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);
1780 end = dp->d_name + D_NAMLEN(dp);
1781
1782
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
1794 {
1795 char *p;
1796 for (p = end -1; p > dp->d_name; --p)
1797 if (*p == '.')
1798 {
1799 end = p;
1800 break;
1801 }
1802 }
1803
1804
1805 end_offset = end - dp->d_name;
1806 buf_len = dir_len + 1+ end_offset;
1807 buf = MALLOC (char, 1+ buf_len);
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
1819 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1820 ++errors;
1821
1822 FREE (buf);
1823
1824 return errors;
1825 }
1826
1827 static int
1828 list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1829 {
1830 DIR *dirp = 0;
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 {
1841 struct dirent *dp = 0;
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;
1857 }
1858
1859
1860
1861
1862 static int
1863 foreachfile_callback (char *dirname, void *data1, void *data2)
1864 {
1865 file_worker_func *func = *(file_worker_func **) data1;
1866
1867 int is_done = 0;
1868 char *argz = 0;
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 {
1877 char *filename = 0;
1878 while ((filename = argz_next (argz, argz_len, filename)))
1879 if ((is_done = (*func) (filename, data2)))
1880 break;
1881 }
1882
1883 cleanup:
1884 FREE (argz);
1885
1886 return is_done;
1887 }
1888
1889
1890
1891
1892
1893
1894
1895
1896 int
1897 lt_dlforeachfile (const char *search_path,
1898 int (*func) (const char *filename, void *data),
1899 void *data)
1900 {
1901 int is_done = 0;
1902 file_worker_func **fpptr = &func;
1903
1904 if (search_path)
1905 {
1906
1907
1908 is_done = foreach_dirinpath (search_path, 0,
1909 foreachfile_callback, fpptr, data);
1910 }
1911 else
1912 {
1913
1914 is_done = foreach_dirinpath (user_search_path, 0,
1915 foreachfile_callback, fpptr, data);
1916 if (!is_done)
1917 {
1918 is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1919 foreachfile_callback, fpptr, data);
1920 }
1921
1922 #if defined(LT_MODULE_PATH_VAR)
1923 if (!is_done)
1924 {
1925 is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1926 foreachfile_callback, fpptr, data);
1927 }
1928 #endif
1929 #if defined(LT_DLSEARCH_PATH)
1930 if (!is_done && *sys_dlsearch_path)
1931 {
1932 is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1933 foreachfile_callback, fpptr, data);
1934 }
1935 #endif
1936 }
1937
1938 return is_done;
1939 }
1940
1941 int
1942 lt_dlclose (lt_dlhandle handle)
1943 {
1944 lt_dlhandle cur, last;
1945 int errors = 0;
1946
1947
1948 last = cur = handles;
1949 while (cur && handle != cur)
1950 {
1951 last = cur;
1952 cur = cur->next;
1953 }
1954
1955 if (!cur)
1956 {
1957 LT__SETERROR (INVALID_HANDLE);
1958 ++errors;
1959 goto done;
1960 }
1961
1962 cur = handle;
1963 cur->info.ref_count--;
1964
1965
1966
1967
1968
1969 if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1970 {
1971 lt_user_data data = cur->vtable->dlloader_data;
1972
1973 if (cur != handles)
1974 {
1975 last->next = cur->next;
1976 }
1977 else
1978 {
1979 handles = cur->next;
1980 }
1981
1982 errors += cur->vtable->module_close (data, cur->module);
1983 errors += unload_deplibs (handle);
1984
1985
1986 FREE (cur->interface_data);
1987
1988 FREE (cur->info.filename);
1989 FREE (cur->info.name);
1990 FREE (cur);
1991
1992 goto done;
1993 }
1994
1995 if (LT_DLIS_RESIDENT (handle))
1996 {
1997 LT__SETERROR (CLOSE_RESIDENT_MODULE);
1998 ++errors;
1999 }
2000
2001 done:
2002 return errors;
2003 }
2004
2005 void *
2006 lt_dlsym (lt_dlhandle place, const char *symbol)
2007 {
2008 size_t lensym;
2009 char lsym[LT_SYMBOL_LENGTH];
2010 char *sym;
2011 void *address;
2012 lt_user_data data;
2013 lt_dlhandle handle;
2014
2015 if (!place)
2016 {
2017 LT__SETERROR (INVALID_HANDLE);
2018 return 0;
2019 }
2020
2021 handle = place;
2022
2023 if (!symbol)
2024 {
2025 LT__SETERROR (SYMBOL_NOT_FOUND);
2026 return 0;
2027 }
2028
2029 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
2030 + LT_STRLEN (handle->info.name);
2031
2032 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
2033 {
2034 sym = lsym;
2035 }
2036 else
2037 {
2038 sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
2039 if (!sym)
2040 {
2041 LT__SETERROR (BUFFER_OVERFLOW);
2042 return 0;
2043 }
2044 }
2045
2046 data = handle->vtable->dlloader_data;
2047 if (handle->info.name)
2048 {
2049 const char *saved_error;
2050
2051 LT__GETERROR (saved_error);
2052
2053
2054 if (handle->vtable->sym_prefix)
2055 {
2056 strcpy(sym, handle->vtable->sym_prefix);
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
2068 address = handle->vtable->find_sym (data, handle->module, sym);
2069 if (address)
2070 {
2071 if (sym != lsym)
2072 {
2073 FREE (sym);
2074 }
2075 return address;
2076 }
2077 LT__SETERRORSTR (saved_error);
2078 }
2079
2080
2081 if (handle->vtable->sym_prefix)
2082 {
2083 strcpy(sym, handle->vtable->sym_prefix);
2084 strcat(sym, symbol);
2085 }
2086 else
2087 {
2088 strcpy(sym, symbol);
2089 }
2090
2091 address = handle->vtable->find_sym (data, handle->module, sym);
2092 if (sym != lsym)
2093 {
2094 FREE (sym);
2095 }
2096
2097 return address;
2098 }
2099
2100 const char *
2101 lt_dlerror (void)
2102 {
2103 const char *error;
2104
2105 LT__GETERROR (error);
2106 LT__SETERRORSTR (0);
2107
2108 return error;
2109 }
2110
2111 static int
2112 lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
2113 {
2114 int errors = 0;
2115 char *canonical = 0;
2116 char *argz = 0;
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
2131 if (*ppath == 0)
2132 {
2133 assert (!before);
2134 assert (dir);
2135
2136 *ppath = lt__strdup (dir);
2137 if (*ppath == 0)
2138 ++errors;
2139
2140 goto cleanup;
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
2152
2153
2154
2155
2156 if (before)
2157 {
2158 assert (*ppath <= before);
2159 assert ((int) (before - *ppath) <= (int) strlen (*ppath));
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);
2171 MEMREASSIGN(*ppath, argz);
2172
2173 cleanup:
2174 FREE (argz);
2175 FREE (canonical);
2176
2177 return errors;
2178 }
2179
2180 int
2181 lt_dladdsearchdir (const char *search_dir)
2182 {
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;
2192 }
2193
2194 int
2195 lt_dlinsertsearchdir (const char *before, const char *search_dir)
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 {
2204 LT__SETERROR (INVALID_POSITION);
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;
2215 }
2216 }
2217
2218 return errors;
2219 }
2220
2221 int
2222 lt_dlsetsearchpath (const char *search_path)
2223 {
2224 int errors = 0;
2225
2226 FREE (user_search_path);
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;
2237 }
2238
2239 const char *
2240 lt_dlgetsearchpath (void)
2241 {
2242 const char *saved_path;
2243
2244 saved_path = user_search_path;
2245
2246 return saved_path;
2247 }
2248
2249 int
2250 lt_dlmakeresident (lt_dlhandle handle)
2251 {
2252 int errors = 0;
2253
2254 if (!handle)
2255 {
2256 LT__SETERROR (INVALID_HANDLE);
2257 ++errors;
2258 }
2259 else
2260 {
2261 handle->info.is_resident = 1;
2262 }
2263
2264 return errors;
2265 }
2266
2267 int
2268 lt_dlisresident (lt_dlhandle handle)
2269 {
2270 if (!handle)
2271 {
2272 LT__SETERROR (INVALID_HANDLE);
2273 return -1;
2274 }
2275
2276 return LT_DLIS_RESIDENT (handle);
2277 }
2278
2279
2280
2281
2282
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
2294
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;
2302 }
2303
2304 return (lt_dlinterface_id) interface_id;
2305 }
2306
2307 void lt_dlinterface_free (lt_dlinterface_id key)
2308 {
2309 lt__interface_id *interface_id = (lt__interface_id *)key;
2310 FREE (interface_id->id_string);
2311 FREE (interface_id);
2312 }
2313
2314 void *
2315 lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2316 {
2317 int n_elements = 0;
2318 void *stale = (void *) 0;
2319 lt_dlhandle cur = handle;
2320 int i;
2321
2322 if (cur->interface_data)
2323 while (cur->interface_data[n_elements].key)
2324 ++n_elements;
2325
2326 for (i = 0; i < n_elements; ++i)
2327 {
2328 if (cur->interface_data[i].key == key)
2329 {
2330 stale = cur->interface_data[i].data;
2331 break;
2332 }
2333 }
2334
2335
2336
2337 if (i == n_elements)
2338 {
2339 lt_interface_data *temp
2340 = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2341
2342 if (!temp)
2343 {
2344 stale = 0;
2345 goto done;
2346 }
2347
2348 cur->interface_data = temp;
2349
2350
2351 cur->interface_data[i].key = key;
2352 cur->interface_data[1+ i].key = 0;
2353 }
2354
2355 cur->interface_data[i].data = data;
2356
2357 done:
2358 return stale;
2359 }
2360
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;
2366
2367
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 }
2380
2381 return result;
2382 }
2383
2384 const lt_dlinfo *
2385 lt_dlgetinfo (lt_dlhandle handle)
2386 {
2387 if (!handle)
2388 {
2389 LT__SETERROR (INVALID_HANDLE);
2390 return 0;
2391 }
2392
2393 return &(handle->info);
2394 }
2395
2396
2397 lt_dlhandle
2398 lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2399 {
2400 lt_dlhandle handle = place;
2401 lt__interface_id *iterator = (lt__interface_id *) iface;
2402
2403 assert (iface);
2404
2405 if (!handle)
2406 handle = handles;
2407 else
2408 handle = handle->next;
2409
2410
2411 while (handle && iterator->iface
2412 && ((*iterator->iface) (handle, iterator->id_string) != 0))
2413 {
2414 handle = handle->next;
2415 }
2416
2417 return handle;
2418 }
2419
2420
2421 lt_dlhandle
2422 lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2423 {
2424 lt_dlhandle handle = 0;
2425
2426 assert (iface);
2427
2428 while ((handle = lt_dlhandle_iterate (iface, handle)))
2429 {
2430 lt_dlhandle cur = handle;
2431 if (cur && cur->info.name && streq (cur->info.name, module_name))
2432 break;
2433 }
2434
2435 return handle;
2436 }
2437
2438
2439 int
2440 lt_dlhandle_map (lt_dlinterface_id iface,
2441 int (*func) (lt_dlhandle handle, void *data), void *data)
2442 {
2443 lt__interface_id *iterator = (lt__interface_id *) iface;
2444 lt_dlhandle cur = handles;
2445
2446 assert (iface);
2447
2448 while (cur)
2449 {
2450 int errorcode = 0;
2451
2452
2453 while (cur && iterator->iface
2454 && ((*iterator->iface) (cur, iterator->id_string) != 0))
2455 {
2456 cur = cur->next;
2457 }
2458
2459 if ((errorcode = (*func) (cur, data)) != 0)
2460 return errorcode;
2461 }
2462
2463 return 0;
2464 }