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 if (!handle->module) {
448 char *error;
449 LT__GETERROR(error);
450 fprintf (stderr, " Result: Failed\n"
451 " Error message << %s >>\n",
452 error ? error : "(null)");
453 } else {
454 fprintf (stderr, " Result: Success\n");
455 }
456 #endif
457
458 if (handle->module != 0)
459 {
460 if (advise)
461 {
462 handle->info.is_resident = advise->is_resident;
463 handle->info.is_symglobal = advise->is_symglobal;
464 handle->info.is_symlocal = advise->is_symlocal;
465 }
466 break;
467 }
468 }
469 while (!vtable && (loader = lt_dlloader_next (loader)));
470
471
472
473
474 if ((vtable && !handle->module)
475 || (!vtable && !loader))
476 {
477 FREE (handle->info.filename);
478 ++errors;
479 goto done;
480 }
481
482 handle->vtable = loader_vtable;
483 }
484
485 LT__SETERRORSTR (saved_error);
486
487 done:
488 return errors;
489 }
490
491
492 static int
493 tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
494 const char *dirname, const char *dlname,
495 lt_dladvise advise)
496 {
497 int error = 0;
498 char *filename = 0;
499 size_t filename_len = 0;
500 size_t dirname_len = LT_STRLEN (dirname);
501
502 assert (handle);
503 assert (dirname);
504 assert (dlname);
505 #if defined LT_DIRSEP_CHAR
506
507
508 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
509 #endif
510
511 if (dirname_len > 0)
512 if (dirname[dirname_len -1] == '/')
513 --dirname_len;
514 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
515
516
517
518 filename = MALLOC (char, filename_len + 1);
519 if (!filename)
520 return 1;
521
522 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
523
524
525
526
527 if (prefix)
528 {
529 error += tryall_dlopen_module (handle, (const char *) 0,
530 prefix, filename, advise);
531 }
532 else if (tryall_dlopen (handle, filename, advise, 0) != 0)
533 {
534 ++error;
535 }
536
537 FREE (filename);
538 return error;
539 }
540
541 static int
542 find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
543 const char *dlname, const char *old_name, int installed,
544 lt_dladvise advise)
545 {
546
547
548
549 if (old_name && tryall_dlopen (handle, old_name,
550 advise, lt_dlloader_find ("lt_preopen") ) == 0)
551 {
552 return 0;
553 }
554
555
556 if (dlname)
557 {
558
559 if (installed && libdir)
560 {
561 if (tryall_dlopen_module (handle, (const char *) 0,
562 libdir, dlname, advise) == 0)
563 return 0;
564 }
565
566
567 if (!installed)
568 {
569 if (tryall_dlopen_module (handle, dir, objdir,
570 dlname, advise) == 0)
571 return 0;
572 }
573
574
575 {
576 if (dir && (tryall_dlopen_module (handle, (const char *) 0,
577 dir, dlname, advise) == 0))
578 return 0;
579 }
580 }
581
582 return 1;
583 }
584
585
586 static int
587 canonicalize_path (const char *path, char **pcanonical)
588 {
589 char *canonical = 0;
590
591 assert (path && *path);
592 assert (pcanonical);
593
594 canonical = MALLOC (char, 1+ LT_STRLEN (path));
595 if (!canonical)
596 return 1;
597
598 {
599 size_t dest = 0;
600 size_t src;
601 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
602 {
603
604
605
606 if (path[src] == LT_PATHSEP_CHAR)
607 {
608 if ((dest == 0)
609 || (path[1+ src] == LT_PATHSEP_CHAR)
610 || (path[1+ src] == LT_EOS_CHAR))
611 continue;
612 }
613
614
615 if ((path[src] != '/')
616 #if defined LT_DIRSEP_CHAR
617 && (path[src] != LT_DIRSEP_CHAR)
618 #endif
619 )
620 {
621 canonical[dest++] = path[src];
622 }
623
624
625
626 else if ((path[1+ src] != LT_PATHSEP_CHAR)
627 && (path[1+ src] != LT_EOS_CHAR)
628 #if defined LT_DIRSEP_CHAR
629 && (path[1+ src] != LT_DIRSEP_CHAR)
630 #endif
631 && (path[1+ src] != '/'))
632 {
633 canonical[dest++] = '/';
634 }
635 }
636
637
638 canonical[dest] = LT_EOS_CHAR;
639 }
640
641
642 *pcanonical = canonical;
643
644 return 0;
645 }
646
647 static int
648 argzize_path (const char *path, char **pargz, size_t *pargz_len)
649 {
650 error_t error;
651
652 assert (path);
653 assert (pargz);
654 assert (pargz_len);
655
656 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
657 {
658 switch (error)
659 {
660 case ENOMEM:
661 LT__SETERROR (NO_MEMORY);
662 break;
663 default:
664 LT__SETERROR (UNKNOWN);
665 break;
666 }
667
668 return 1;
669 }
670
671 return 0;
672 }
673
674
675
676
677
678 static int
679 foreach_dirinpath (const char *search_path, const char *base_name,
680 foreach_callback_func *func, void *data1, void *data2)
681 {
682 int result = 0;
683 size_t filenamesize = 0;
684 size_t lenbase = LT_STRLEN (base_name);
685 size_t argz_len = 0;
686 char *argz = 0;
687 char *filename = 0;
688 char *canonical = 0;
689
690 if (!search_path || !*search_path)
691 {
692 LT__SETERROR (FILE_NOT_FOUND);
693 goto cleanup;
694 }
695
696 if (canonicalize_path (search_path, &canonical) != 0)
697 goto cleanup;
698
699 if (argzize_path (canonical, &argz, &argz_len) != 0)
700 goto cleanup;
701
702 {
703 char *dir_name = 0;
704 while ((dir_name = argz_next (argz, argz_len, dir_name)))
705 {
706 size_t lendir = LT_STRLEN (dir_name);
707
708 if (1+ lendir + lenbase >= filenamesize)
709 {
710 FREE (filename);
711 filenamesize = 1+ lendir + 1+ lenbase;
712 filename = MALLOC (char, filenamesize);
713 if (!filename)
714 goto cleanup;
715 }
716
717 assert (filenamesize > lendir);
718 strcpy (filename, dir_name);
719
720 if (base_name && *base_name)
721 {
722 if (filename[lendir -1] != '/')
723 filename[lendir++] = '/';
724 strcpy (filename +lendir, base_name);
725 }
726
727 if ((result = (*func) (filename, data1, data2)))
728 {
729 break;
730 }
731 }
732 }
733
734 cleanup:
735 FREE (argz);
736 FREE (canonical);
737 FREE (filename);
738
739 return result;
740 }
741
742
743
744
745 static int
746 find_file_callback (char *filename, void *data1, void *data2)
747 {
748 char **pdir = (char **) data1;
749 FILE **pfile = (FILE **) data2;
750 int is_done = 0;
751
752 assert (filename && *filename);
753 assert (pdir);
754 assert (pfile);
755
756 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
757 {
758 char *dirend = strrchr (filename, '/');
759
760 if (dirend > filename)
761 *dirend = LT_EOS_CHAR;
762
763 FREE (*pdir);
764 *pdir = lt__strdup (filename);
765 is_done = (*pdir == 0) ? -1 : 1;
766 }
767
768 return is_done;
769 }
770
771 static FILE *
772 find_file (const char *search_path, const char *base_name, char **pdir)
773 {
774 FILE *file = 0;
775
776 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
777
778 return file;
779 }
780
781 static int
782 find_handle_callback (char *filename, void *data, void *data2)
783 {
784 lt_dlhandle *phandle = (lt_dlhandle *) data;
785 int notfound = access (filename, R_OK);
786 lt_dladvise advise = (lt_dladvise) data2;
787
788
789 if (notfound)
790 return 0;
791
792
793
794 if (tryall_dlopen (phandle, filename, advise, 0) != 0)
795 *phandle = 0;
796
797 return 1;
798 }
799
800
801
802 static lt_dlhandle *
803 find_handle (const char *search_path, const char *base_name,
804 lt_dlhandle *phandle, lt_dladvise advise)
805 {
806 if (!search_path)
807 return 0;
808
809 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
810 phandle, advise))
811 return 0;
812
813 return phandle;
814 }
815
816 #if !defined LTDL_DLOPEN_DEPLIBS
817 static int
818 load_deplibs (lt_dlhandle handle, char * deplibs LT__UNUSED)
819 {
820 handle->depcount = 0;
821 return 0;
822 }
823
824 #else
825 static int
826 load_deplibs (lt_dlhandle handle, char *deplibs)
827 {
828 char *p, *save_search_path = 0;
829 int depcount = 0;
830 int i;
831 char **names = 0;
832 int errors = 0;
833
834 handle->depcount = 0;
835
836 if (!deplibs)
837 {
838 return errors;
839 }
840 ++errors;
841
842 if (user_search_path)
843 {
844 save_search_path = lt__strdup (user_search_path);
845 if (!save_search_path)
846 goto cleanup;
847 }
848
849
850 p = deplibs;
851 while (*p)
852 {
853 if (!isspace ((unsigned char) *p))
854 {
855 char *end = p+1;
856 while (*end && !isspace((unsigned char) *end))
857 {
858 ++end;
859 }
860
861 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
862 {
863 char save = *end;
864 *end = 0;
865 if (lt_dladdsearchdir(p+2))
866 {
867 goto cleanup;
868 }
869 *end = save;
870 }
871 else
872 {
873 ++depcount;
874 }
875
876 p = end;
877 }
878 else
879 {
880 ++p;
881 }
882 }
883
884
885 if (!depcount)
886 {
887 errors = 0;
888 goto cleanup;
889 }
890
891 names = MALLOC (char *, depcount);
892 if (!names)
893 goto cleanup;
894
895
896 depcount = 0;
897 p = deplibs;
898 while (*p)
899 {
900 if (isspace ((unsigned char) *p))
901 {
902 ++p;
903 }
904 else
905 {
906 char *end = p+1;
907 while (*end && !isspace ((unsigned char) *end))
908 {
909 ++end;
910 }
911
912 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
913 {
914 char *name;
915 char save = *end;
916 *end = 0;
917 if (strncmp(p, "-l", 2) == 0)
918 {
919 size_t name_len = 3+ LT_STRLEN (p + 2);
920 name = MALLOC (char, 1+ name_len);
921 if (name)
922 sprintf (name, "lib%s", p+2);
923 }
924 else
925 name = lt__strdup(p);
926
927 if (!name)
928 goto cleanup_names;
929
930 names[depcount++] = name;
931 *end = save;
932 }
933 p = end;
934 }
935 }
936
937
938
939
940
941
942 if (depcount)
943 {
944 lt_dlhandle cur = handle;
945 int j = 0;
946
947 cur->deplibs = MALLOC (lt_dlhandle, depcount);
948 if (!cur->deplibs)
949 goto cleanup_names;
950
951 for (i = 0; i < depcount; ++i)
952 {
953 cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
954 if (cur->deplibs[j])
955 {
956 ++j;
957 }
958 }
959
960 cur->depcount = j;
961 errors = 0;
962 }
963
964 cleanup_names:
965 for (i = 0; i < depcount; ++i)
966 {
967 FREE (names[i]);
968 }
969
970 cleanup:
971 FREE (names);
972
973 if (save_search_path) {
974 MEMREASSIGN (user_search_path, save_search_path);
975 }
976
977 return errors;
978 }
979 #endif
980
981 static int
982 unload_deplibs (lt_dlhandle handle)
983 {
984 int i;
985 int errors = 0;
986 lt_dlhandle cur = handle;
987
988 if (cur->depcount)
989 {
990 for (i = 0; i < cur->depcount; ++i)
991 {
992 if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
993 {
994 errors += lt_dlclose (cur->deplibs[i]);
995 }
996 }
997 FREE (cur->deplibs);
998 }
999
1000 return errors;
1001 }
1002
1003 static int
1004 trim (char **dest, const char *str)
1005 {
1006
1007
1008 const char *end = strrchr (str, '\'');
1009 size_t len = LT_STRLEN (str);
1010 char *tmp;
1011
1012 FREE (*dest);
1013
1014 if (!end || end == str)
1015 return 1;
1016
1017 if (len > 3 && str[0] == '\'')
1018 {
1019 tmp = MALLOC (char, end - str);
1020 if (!tmp)
1021 return 1;
1022
1023 memcpy(tmp, &str[1], (end - str) - 1);
1024 tmp[(end - str) - 1] = LT_EOS_CHAR;
1025 *dest = tmp;
1026 }
1027 else
1028 {
1029 *dest = 0;
1030 }
1031
1032 return 0;
1033 }
1034
1035
1036 static int
1037 parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
1038 char **old_name, int *installed)
1039 {
1040 int errors = 0;
1041 size_t line_len = LT_FILENAME_MAX;
1042 char * line = MALLOC (char, line_len);
1043
1044 if (!line)
1045 {
1046 LT__SETERROR (FILE_NOT_FOUND);
1047 return 1;
1048 }
1049
1050 while (!feof (file))
1051 {
1052 line[line_len-2] = '\0';
1053 if (!fgets (line, (int) line_len, file))
1054 {
1055 break;
1056 }
1057
1058
1059
1060
1061 while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
1062 {
1063 line = REALLOC (char, line, line_len *2);
1064 if (!line)
1065 {
1066 ++errors;
1067 goto cleanup;
1068 }
1069 line[line_len * 2 - 2] = '\0';
1070 if (!fgets (&line[line_len -1], (int) line_len +1, file))
1071 {
1072 break;
1073 }
1074 line_len *= 2;
1075 }
1076
1077 if (line[0] == '\n' || line[0] == '#')
1078 {
1079 continue;
1080 }
1081
1082 #undef STR_DLNAME
1083 #define STR_DLNAME "dlname="
1084 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
1085 {
1086 errors += trim (dlname, &line[sizeof (STR_DLNAME) - 1]);
1087 }
1088
1089 #undef STR_OLD_LIBRARY
1090 #define STR_OLD_LIBRARY "old_library="
1091 else if (strncmp (line, STR_OLD_LIBRARY,
1092 sizeof (STR_OLD_LIBRARY) - 1) == 0)
1093 {
1094 errors += trim (old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
1095 }
1096
1097
1098
1099 #undef STR_LIBDIR
1100 #define STR_LIBDIR "libdir="
1101 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
1102 {
1103 errors += trim (libdir, &line[sizeof(STR_LIBDIR) - 1]);
1104 #ifdef __WINDOWS__
1105
1106 if (*libdir && (**libdir == '/' || **libdir == '\\'))
1107 **libdir = '\0';
1108 #endif
1109 }
1110
1111 #undef STR_DL_DEPLIBS
1112 #define STR_DL_DEPLIBS "dependency_libs="
1113 else if (strncmp (line, STR_DL_DEPLIBS,
1114 sizeof (STR_DL_DEPLIBS) - 1) == 0)
1115 {
1116 errors += trim (deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
1117 }
1118 else if (STREQ (line, "installed=yes\n"))
1119 {
1120 *installed = 1;
1121 }
1122 else if (STREQ (line, "installed=no\n"))
1123 {
1124 *installed = 0;
1125 }
1126
1127 #undef STR_LIBRARY_NAMES
1128 #define STR_LIBRARY_NAMES "library_names="
1129 else if (!*dlname && strncmp (line, STR_LIBRARY_NAMES,
1130 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
1131 {
1132 char *last_libname;
1133 errors += trim (dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
1134 if (!errors
1135 && *dlname
1136 && (last_libname = strrchr (*dlname, ' ')) != 0)
1137 {
1138 last_libname = lt__strdup (last_libname + 1);
1139 if (!last_libname)
1140 {
1141 ++errors;
1142 goto cleanup;
1143 }
1144 MEMREASSIGN (*dlname, last_libname);
1145 }
1146 }
1147
1148 if (errors)
1149 break;
1150 }
1151 cleanup:
1152 FREE (line);
1153 return errors;
1154 }
1155
1156
1157
1158 static int
1159 try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
1160 lt_dladvise advise)
1161 {
1162 const char * saved_error = 0;
1163 char * archive_name = 0;
1164 char * canonical = 0;
1165 char * base_name = 0;
1166 char * dir = 0;
1167 char * name = 0;
1168 char * attempt = 0;
1169 int errors = 0;
1170 lt_dlhandle newhandle;
1171
1172 assert (phandle);
1173 assert (*phandle == 0);
1174
1175 #ifdef LT_DEBUG_LOADERS
1176 fprintf (stderr, "try_dlopen (%s, %s)\n",
1177 filename ? filename : "(null)",
1178 ext ? ext : "(null)");
1179 #endif
1180
1181 LT__GETERROR (saved_error);
1182
1183
1184 if (!filename)
1185 {
1186 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1187 if (*phandle == 0)
1188 return 1;
1189
1190 newhandle = *phandle;
1191
1192
1193 newhandle->info.is_resident = 1;
1194
1195 if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
1196 {
1197 FREE (*phandle);
1198 return 1;
1199 }
1200
1201 goto register_handle;
1202 }
1203
1204 assert (filename && *filename);
1205
1206 if (ext)
1207 {
1208 attempt = MALLOC (char, LT_STRLEN (filename) + LT_STRLEN (ext) + 1);
1209 if (!attempt)
1210 return 1;
1211
1212 sprintf(attempt, "%s%s", filename, ext);
1213 }
1214 else
1215 {
1216 attempt = lt__strdup (filename);
1217 if (!attempt)
1218 return 1;
1219 }
1220
1221
1222
1223 if (canonicalize_path (attempt, &canonical) != 0)
1224 {
1225 ++errors;
1226 goto cleanup;
1227 }
1228
1229
1230
1231 base_name = strrchr (canonical, '/');
1232 if (base_name)
1233 {
1234 size_t dirlen = (1+ base_name) - canonical;
1235
1236 dir = MALLOC (char, 1+ dirlen);
1237 if (!dir)
1238 {
1239 ++errors;
1240 goto cleanup;
1241 }
1242
1243 strlcpy (dir, canonical, dirlen);
1244 dir[dirlen] = LT_EOS_CHAR;
1245
1246 ++base_name;
1247 }
1248 else
1249 MEMREASSIGN (base_name, canonical);
1250
1251 assert (base_name && *base_name);
1252
1253 ext = strrchr (base_name, '.');
1254 if (!ext)
1255 {
1256 ext = base_name + LT_STRLEN (base_name);
1257 }
1258
1259
1260 name = MALLOC (char, ext - base_name + 1);
1261 if (!name)
1262 {
1263 ++errors;
1264 goto cleanup;
1265 }
1266
1267
1268 {
1269 int i;
1270 for (i = 0; i < ext - base_name; ++i)
1271 {
1272 if (isalnum ((unsigned char)(base_name[i])))
1273 {
1274 name[i] = base_name[i];
1275 }
1276 else
1277 {
1278 name[i] = '_';
1279 }
1280 }
1281 name[ext - base_name] = LT_EOS_CHAR;
1282 }
1283
1284
1285
1286 if (!dir)
1287 {
1288 const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
1289
1290 if (vtable)
1291 {
1292
1293 archive_name = MALLOC (char, strlen (libprefix) + LT_STRLEN (name) + strlen (libext) + 2);
1294 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1295
1296 if ((*phandle == NULL) || (archive_name == NULL))
1297 {
1298 ++errors;
1299 goto cleanup;
1300 }
1301 newhandle = *phandle;
1302
1303
1304
1305 if (strncmp(name, "lib", 3) == 0)
1306 {
1307 sprintf (archive_name, "%s%s.%s", libprefix, name + 3, libext);
1308 }
1309 else
1310 {
1311 sprintf (archive_name, "%s.%s", name, libext);
1312 }
1313
1314 if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
1315 {
1316 goto register_handle;
1317 }
1318
1319
1320
1321 FREE (*phandle);
1322 newhandle = NULL;
1323 }
1324 }
1325
1326
1327
1328 if (advise && advise->try_preload_only)
1329 {
1330 goto cleanup;
1331 }
1332
1333
1334 if (ext && STREQ (ext, archive_ext))
1335 {
1336
1337 FILE * file = 0;
1338 char * dlname = 0;
1339 char * old_name = 0;
1340 char * libdir = 0;
1341 char * deplibs = 0;
1342
1343
1344
1345
1346 int installed = 1;
1347
1348
1349
1350
1351
1352 if (!dir)
1353 {
1354 const char *search_path = user_search_path;
1355
1356 if (search_path)
1357 file = find_file (user_search_path, base_name, &dir);
1358
1359 if (!file)
1360 {
1361 search_path = getenv (LTDL_SEARCHPATH_VAR);
1362 if (search_path)
1363 file = find_file (search_path, base_name, &dir);
1364 }
1365
1366 #if defined LT_MODULE_PATH_VAR
1367 if (!file)
1368 {
1369 search_path = getenv (LT_MODULE_PATH_VAR);
1370 if (search_path)
1371 file = find_file (search_path, base_name, &dir);
1372 }
1373 #endif
1374 #if defined LT_DLSEARCH_PATH
1375 if (!file && *sys_dlsearch_path)
1376 {
1377 file = find_file (sys_dlsearch_path, base_name, &dir);
1378 }
1379 #endif
1380 }
1381 else
1382 {
1383 file = fopen (attempt, LT_READTEXT_MODE);
1384 }
1385
1386
1387
1388 if (!file)
1389 {
1390 LT__SETERROR (FILE_NOT_FOUND);
1391 ++errors;
1392 goto cleanup;
1393 }
1394
1395
1396 if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1397 &old_name, &installed) != 0)
1398 ++errors;
1399
1400 fclose (file);
1401
1402
1403 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1404 if (*phandle == 0)
1405 ++errors;
1406
1407 if (errors)
1408 {
1409 FREE (dlname);
1410 FREE (old_name);
1411 FREE (libdir);
1412 FREE (deplibs);
1413 FREE (*phandle);
1414 goto cleanup;
1415 }
1416
1417 assert (*phandle);
1418
1419 if (load_deplibs (*phandle, deplibs) == 0)
1420 {
1421 newhandle = *phandle;
1422
1423 if (find_module (&newhandle, dir, libdir, dlname, old_name,
1424 installed, advise))
1425 {
1426 unload_deplibs (*phandle);
1427 ++errors;
1428 }
1429 }
1430 else
1431 {
1432 ++errors;
1433 }
1434
1435 FREE (dlname);
1436 FREE (old_name);
1437 FREE (libdir);
1438 FREE (deplibs);
1439
1440 if (errors)
1441 {
1442 FREE (*phandle);
1443 goto cleanup;
1444 }
1445
1446 if (*phandle != newhandle)
1447 {
1448 unload_deplibs (*phandle);
1449 }
1450 }
1451 else
1452 {
1453
1454 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1455 if (*phandle == 0)
1456 {
1457 ++errors;
1458 goto cleanup;
1459 }
1460
1461 newhandle = *phandle;
1462
1463
1464
1465
1466
1467 if ((dir || (!find_handle (user_search_path, base_name,
1468 &newhandle, advise)
1469 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
1470 &newhandle, advise)
1471 #if defined LT_MODULE_PATH_VAR
1472 && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
1473 &newhandle, advise)
1474 #endif
1475 #if defined LT_DLSEARCH_PATH
1476 && !find_handle (sys_dlsearch_path, base_name,
1477 &newhandle, advise)
1478 #endif
1479 )))
1480 {
1481 if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1482 {
1483 newhandle = NULL;
1484 }
1485 }
1486
1487 if (!newhandle)
1488 {
1489 FREE (*phandle);
1490 ++errors;
1491 goto cleanup;
1492 }
1493 }
1494
1495 register_handle:
1496 MEMREASSIGN (*phandle, newhandle);
1497
1498 if ((*phandle)->info.ref_count == 0)
1499 {
1500 (*phandle)->info.ref_count = 1;
1501 MEMREASSIGN ((*phandle)->info.name, name);
1502
1503 (*phandle)->next = handles;
1504 handles = *phandle;
1505 }
1506
1507 LT__SETERRORSTR (saved_error);
1508
1509 cleanup:
1510 FREE (dir);
1511 FREE (attempt);
1512 FREE (name);
1513 if (!canonical)
1514 FREE (base_name);
1515 FREE (canonical);
1516 FREE (archive_name);
1517
1518 return errors;
1519 }
1520
1521
1522
1523
1524 static int
1525 file_not_found (void)
1526 {
1527 const char *error = 0;
1528
1529 LT__GETERROR (error);
1530 if (error == LT__STRERROR (FILE_NOT_FOUND))
1531 return 1;
1532
1533 return 0;
1534 }
1535
1536
1537
1538
1539 static int
1540 has_library_ext (const char *filename)
1541 {
1542 const char * ext = 0;
1543
1544 assert (filename);
1545
1546 ext = strrchr (filename, '.');
1547
1548 if (ext && ((STREQ (ext, archive_ext))
1549 #if defined LT_MODULE_EXT
1550 || (STREQ (ext, shlib_ext))
1551 #endif
1552 #if defined LT_SHARED_EXT
1553 || (STREQ (ext, shared_ext))
1554 #endif
1555 ))
1556 {
1557 return 1;
1558 }
1559
1560 return 0;
1561 }
1562
1563
1564
1565
1566 int
1567 lt_dladvise_init (lt_dladvise *padvise)
1568 {
1569 lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
1570 *padvise = advise;
1571 return (advise ? 0 : 1);
1572 }
1573
1574 int
1575 lt_dladvise_destroy (lt_dladvise *padvise)
1576 {
1577 if (padvise)
1578 FREE(*padvise);
1579 return 0;
1580 }
1581
1582 int
1583 lt_dladvise_ext (lt_dladvise *padvise)
1584 {
1585 assert (padvise && *padvise);
1586 (*padvise)->try_ext = 1;
1587 return 0;
1588 }
1589
1590 int
1591 lt_dladvise_resident (lt_dladvise *padvise)
1592 {
1593 assert (padvise && *padvise);
1594 (*padvise)->is_resident = 1;
1595 return 0;
1596 }
1597
1598 int
1599 lt_dladvise_local (lt_dladvise *padvise)
1600 {
1601 assert (padvise && *padvise);
1602 (*padvise)->is_symlocal = 1;
1603 return 0;
1604 }
1605
1606 int
1607 lt_dladvise_global (lt_dladvise *padvise)
1608 {
1609 assert (padvise && *padvise);
1610 (*padvise)->is_symglobal = 1;
1611 return 0;
1612 }
1613
1614 int
1615 lt_dladvise_preload (lt_dladvise *padvise)
1616 {
1617 assert (padvise && *padvise);
1618 (*padvise)->try_preload_only = 1;
1619 return 0;
1620 }
1621
1622
1623 lt_dlhandle
1624 lt_dlopen (const char *filename)
1625 {
1626 return lt_dlopenadvise (filename, NULL);
1627 }
1628
1629
1630
1631
1632
1633
1634 lt_dlhandle
1635 lt_dlopenext (const char *filename)
1636 {
1637 lt_dlhandle handle = 0;
1638 lt_dladvise advise;
1639
1640 if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
1641 handle = lt_dlopenadvise (filename, advise);
1642
1643 lt_dladvise_destroy (&advise);
1644 return handle;
1645 }
1646
1647
1648 lt_dlhandle
1649 lt_dlopenadvise (const char *filename, lt_dladvise advise)
1650 {
1651 lt_dlhandle handle = 0;
1652 int errors = 0;
1653 const char * saved_error = 0;
1654
1655 LT__GETERROR (saved_error);
1656
1657
1658 if (advise && advise->is_symlocal && advise->is_symglobal)
1659 {
1660 LT__SETERROR (CONFLICTING_FLAGS);
1661 return 0;
1662 }
1663
1664 if (!filename
1665 || !advise
1666 || !advise->try_ext
1667 || has_library_ext (filename))
1668 {
1669
1670
1671 if (try_dlopen (&handle, filename, NULL, advise) != 0)
1672 return 0;
1673
1674 return handle;
1675 }
1676 else if (filename && *filename)
1677 {
1678
1679
1680 errors += try_dlopen (&handle, filename, archive_ext, advise);
1681
1682
1683
1684
1685
1686
1687 if (handle || ((errors > 0) && !file_not_found ()))
1688 return handle;
1689
1690 #if defined LT_MODULE_EXT
1691
1692 LT__SETERRORSTR (saved_error);
1693 errors = try_dlopen (&handle, filename, shlib_ext, advise);
1694
1695
1696
1697 if (handle || ((errors > 0) && !file_not_found ()))
1698 return handle;
1699 #endif
1700
1701 #if defined LT_SHARED_EXT
1702
1703 LT__SETERRORSTR (saved_error);
1704 errors = try_dlopen (&handle, filename, shared_ext, advise);
1705
1706
1707
1708 if (handle || ((errors > 0) && !file_not_found ()))
1709 return handle;
1710 #endif
1711 }
1712
1713
1714
1715 LT__SETERROR (FILE_NOT_FOUND);
1716 return 0;
1717 }
1718
1719
1720 static int
1721 lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1722 const char *entry)
1723 {
1724 error_t error;
1725
1726
1727
1728 if (before)
1729 error = argz_insert (pargz, pargz_len, before, entry);
1730 else
1731 error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1732
1733 if (error)
1734 {
1735 switch (error)
1736 {
1737 case ENOMEM:
1738 LT__SETERROR (NO_MEMORY);
1739 break;
1740 default:
1741 LT__SETERROR (UNKNOWN);
1742 break;
1743 }
1744 return 1;
1745 }
1746
1747 return 0;
1748 }
1749
1750 static int
1751 lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1752 {
1753 char *before = 0;
1754
1755 assert (pargz);
1756 assert (pargz_len);
1757 assert (entry && *entry);
1758
1759 if (*pargz)
1760 while ((before = argz_next (*pargz, *pargz_len, before)))
1761 {
1762 int cmp = strcmp (entry, before);
1763
1764 if (cmp < 0) break;
1765 if (cmp == 0) return 0;
1766 }
1767
1768 return lt_argz_insert (pargz, pargz_len, before, entry);
1769 }
1770
1771 static int
1772 lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1773 struct dirent *dp)
1774 {
1775 char *buf = 0;
1776 size_t buf_len = 0;
1777 char *end = 0;
1778 size_t end_offset = 0;
1779 size_t dir_len = 0;
1780 int errors = 0;
1781
1782 assert (pargz);
1783 assert (pargz_len);
1784 assert (dp);
1785
1786 dir_len = LT_STRLEN (dirnam);
1787 end = dp->d_name + D_NAMLEN(dp);
1788
1789
1790 {
1791 char *p;
1792 for (p = end; p -1 > dp->d_name; --p)
1793 if (strchr (".0123456789", p[-1]) == 0)
1794 break;
1795
1796 if (*p == '.')
1797 end = p;
1798 }
1799
1800
1801 {
1802 char *p;
1803 for (p = end -1; p > dp->d_name; --p)
1804 if (*p == '.')
1805 {
1806 end = p;
1807 break;
1808 }
1809 }
1810
1811
1812 end_offset = end - dp->d_name;
1813 buf_len = dir_len + 1+ end_offset;
1814 buf = MALLOC (char, 1+ buf_len);
1815 if (!buf)
1816 return ++errors;
1817
1818 assert (buf);
1819
1820 strcpy (buf, dirnam);
1821 strcat (buf, "/");
1822 strncat (buf, dp->d_name, end_offset);
1823 buf[buf_len] = LT_EOS_CHAR;
1824
1825
1826 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1827 ++errors;
1828
1829 FREE (buf);
1830
1831 return errors;
1832 }
1833
1834 static int
1835 list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1836 {
1837 DIR *dirp = 0;
1838 int errors = 0;
1839
1840 assert (dirnam && *dirnam);
1841 assert (pargz);
1842 assert (pargz_len);
1843 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
1844
1845 dirp = opendir (dirnam);
1846 if (dirp)
1847 {
1848 struct dirent *dp = 0;
1849
1850 while ((dp = readdir (dirp)))
1851 if (dp->d_name[0] != '.')
1852 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
1853 {
1854 ++errors;
1855 break;
1856 }
1857
1858 closedir (dirp);
1859 }
1860 else
1861 ++errors;
1862
1863 return errors;
1864 }
1865
1866
1867
1868
1869 static int
1870 foreachfile_callback (char *dirname, void *data1, void *data2)
1871 {
1872 file_worker_func *func = *(file_worker_func **) data1;
1873
1874 int is_done = 0;
1875 char *argz = 0;
1876 size_t argz_len = 0;
1877
1878 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
1879 goto cleanup;
1880 if (!argz)
1881 goto cleanup;
1882
1883 {
1884 char *filename = 0;
1885 while ((filename = argz_next (argz, argz_len, filename)))
1886 if ((is_done = (*func) (filename, data2)))
1887 break;
1888 }
1889
1890 cleanup:
1891 FREE (argz);
1892
1893 return is_done;
1894 }
1895
1896
1897
1898
1899
1900
1901
1902
1903 int
1904 lt_dlforeachfile (const char *search_path,
1905 int (*func) (const char *filename, void *data),
1906 void *data)
1907 {
1908 int is_done = 0;
1909 file_worker_func **fpptr = &func;
1910
1911 if (search_path)
1912 {
1913
1914
1915 is_done = foreach_dirinpath (search_path, 0,
1916 foreachfile_callback, fpptr, data);
1917 }
1918 else
1919 {
1920
1921 is_done = foreach_dirinpath (user_search_path, 0,
1922 foreachfile_callback, fpptr, data);
1923 if (!is_done)
1924 {
1925 is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1926 foreachfile_callback, fpptr, data);
1927 }
1928
1929 #if defined LT_MODULE_PATH_VAR
1930 if (!is_done)
1931 {
1932 is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1933 foreachfile_callback, fpptr, data);
1934 }
1935 #endif
1936 #if defined LT_DLSEARCH_PATH
1937 if (!is_done && *sys_dlsearch_path)
1938 {
1939 is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1940 foreachfile_callback, fpptr, data);
1941 }
1942 #endif
1943 }
1944
1945 return is_done;
1946 }
1947
1948 int
1949 lt_dlclose (lt_dlhandle handle)
1950 {
1951 lt_dlhandle cur, last;
1952 int errors = 0;
1953
1954
1955 last = cur = handles;
1956 while (cur && handle != cur)
1957 {
1958 last = cur;
1959 cur = cur->next;
1960 }
1961
1962 if (!cur)
1963 {
1964 LT__SETERROR (INVALID_HANDLE);
1965 ++errors;
1966 goto done;
1967 }
1968
1969 cur = handle;
1970 cur->info.ref_count--;
1971
1972
1973
1974
1975
1976 if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1977 {
1978 lt_user_data data = cur->vtable->dlloader_data;
1979
1980 if (cur != handles)
1981 {
1982 last->next = cur->next;
1983 }
1984 else
1985 {
1986 handles = cur->next;
1987 }
1988
1989 errors += cur->vtable->module_close (data, cur->module);
1990 errors += unload_deplibs (handle);
1991
1992
1993 FREE (cur->interface_data);
1994
1995 FREE (cur->info.filename);
1996 FREE (cur->info.name);
1997 FREE (cur);
1998
1999 goto done;
2000 }
2001
2002 if (LT_DLIS_RESIDENT (handle))
2003 {
2004 LT__SETERROR (CLOSE_RESIDENT_MODULE);
2005 ++errors;
2006 }
2007
2008 done:
2009 return errors;
2010 }
2011
2012 void *
2013 lt_dlsym (lt_dlhandle place, const char *symbol)
2014 {
2015 size_t lensym;
2016 char lsym[LT_SYMBOL_LENGTH];
2017 char *sym;
2018 void *address;
2019 lt_user_data data;
2020 lt_dlhandle handle;
2021
2022 if (!place)
2023 {
2024 LT__SETERROR (INVALID_HANDLE);
2025 return 0;
2026 }
2027
2028 handle = place;
2029
2030 if (!symbol)
2031 {
2032 LT__SETERROR (SYMBOL_NOT_FOUND);
2033 return 0;
2034 }
2035
2036 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
2037 + LT_STRLEN (handle->info.name);
2038
2039 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
2040 {
2041 sym = lsym;
2042 }
2043 else
2044 {
2045 sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
2046 if (!sym)
2047 {
2048 LT__SETERROR (BUFFER_OVERFLOW);
2049 return 0;
2050 }
2051 }
2052
2053 data = handle->vtable->dlloader_data;
2054 if (handle->info.name)
2055 {
2056 const char *saved_error;
2057
2058 LT__GETERROR (saved_error);
2059
2060
2061 if (handle->vtable->sym_prefix)
2062 {
2063 strcpy(sym, handle->vtable->sym_prefix);
2064 strcat(sym, handle->info.name);
2065 }
2066 else
2067 {
2068 strcpy(sym, handle->info.name);
2069 }
2070
2071 strcat(sym, "_LTX_");
2072 strcat(sym, symbol);
2073
2074
2075 address = handle->vtable->find_sym (data, handle->module, sym);
2076 if (address)
2077 {
2078 if (sym != lsym)
2079 {
2080 FREE (sym);
2081 }
2082 return address;
2083 }
2084 LT__SETERRORSTR (saved_error);
2085 }
2086
2087
2088 if (handle->vtable->sym_prefix)
2089 {
2090 strcpy(sym, handle->vtable->sym_prefix);
2091 strcat(sym, symbol);
2092 }
2093 else
2094 {
2095 strcpy(sym, symbol);
2096 }
2097
2098 address = handle->vtable->find_sym (data, handle->module, sym);
2099 if (sym != lsym)
2100 {
2101 FREE (sym);
2102 }
2103
2104 return address;
2105 }
2106
2107 const char *
2108 lt_dlerror (void)
2109 {
2110 const char *error;
2111
2112 LT__GETERROR (error);
2113 LT__SETERRORSTR (0);
2114
2115 return error;
2116 }
2117
2118 static int
2119 lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
2120 {
2121 int errors = 0;
2122 char *canonical = 0;
2123 char *argz = 0;
2124 size_t argz_len = 0;
2125
2126 assert (ppath);
2127 assert (dir && *dir);
2128
2129 if (canonicalize_path (dir, &canonical) != 0)
2130 {
2131 ++errors;
2132 goto cleanup;
2133 }
2134
2135 assert (canonical && *canonical);
2136
2137
2138 if (*ppath == 0)
2139 {
2140 assert (!before);
2141 assert (dir);
2142
2143 *ppath = lt__strdup (dir);
2144 if (*ppath == 0)
2145 ++errors;
2146
2147 goto cleanup;
2148 }
2149
2150 assert (ppath && *ppath);
2151
2152 if (argzize_path (*ppath, &argz, &argz_len) != 0)
2153 {
2154 ++errors;
2155 goto cleanup;
2156 }
2157
2158
2159
2160
2161
2162
2163 if (before)
2164 {
2165 assert (*ppath <= before);
2166 assert ((int) (before - *ppath) <= (int) strlen (*ppath));
2167
2168 before = before - *ppath + argz;
2169 }
2170
2171 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2172 {
2173 ++errors;
2174 goto cleanup;
2175 }
2176
2177 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
2178 MEMREASSIGN(*ppath, argz);
2179
2180 cleanup:
2181 FREE (argz);
2182 FREE (canonical);
2183
2184 return errors;
2185 }
2186
2187 int
2188 lt_dladdsearchdir (const char *search_dir)
2189 {
2190 int errors = 0;
2191
2192 if (search_dir && *search_dir)
2193 {
2194 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2195 ++errors;
2196 }
2197
2198 return errors;
2199 }
2200
2201 int
2202 lt_dlinsertsearchdir (const char *before, const char *search_dir)
2203 {
2204 int errors = 0;
2205
2206 if (before)
2207 {
2208 if ((before < user_search_path)
2209 || (before >= user_search_path + LT_STRLEN (user_search_path)))
2210 {
2211 LT__SETERROR (INVALID_POSITION);
2212 return 1;
2213 }
2214 }
2215
2216 if (search_dir && *search_dir)
2217 {
2218 if (lt_dlpath_insertdir (&user_search_path,
2219 (char *) before, search_dir) != 0)
2220 {
2221 ++errors;
2222 }
2223 }
2224
2225 return errors;
2226 }
2227
2228 int
2229 lt_dlsetsearchpath (const char *search_path)
2230 {
2231 int errors = 0;
2232
2233 FREE (user_search_path);
2234
2235 if (!search_path || !LT_STRLEN (search_path))
2236 {
2237 return errors;
2238 }
2239
2240 if (canonicalize_path (search_path, &user_search_path) != 0)
2241 ++errors;
2242
2243 return errors;
2244 }
2245
2246 const char *
2247 lt_dlgetsearchpath (void)
2248 {
2249 const char *saved_path;
2250
2251 saved_path = user_search_path;
2252
2253 return saved_path;
2254 }
2255
2256 int
2257 lt_dlmakeresident (lt_dlhandle handle)
2258 {
2259 int errors = 0;
2260
2261 if (!handle)
2262 {
2263 LT__SETERROR (INVALID_HANDLE);
2264 ++errors;
2265 }
2266 else
2267 {
2268 handle->info.is_resident = 1;
2269 }
2270
2271 return errors;
2272 }
2273
2274 int
2275 lt_dlisresident (lt_dlhandle handle)
2276 {
2277 if (!handle)
2278 {
2279 LT__SETERROR (INVALID_HANDLE);
2280 return -1;
2281 }
2282
2283 return LT_DLIS_RESIDENT (handle);
2284 }
2285
2286
2287
2288
2289
2290 typedef struct {
2291 char *id_string;
2292 lt_dlhandle_interface *iface;
2293 } lt__interface_id;
2294
2295 lt_dlinterface_id
2296 lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
2297 {
2298 lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2299
2300
2301
2302 if (interface_id)
2303 {
2304 interface_id->id_string = lt__strdup (id_string);
2305 if (!interface_id->id_string)
2306 FREE (interface_id);
2307 else
2308 interface_id->iface = iface;
2309 }
2310
2311 return (lt_dlinterface_id) interface_id;
2312 }
2313
2314 void lt_dlinterface_free (lt_dlinterface_id key)
2315 {
2316 lt__interface_id *interface_id = (lt__interface_id *)key;
2317 FREE (interface_id->id_string);
2318 FREE (interface_id);
2319 }
2320
2321 void *
2322 lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2323 {
2324 int n_elements = 0;
2325 void *stale = (void *) 0;
2326 lt_dlhandle cur = handle;
2327 int i;
2328
2329 if (cur->interface_data)
2330 while (cur->interface_data[n_elements].key)
2331 ++n_elements;
2332
2333 for (i = 0; i < n_elements; ++i)
2334 {
2335 if (cur->interface_data[i].key == key)
2336 {
2337 stale = cur->interface_data[i].data;
2338 break;
2339 }
2340 }
2341
2342
2343
2344 if (i == n_elements)
2345 {
2346 lt_interface_data *temp
2347 = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2348
2349 if (!temp)
2350 {
2351 stale = 0;
2352 goto done;
2353 }
2354
2355 cur->interface_data = temp;
2356
2357
2358 cur->interface_data[i].key = key;
2359 cur->interface_data[1+ i].key = 0;
2360 }
2361
2362 cur->interface_data[i].data = data;
2363
2364 done:
2365 return stale;
2366 }
2367
2368 void *
2369 lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
2370 {
2371 void *result = (void *) 0;
2372 lt_dlhandle cur = handle;
2373
2374
2375 if (cur->interface_data)
2376 {
2377 int i;
2378 for (i = 0; cur->interface_data[i].key; ++i)
2379 {
2380 if (cur->interface_data[i].key == key)
2381 {
2382 result = cur->interface_data[i].data;
2383 break;
2384 }
2385 }
2386 }
2387
2388 return result;
2389 }
2390
2391 const lt_dlinfo *
2392 lt_dlgetinfo (lt_dlhandle handle)
2393 {
2394 if (!handle)
2395 {
2396 LT__SETERROR (INVALID_HANDLE);
2397 return 0;
2398 }
2399
2400 return &(handle->info);
2401 }
2402
2403
2404 lt_dlhandle
2405 lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2406 {
2407 lt_dlhandle handle = place;
2408 lt__interface_id *iterator = (lt__interface_id *) iface;
2409
2410 assert (iface);
2411
2412 if (!handle)
2413 handle = handles;
2414 else
2415 handle = handle->next;
2416
2417
2418 while (handle && iterator->iface
2419 && ((*iterator->iface) (handle, iterator->id_string) != 0))
2420 {
2421 handle = handle->next;
2422 }
2423
2424 return handle;
2425 }
2426
2427
2428 lt_dlhandle
2429 lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2430 {
2431 lt_dlhandle handle = 0;
2432
2433 assert (iface);
2434
2435 while ((handle = lt_dlhandle_iterate (iface, handle)))
2436 {
2437 lt_dlhandle cur = handle;
2438 if (cur && cur->info.name && STREQ (cur->info.name, module_name))
2439 break;
2440 }
2441
2442 return handle;
2443 }
2444
2445
2446 int
2447 lt_dlhandle_map (lt_dlinterface_id iface,
2448 int (*func) (lt_dlhandle handle, void *data), void *data)
2449 {
2450 lt__interface_id *iterator = (lt__interface_id *) iface;
2451 lt_dlhandle cur = handles;
2452
2453 assert (iface);
2454
2455 while (cur)
2456 {
2457 int errorcode = 0;
2458
2459
2460 while (cur && iterator->iface
2461 && ((*iterator->iface) (cur, iterator->id_string) != 0))
2462 {
2463 cur = cur->next;
2464 }
2465
2466 if ((errorcode = (*func) (cur, data)) != 0)
2467 return errorcode;
2468 }
2469
2470 return 0;
2471 }