~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Bochs x86 Emulator
bochs/ltdl.c

Version: ~ [ 2.3.5 ] ~ [ 2.3 ] ~

** Warning: Cannot open xref database.

1 ///////////////////////////////////////////////////////////////////////// 2 // $Id: ltdl.c,v 1.4 2002/11/01 13:02:15 bdenney Exp $ 3 // 4 // NOTE: The ltdl library comes from the Libtool package. Bochs uses 5 // ltdl and libtool to build and load plugins. The libtool 6 // documentation describes how to copy ltdl.c and ltdl.h into your 7 // distribution, so it is clearly legal to do so. 8 ///////////////////////////////////////////////////////////////////////// 9 10 /* ltdl.c -- system independent dlopen wrapper 11 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. 12 Originally by Thomas Tanner <tanner@ffii.org> 13 This file is part of GNU Libtool. 14 15 This library is free software; you can redistribute it and/or 16 modify it under the terms of the GNU Lesser General Public 17 License as published by the Free Software Foundation; either 18 version 2 of the License, or (at your option) any later version. 19 20 As a special exception to the GNU Lesser General Public License, 21 if you distribute this file as part of a program or library that 22 is built using GNU libtool, you may include it under the same 23 distribution terms that you use for the rest of that program. 24 25 This library is distributed in the hope that it will be useful, 26 but WITHOUT ANY WARRANTY; without even the implied warranty of 27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 Lesser General Public License for more details. 29 30 You should have received a copy of the GNU Lesser General Public 31 License along with this library; if not, write to the Free Software 32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 33 02111-1307 USA 34 35 */ 36 37 // ltdlconf.h added for Bochs 38 #include "ltdlconf.h" 39 40 #if HAVE_CONFIG_H 41 # include <config.h> 42 #endif 43 44 #if HAVE_UNISTD_H 45 # include <unistd.h> 46 #endif 47 48 #if HAVE_STDIO_H 49 # include <stdio.h> 50 #endif 51 52 #if HAVE_STDLIB_H 53 # include <stdlib.h> 54 #endif 55 56 #if HAVE_STRING_H 57 # include <string.h> 58 #else 59 # if HAVE_STRINGS_H 60 # include <strings.h> 61 # endif 62 #endif 63 64 #if HAVE_CTYPE_H 65 # include <ctype.h> 66 #endif 67 68 #if HAVE_MALLOC_H 69 # include <malloc.h> 70 #endif 71 72 #if HAVE_MEMORY_H 73 # include <memory.h> 74 #endif 75 76 #if HAVE_ERRNO_H 77 # include <errno.h> 78 #endif 79 80 #if HAVE_DIRENT_H 81 # include <dirent.h> 82 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) 83 #else 84 # define dirent direct 85 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) 86 # if HAVE_SYS_NDIR_H 87 # include <sys/ndir.h> 88 # endif 89 # if HAVE_SYS_DIR_H 90 # include <sys/dir.h> 91 # endif 92 # if HAVE_NDIR_H 93 # include <ndir.h> 94 # endif 95 #endif 96 97 #if HAVE_ARGZ_H 98 # include <argz.h> 99 #endif 100 101 #if HAVE_ASSERT_H 102 # include <assert.h> 103 #else 104 # ifdef __GNUC__ 105 # warning using my own assert 106 # endif 107 # define assert(cond) while (!(cond)) { fprintf (stderr, "Assert failed at %s:%d: '%s'\n", __FILE__, __LINE__, #cond); abort(); } 108 #endif 109 110 #define LTDEBUG_PRINTF(x) /* debug output disabled */ 111 //#define LTDEBUG_PRINTF(x) do{ printf("LT_DEBUG: "); printf x; } while (0) 112 113 #include "ltdl.h" 114 115 116 117 118 /* --- WINDOWS SUPPORT --- */ 119 120 121 #ifdef DLL_EXPORT 122 # define LT_GLOBAL_DATA __declspec(dllexport) 123 #else 124 # define LT_GLOBAL_DATA 125 #endif 126 127 /* fopen() mode flags for reading a text file */ 128 #undef LT_READTEXT_MODE 129 #ifdef __WINDOWS__ 130 # define LT_READTEXT_MODE "rt" 131 #else 132 # define LT_READTEXT_MODE "r" 133 #endif 134 135 136 137 138 /* --- MANIFEST CONSTANTS --- */ 139 140 141 /* Standard libltdl search path environment variable name */ 142 #undef LTDL_SEARCHPATH_VAR 143 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" 144 145 /* Standard libtool archive file extension. */ 146 #undef LTDL_ARCHIVE_EXT 147 #define LTDL_ARCHIVE_EXT ".la" 148 149 /* max. filename length */ 150 #ifndef LT_FILENAME_MAX 151 # define LT_FILENAME_MAX 1024 152 #endif 153 154 /* This is the maximum symbol size that won't require malloc/free */ 155 #undef LT_SYMBOL_LENGTH 156 #define LT_SYMBOL_LENGTH 128 157 158 /* This accounts for the _LTX_ separator */ 159 #undef LT_SYMBOL_OVERHEAD 160 #define LT_SYMBOL_OVERHEAD 5 161 162 163 164 165 /* --- MEMORY HANDLING --- */ 166 167 168 /* These are the functions used internally. In addition to making 169 use of the associated function pointers above, they also perform 170 error handling. */ 171 static char *lt_estrdup LT_PARAMS((const char *str)); 172 static lt_ptr lt_emalloc LT_PARAMS((size_t size)); 173 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); 174 175 static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); 176 177 /* These are the pointers that can be changed by the caller: */ 178 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) 179 = (lt_ptr (*) LT_PARAMS((size_t))) malloc; 180 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) 181 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; 182 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) 183 = (void (*) LT_PARAMS((lt_ptr))) free; 184 185 /* The following macros reduce the amount of typing needed to cast 186 assigned memory. */ 187 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) 188 #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp))) 189 #define LT_DLFREE(p) \ 190 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END 191 192 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) 193 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) 194 195 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ 196 if ((p) != (q)) { lt_dlfree (p); (p) = (q); (q) = 0; } \ 197 } LT_STMT_END 198 199 200 /* --- REPLACEMENT FUNCTIONS --- */ 201 202 203 #undef strdup 204 #define strdup rpl_strdup 205 206 static char *strdup LT_PARAMS((const char *str)); 207 208 char * 209 strdup(str) 210 const char *str; 211 { 212 char *tmp = 0; 213 214 if (str) 215 { 216 tmp = LT_DLMALLOC (char, 1+ strlen (str)); 217 if (tmp) 218 { 219 strcpy(tmp, str); 220 } 221 } 222 223 return tmp; 224 } 225 226 227 #if ! HAVE_STRCMP 228 229 #undef strcmp 230 #define strcmp rpl_strcmp 231 232 static int strcmp LT_PARAMS((const char *str1, const char *str2)); 233 234 int 235 strcmp (str1, str2) 236 const char *str1; 237 const char *str2; 238 { 239 if (str1 == str2) 240 return 0; 241 if (str1 == 0) 242 return -1; 243 if (str2 == 0) 244 return 1; 245 246 for (;*str1 && *str2; ++str1, ++str2) 247 { 248 if (*str1 != *str2) 249 break; 250 } 251 252 return (int)(*str1 - *str2); 253 } 254 #endif 255 256 257 #if ! HAVE_STRCHR 258 259 # if HAVE_INDEX 260 # define strchr index 261 # else 262 # define strchr rpl_strchr 263 264 static const char *strchr LT_PARAMS((const char *str, int ch)); 265 266 const char* 267 strchr(str, ch) 268 const char *str; 269 int ch; 270 { 271 const char *p; 272 273 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) 274 /*NOWORK*/; 275 276 return (*p == (char)ch) ? p : 0; 277 } 278 279 # endif 280 #endif /* !HAVE_STRCHR */ 281 282 283 #if ! HAVE_STRRCHR 284 285 # if HAVE_RINDEX 286 # define strrchr rindex 287 # else 288 # define strrchr rpl_strrchr 289 290 static const char *strrchr LT_PARAMS((const char *str, int ch)); 291 292 const char* 293 strrchr(str, ch) 294 const char *str; 295 int ch; 296 { 297 const char *p, *q = 0; 298 299 for (p = str; *p != LT_EOS_CHAR; ++p) 300 { 301 if (*p == (char) ch) 302 { 303 q = p; 304 } 305 } 306 307 return q; 308 } 309 310 # endif 311 #endif 312 313 /* NOTE: Neither bcopy nor the memcpy implementation below can 314 reliably handle copying in overlapping areas of memory. Use 315 memmove (for which there is a fallback implmentation below) 316 if you need that behaviour. */ 317 #if ! HAVE_MEMCPY 318 319 # if HAVE_BCOPY 320 # define memcpy(dest, src, size) bcopy (src, dest, size) 321 # else 322 # define memcpy rpl_memcpy 323 324 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); 325 326 lt_ptr 327 memcpy (dest, src, size) 328 lt_ptr dest; 329 const lt_ptr src; 330 size_t size; 331 { 332 size_t i = 0; 333 334 for (i = 0; i < size; ++i) 335 { 336 dest[i] = src[i]; 337 } 338 339 return dest; 340 } 341 342 # endif /* !HAVE_BCOPY */ 343 #endif /* !HAVE_MEMCPY */ 344 345 #if ! HAVE_MEMMOVE 346 # define memmove rpl_memmove 347 348 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); 349 350 lt_ptr 351 memmove (dest, src, size) 352 lt_ptr dest; 353 const lt_ptr src; 354 size_t size; 355 { 356 size_t i; 357 358 if (dest < src) 359 for (i = 0; i < size; ++i) 360 { 361 dest[i] = src[i]; 362 } 363 else if (dest > src) 364 for (i = size -1; i >= 0; --i) 365 { 366 dest[i] = src[i]; 367 } 368 369 return dest; 370 } 371 372 #endif /* !HAVE_MEMMOVE */ 373 374 375 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>, 376 ``realloc is not entirely portable'' 377 In any case we want to use the allocator supplied by the user without 378 burdening them with an lt_dlrealloc function pointer to maintain. 379 Instead implement our own version (with known boundary conditions) 380 using lt_dlmalloc and lt_dlfree. */ 381 382 #undef realloc 383 #define realloc rpl_realloc 384 385 lt_ptr 386 realloc (ptr, size) 387 lt_ptr ptr; 388 size_t size; 389 { 390 if (size <= 0) 391 { 392 /* For zero or less bytes, free the original memory */ 393 if (ptr != 0) 394 { 395 lt_dlfree (ptr); 396 } 397 398 return (lt_ptr) 0; 399 } 400 else if (ptr == 0) 401 { 402 /* Allow reallocation of a NULL pointer. */ 403 return lt_dlmalloc (size); 404 } 405 else 406 { 407 /* Allocate a new block, copy and free the old block. */ 408 lt_ptr mem = lt_dlmalloc (size); 409 410 if (mem) 411 { 412 memcpy (mem, ptr, size); 413 lt_dlfree (ptr); 414 } 415 416 /* Note that the contents of PTR are not damaged if there is 417 insufficient memory to realloc. */ 418 return mem; 419 } 420 } 421 422 423 #if ! HAVE_ARGZ_APPEND 424 # define argz_append rpl_argz_append 425 426 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, 427 const char *buf, size_t buf_len)); 428 429 error_t 430 argz_append (pargz, pargz_len, buf, buf_len) 431 char **pargz; 432 size_t *pargz_len; 433 const char *buf; 434 size_t buf_len; 435 { 436 size_t argz_len; 437 char *argz; 438 439 assert (pargz); 440 assert (pargz_len); 441 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); 442 443 /* If nothing needs to be appended, no more work is required. */ 444 if (buf_len == 0) 445 return 0; 446 447 /* Ensure there is enough room to append BUF_LEN. */ 448 argz_len = *pargz_len + buf_len; 449 argz = LT_DLREALLOC (char, *pargz, argz_len); 450 if (!argz) 451 return ENOMEM; 452 453 /* Copy characters from BUF after terminating '\0' in ARGZ. */ 454 memcpy (argz + *pargz_len, buf, buf_len); 455 456 /* Assign new values. */ 457 *pargz = argz; 458 *pargz_len = argz_len; 459 460 return 0; 461 } 462 #endif /* !HAVE_ARGZ_APPEND */ 463 464 465 #if ! HAVE_ARGZ_CREATE_SEP 466 # define argz_create_sep rpl_argz_create_sep 467 468 static error_t argz_create_sep LT_PARAMS((const char *str, int delim, 469 char **pargz, size_t *pargz_len)); 470 471 error_t 472 argz_create_sep (str, delim, pargz, pargz_len) 473 const char *str; 474 int delim; 475 char **pargz; 476 size_t *pargz_len; 477 { 478 size_t argz_len; 479 char *argz = 0; 480 481 assert (str); 482 assert (pargz); 483 assert (pargz_len); 484 485 /* Make a copy of STR, but replacing each occurence of 486 DELIM with '\0'. */ 487 argz_len = 1+ LT_STRLEN (str); 488 if (argz_len) 489 { 490 const char *p; 491 char *q; 492 493 argz = LT_DLMALLOC (char, argz_len); 494 if (!argz) 495 return ENOMEM; 496 497 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) 498 { 499 if (*p == delim) 500 { 501 /* Ignore leading delimiters, and fold consecutive 502 delimiters in STR into a single '\0' in ARGZ. */ 503 if ((q > argz) && (q[-1] != LT_EOS_CHAR)) 504 *q++ = LT_EOS_CHAR; 505 else 506 --argz_len; 507 } 508 else 509 *q++ = *p; 510 } 511 /* Copy terminating LT_EOS_CHAR. */ 512 *q = *p; 513 } 514 515 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ 516 if (!argz_len) 517 LT_DLFREE (argz); 518 519 /* Assign new values. */ 520 *pargz = argz; 521 *pargz_len = argz_len; 522 523 return 0; 524 } 525 #endif /* !HAVE_ARGZ_CREATE_SEP */ 526 527 528 #if ! HAVE_ARGZ_INSERT 529 # define argz_insert rpl_argz_insert 530 531 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, 532 char *before, const char *entry)); 533 534 error_t 535 argz_insert (pargz, pargz_len, before, entry) 536 char **pargz; 537 size_t *pargz_len; 538 char *before; 539 const char *entry; 540 { 541 assert (pargz); 542 assert (pargz_len); 543 assert (entry && *entry); 544 545 /* Either PARGZ/PARGZ_LEN is empty and BEFORE is NULL, 546 or BEFORE points into an address within the ARGZ vector. */ 547 assert ((!*pargz && !*pargz_len && !before) 548 || ((*pargz <= before) && (before < (*pargz + *pargz_len)))); 549 550 /* No BEFORE address indicates ENTRY should be inserted after the 551 current last element. */ 552 if (!before) 553 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); 554 555 /* This probably indicates a programmer error, but to preserve 556 semantics, scan back to the start of an entry if BEFORE points 557 into the middle of it. */ 558 while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR)) 559 --before; 560 561 { 562 size_t entry_len = 1+ LT_STRLEN (entry); 563 size_t argz_len = *pargz_len + entry_len; 564 size_t offset = before - *pargz; 565 char *argz = LT_DLREALLOC (char, *pargz, argz_len); 566 567 if (!argz) 568 return ENOMEM; 569 570 /* Make BEFORE point to the equivalent offset in ARGZ that it 571 used to have in *PARGZ incase realloc() moved the block. */ 572 before = argz + offset; 573 574 /* Move the ARGZ entries starting at BEFORE up into the new 575 space at the end -- making room to copy ENTRY into the 576 resulting gap. */ 577 memmove (before + entry_len, before, *pargz_len - offset); 578 memcpy (before, entry, entry_len); 579 580 /* Assign new values. */ 581 *pargz = argz; 582 *pargz_len = argz_len; 583 } 584 585 return 0; 586 } 587 #endif /* !HAVE_ARGZ_INSERT */ 588 589 590 #if ! HAVE_ARGZ_NEXT 591 # define argz_next rpl_argz_next 592 593 static char *argz_next LT_PARAMS((char *argz, size_t argz_len, 594 const char *entry)); 595 596 char * 597 argz_next (argz, argz_len, entry) 598 char *argz; 599 size_t argz_len; 600 const char *entry; 601 { 602 assert ((argz && argz_len) || (!argz && !argz_len)); 603 604 if (entry) 605 { 606 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address 607 within the ARGZ vector. */ 608 assert ((!argz && !argz_len) 609 || ((argz <= entry) && (entry < (argz + argz_len)))); 610 611 /* Move to the char immediately after the terminating 612 '\0' of ENTRY. */ 613 entry = 1+ strchr (entry, LT_EOS_CHAR); 614 615 /* Return either the new ENTRY, or else NULL if ARGZ is 616 exhausted. */ 617 return (entry >= argz + argz_len) ? 0 : (char *) entry; 618 } 619 else 620 { 621 /* This should probably be flagged as a programmer error, 622 since starting an argz_next loop with the iterator set 623 to ARGZ is safer. To preserve semantics, handle the NULL 624 case by returning the start of ARGZ (if any). */ 625 if (argz_len > 0) 626 return argz; 627 else 628 return 0; 629 } 630 } 631 #endif /* !HAVE_ARGZ_NEXT */ 632 633 634 635 #if ! HAVE_ARGZ_STRINGIFY 636 # define argz_stringify rpl_argz_stringify 637 638 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, 639 int sep)); 640 641 void 642 argz_stringify (argz, argz_len, sep) 643 char *argz; 644 size_t argz_len; 645 int sep; 646 { 647 assert ((argz && argz_len) || (!argz && !argz_len)); 648 649 if (sep) 650 { 651 --argz_len; /* don't stringify the terminating EOS */ 652 while (--argz_len > 0) 653 { 654 if (argz[argz_len] == LT_EOS_CHAR) 655 argz[argz_len] = sep; 656 } 657 } 658 } 659 #endif /* !HAVE_ARGZ_STRINGIFY */ 660 661 662 663 664 /* --- TYPE DEFINITIONS -- */ 665 666 667 /* This type is used for the array of caller data sets in each handler. */ 668 typedef struct { 669 lt_dlcaller_id key; 670 lt_ptr data; 671 } lt_caller_data; 672 673 674 675 676 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ 677 678 679 /* Extract the diagnostic strings from the error table macro in the same 680 order as the enumerated indices in ltdl.h. */ 681 682 static const char *lt_dlerror_strings[] = 683 { 684 lt_dlerror_names_list 685 0 686 }; 687 688 /* This structure is used for the list of registered loaders. */ 689 struct lt_dlloader { 690 struct lt_dlloader *next; 691 const char *loader_name; /* identifying name for each loader */ 692 const char *sym_prefix; /* prefix for symbols */ 693 lt_module_open *module_open; 694 lt_module_close *module_close; 695 lt_find_sym *find_sym; 696 lt_dlloader_exit *dlloader_exit; 697 lt_user_data dlloader_data; 698 }; 699 700 struct lt_dlhandle_struct { 701 struct lt_dlhandle_struct *next; 702 lt_dlloader *loader; /* dlopening interface */ 703 lt_dlinfo info; 704 int depcount; /* number of dependencies */ 705 lt_dlhandle *deplibs; /* dependencies */ 706 lt_module module; /* system module handle */ 707 lt_ptr system; /* system specific data */ 708 lt_caller_data *caller_data; /* per caller associated data */ 709 int flags; /* various boolean stats */ 710 }; 711 712 /* Various boolean flags can be stored in the flags field of an 713 lt_dlhandle_struct... */ 714 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) 715 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) 716 717 #define LT_DLRESIDENT_FLAG (0x01 << 0) 718 /* ...add more flags here... */ 719 720 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) 721 722 723 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] 724 725 static const char objdir[] = LTDL_OBJDIR; 726 static const char archive_ext[] = LTDL_ARCHIVE_EXT; 727 #ifdef LTDL_SHLIB_EXT 728 static const char shlib_ext[] = LTDL_SHLIB_EXT; 729 #endif 730 #ifdef LTDL_SYSSEARCHPATH 731 static const char sys_search_path[] = LTDL_SYSSEARCHPATH; 732 #endif 733 734 735 736 737 /* --- MUTEX LOCKING --- */ 738 739 740 /* Macros to make it easier to run the lock functions only if they have 741 been registered. The reason for the complicated lock macro is to 742 ensure that the stored error message from the last error is not 743 accidentally erased if the current function doesn't generate an 744 error of its own. */ 745 #define LT_DLMUTEX_LOCK() LT_STMT_START { \ 746 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ 747 } LT_STMT_END 748 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ 749 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ 750 } LT_STMT_END 751 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ 752 if (lt_dlmutex_seterror_func) \ 753 (*lt_dlmutex_seterror_func) (errormsg); \ 754 else lt_dllast_error = (errormsg); } LT_STMT_END 755 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ 756 if (lt_dlmutex_seterror_func) \ 757 (errormsg) = (*lt_dlmutex_geterror_func) (); \ 758 else (errormsg) = lt_dllast_error; } LT_STMT_END 759 760 /* The mutex functions stored here are global, and are necessarily the 761 same for all threads that wish to share access to libltdl. */ 762 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; 763 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; 764 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; 765 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; 766 static const char *lt_dllast_error = 0; 767 768 769 /* Either set or reset the mutex functions. Either all the arguments must 770 be valid functions, or else all can be NULL to turn off locking entirely. 771 The registered functions should be manipulating a static global lock 772 from the lock() and unlock() callbacks, which needs to be reentrant. */ 773 int 774 lt_dlmutex_register (lock, unlock, seterror, geterror) 775 lt_dlmutex_lock *lock; 776 lt_dlmutex_unlock *unlock; 777 lt_dlmutex_seterror *seterror; 778 lt_dlmutex_geterror *geterror; 779 { 780 lt_dlmutex_unlock *old_unlock = unlock; 781 int errors = 0; 782 783 /* Lock using the old lock() callback, if any. */ 784 LT_DLMUTEX_LOCK (); 785 786 if ((lock && unlock && seterror && geterror) 787 || !(lock || unlock || seterror || geterror)) 788 { 789 lt_dlmutex_lock_func = lock; 790 lt_dlmutex_unlock_func = unlock; 791 lt_dlmutex_geterror_func = geterror; 792 } 793 else 794 { 795 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); 796 ++errors; 797 } 798 799 /* Use the old unlock() callback we saved earlier, if any. Otherwise 800 record any errors using internal storage. */ 801 if (old_unlock) 802 (*old_unlock) (); 803 804 /* Return the number of errors encountered during the execution of 805 this function. */ 806 return errors; 807 } 808 809 810 811 812 /* --- ERROR HANDLING --- */ 813 814 815 static const char **user_error_strings = 0; 816 static int errorcount = LT_ERROR_MAX; 817 818 int 819 lt_dladderror (diagnostic) 820 const char *diagnostic; 821 { 822 int errindex = 0; 823 int result = -1; 824 const char **temp = (const char **) 0; 825 826 assert (diagnostic); 827 828 LT_DLMUTEX_LOCK (); 829 830 errindex = errorcount - LT_ERROR_MAX; 831 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); 832 if (temp) 833 { 834 user_error_strings = temp; 835 user_error_strings[errindex] = diagnostic; 836 result = errorcount++; 837 } 838 839 LT_DLMUTEX_UNLOCK (); 840 841 return result; 842 } 843 844 int 845 lt_dlseterror (errindex) 846 int errindex; 847 { 848 int errors = 0; 849 850 LT_DLMUTEX_LOCK (); 851 852 if (errindex >= errorcount || errindex < 0) 853 { 854 /* Ack! Error setting the error message! */ 855 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); 856 ++errors; 857 } 858 else if (errindex < LT_ERROR_MAX) 859 { 860 /* No error setting the error message! */ 861 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); 862 } 863 else 864 { 865 /* No error setting the error message! */ 866 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); 867 } 868 869 LT_DLMUTEX_UNLOCK (); 870 871 return errors; 872 } 873 874 lt_ptr 875 lt_emalloc (size) 876 size_t size; 877 { 878 lt_ptr mem = lt_dlmalloc (size); 879 if (size && !mem) 880 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 881 return mem; 882 } 883 884 lt_ptr 885 lt_erealloc (addr, size) 886 lt_ptr addr; 887 size_t size; 888 { 889 lt_ptr mem = realloc (addr, size); 890 if (size && !mem) 891 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 892 return mem; 893 } 894 895 char * 896 lt_estrdup (str) 897 const char *str; 898 { 899 char *dup = strdup (str); 900 if (LT_STRLEN (str) && !dup) 901 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 902 return dup; 903 } 904 905 906 907 908 /* --- DLOPEN() INTERFACE LOADER --- */ 909 910 911 /* The Cygwin dlopen implementation prints a spurious error message to 912 stderr if its call to LoadLibrary() fails for any reason. We can 913 mitigate this by not using the Cygwin implementation, and falling 914 back to our own LoadLibrary() wrapper. */ 915 #if HAVE_LIBDL && !defined(__CYGWIN__) 916 917 /* dynamic linking with dlopen/dlsym */ 918 919 #if HAVE_DLFCN_H 920 # include <dlfcn.h> 921 #endif 922 923 #if HAVE_SYS_DL_H 924 # include <sys/dl.h> 925 #endif 926 927 #ifdef RTLD_GLOBAL 928 # define LT_GLOBAL RTLD_GLOBAL 929 #else 930 # ifdef DL_GLOBAL 931 # define LT_GLOBAL DL_GLOBAL 932 # endif 933 #endif /* !RTLD_GLOBAL */ 934 #ifndef LT_GLOBAL 935 # define LT_GLOBAL 0 936 #endif /* !LT_GLOBAL */ 937 938 /* We may have to define LT_LAZY_OR_NOW in the command line if we 939 find out it does not work in some platform. */ 940 #ifndef LT_LAZY_OR_NOW 941 # ifdef RTLD_LAZY 942 # define LT_LAZY_OR_NOW RTLD_LAZY 943 # else 944 # ifdef DL_LAZY 945 # define LT_LAZY_OR_NOW DL_LAZY 946 # endif 947 # endif /* !RTLD_LAZY */ 948 #endif 949 #ifndef LT_LAZY_OR_NOW 950 # ifdef RTLD_NOW 951 # define LT_LAZY_OR_NOW RTLD_NOW 952 # else 953 # ifdef DL_NOW 954 # define LT_LAZY_OR_NOW DL_NOW 955 # endif 956 # endif /* !RTLD_NOW */ 957 #endif 958 #ifndef LT_LAZY_OR_NOW 959 # define LT_LAZY_OR_NOW 0 960 #endif /* !LT_LAZY_OR_NOW */ 961 962 #if HAVE_DLERROR 963 # define DLERROR(arg) dlerror () 964 #else 965 # define DLERROR(arg) LT_DLSTRERROR (arg) 966 #endif 967 968 static lt_module 969 sys_dl_open (loader_data, filename) 970 lt_user_data loader_data; 971 const char *filename; 972 { 973 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW); 974 975 if (!module) 976 { 977 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); 978 } 979 980 return module; 981 } 982 983 static int 984 sys_dl_close (loader_data, module) 985 lt_user_data loader_data; 986 lt_module module; 987 { 988 int errors = 0; 989 990 if (dlclose (module) != 0) 991 { 992 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); 993 ++errors; 994 } 995 996 return errors; 997 } 998 999 static lt_ptr 1000 sys_dl_sym (loader_data, module, symbol) 1001 lt_user_data loader_data; 1002 lt_module module; 1003 const char *symbol; 1004 { 1005 lt_ptr address = dlsym (module, symbol); 1006 1007 if (!address) 1008 { 1009 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); 1010 } 1011 1012 return address; 1013 } 1014 1015 static struct lt_user_dlloader sys_dl = 1016 { 1017 # ifdef NEED_USCORE 1018 "_", 1019 # else 1020 0, 1021 # endif 1022 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; 1023 1024 1025 #endif /* HAVE_LIBDL */ 1026 1027 1028 1029 /* --- SHL_LOAD() INTERFACE LOADER --- */ 1030 1031 #if HAVE_SHL_LOAD 1032 1033 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ 1034 1035 #ifdef HAVE_DL_H 1036 # include <dl.h> 1037 #endif 1038 1039 /* some flags are missing on some systems, so we provide 1040 * harmless defaults. 1041 * 1042 * Mandatory: 1043 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. 1044 * BIND_DEFERRED - Delay code symbol resolution until actual reference. 1045 * 1046 * Optionally: 1047 * BIND_FIRST - Place the library at the head of the symbol search 1048 * order. 1049 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all 1050 * unsatisfied symbols as fatal. This flag allows 1051 * binding of unsatisfied code symbols to be deferred 1052 * until use. 1053 * [Perl: For certain libraries, like DCE, deferred 1054 * binding often causes run time problems. Adding 1055 * BIND_NONFATAL to BIND_IMMEDIATE still allows 1056 * unresolved references in situations like this.] 1057 * BIND_NOSTART - Do not call the initializer for the shared library 1058 * when the library is loaded, nor on a future call to 1059 * shl_unload(). 1060 * BIND_VERBOSE - Print verbose messages concerning possible 1061 * unsatisfied symbols. 1062 * 1063 * hp9000s700/hp9000s800: 1064 * BIND_RESTRICTED - Restrict symbols visible by the library to those 1065 * present at library load time. 1066 * DYNAMIC_PATH - Allow the loader to dynamically search for the 1067 * library specified by the path argument. 1068 */ 1069 1070 #ifndef DYNAMIC_PATH 1071 # define DYNAMIC_PATH 0 1072 #endif 1073 #ifndef BIND_RESTRICTED 1074 # define BIND_RESTRICTED 0 1075 #endif 1076 1077 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) 1078 1079 static lt_module 1080 sys_shl_open (loader_data, filename) 1081 lt_user_data loader_data; 1082 const char *filename; 1083 { 1084 static shl_t self = (shl_t) 0; 1085 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); 1086 1087 /* Since searching for a symbol against a NULL module handle will also 1088 look in everything else that was already loaded and exported with 1089 the -E compiler flag, we always cache a handle saved before any 1090 modules are loaded. */ 1091 if (!self) 1092 { 1093 lt_ptr address; 1094 shl_findsym (&self, "main", TYPE_UNDEFINED, &address); 1095 } 1096 1097 if (!filename) 1098 { 1099 module = self; 1100 } 1101 else 1102 { 1103 module = shl_load (filename, LT_BIND_FLAGS, 0L); 1104 1105 if (!module) 1106 { 1107 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1108 } 1109 } 1110 1111 return module; 1112 } 1113 1114 static int 1115 sys_shl_close (loader_data, module) 1116 lt_user_data loader_data; 1117 lt_module module; 1118 { 1119 int errors = 0; 1120 1121 if (module && (shl_unload ((shl_t) (module)) != 0)) 1122 { 1123 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1124 ++errors; 1125 } 1126 1127 return errors; 1128 } 1129 1130 static lt_ptr 1131 sys_shl_sym (loader_data, module, symbol) 1132 lt_user_data loader_data; 1133 lt_module module; 1134 const char *symbol; 1135 { 1136 lt_ptr address = 0; 1137 1138 /* sys_shl_open should never return a NULL module handle */ 1139 if (module == (lt_module) 0) 1140 { 1141 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 1142 } 1143 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) 1144 { 1145 if (!address) 1146 { 1147 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1148 } 1149 } 1150 1151 return address; 1152 } 1153 1154 static struct lt_user_dlloader sys_shl = { 1155 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 1156 }; 1157 1158 #endif /* HAVE_SHL_LOAD */ 1159 1160 1161 1162 1163 /* --- LOADLIBRARY() INTERFACE LOADER --- */ 1164 1165 #ifdef __WINDOWS__ 1166 1167 /* dynamic linking for Win32 */ 1168 1169 #include <windows.h> 1170 1171 void win32_print_last_error (char *fmtstring) 1172 { 1173 LPVOID lpMsgBuf; 1174 FormatMessage( 1175 FORMAT_MESSAGE_ALLOCATE_BUFFER | 1176 FORMAT_MESSAGE_FROM_SYSTEM | 1177 FORMAT_MESSAGE_IGNORE_INSERTS, 1178 NULL, 1179 GetLastError(), 1180 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 1181 (LPTSTR) &lpMsgBuf, 1182 0, 1183 NULL 1184 ); 1185 printf (fmtstring, (char*)lpMsgBuf); 1186 LocalFree (lpMsgBuf); 1187 } 1188 1189 /* Forward declaration; required to implement handle search below. */ 1190 static lt_dlhandle handles; 1191 1192 static lt_module 1193 sys_wll_open (loader_data, filename) 1194 lt_user_data loader_data; 1195 const char *filename; 1196 { 1197 lt_dlhandle cur; 1198 lt_module module = 0; 1199 const char *errormsg = 0; 1200 char *searchname = 0; 1201 char *ext; 1202 char self_name_buf[MAX_PATH]; 1203 1204 if (!filename) 1205 { 1206 /* Get the name of main module */ 1207 *self_name_buf = 0; 1208 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); 1209 filename = ext = self_name_buf; 1210 } 1211 else 1212 { 1213 ext = strrchr (filename, '.'); 1214 } 1215 1216 if (ext) 1217 { 1218 /* FILENAME already has an extension. */ 1219 searchname = lt_estrdup (filename); 1220 } 1221 else 1222 { 1223 /* Append a `.' to stop Windows from adding an 1224 implicit `.dll' extension. */ 1225 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); 1226 if (searchname) 1227 sprintf (searchname, "%s.", filename); 1228 } 1229 if (!searchname) 1230 return 0; 1231 1232 #if __CYGWIN__ 1233 { 1234 char wpath[MAX_PATH]; 1235 cygwin_conv_to_full_win32_path(searchname, wpath); 1236 module = LoadLibrary(wpath); 1237 } 1238 #else 1239 module = LoadLibrary (searchname); 1240 if (!module) { 1241 win32_print_last_error ("LoadLibrary failed: %s\n"); 1242 } 1243 #endif 1244 LT_DLFREE (searchname); 1245 1246 /* libltdl expects this function to fail if it is unable 1247 to physically load the library. Sadly, LoadLibrary 1248 will search the loaded libraries for a match and return 1249 one of them if the path search load fails. 1250 1251 We check whether LoadLibrary is returning a handle to 1252 an already loaded module, and simulate failure if we 1253 find one. */ 1254 LT_DLMUTEX_LOCK (); 1255 cur = handles; 1256 while (cur) 1257 { 1258 if (!cur->module) 1259 { 1260 cur = 0; 1261 break; 1262 } 1263 1264 if (cur->module == module) 1265 { 1266 break; 1267 } 1268 1269 cur = cur->next; 1270 } 1271 LT_DLMUTEX_UNLOCK (); 1272 1273 if (cur || !module) 1274 { 1275 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1276 module = 0; 1277 } 1278 1279 return module; 1280 } 1281 1282 static int 1283 sys_wll_close (loader_data, module) 1284 lt_user_data loader_data; 1285 lt_module module; 1286 { 1287 int errors = 0; 1288 1289 if (FreeLibrary(module) == 0) 1290 { 1291 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1292 ++errors; 1293 } 1294 1295 return errors; 1296 } 1297 1298 static lt_ptr 1299 sys_wll_sym (loader_data, module, symbol) 1300 lt_user_data loader_data; 1301 lt_module module; 1302 const char *symbol; 1303 { 1304 lt_ptr address = GetProcAddress (module, symbol); 1305 1306 if (!address) 1307 { 1308 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1309 } 1310 1311 return address; 1312 } 1313 1314 static struct lt_user_dlloader sys_wll = { 1315 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 1316 }; 1317 1318 #endif /* __WINDOWS__ */ 1319 1320 1321 1322 1323 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */ 1324 1325 1326 #ifdef __BEOS__ 1327 1328 /* dynamic linking for BeOS */ 1329 1330 #include <kernel/image.h> 1331 1332 static lt_module 1333 sys_bedl_open (loader_data, filename) 1334 lt_user_data loader_data; 1335 const char *filename; 1336 { 1337 image_id image = 0; 1338 1339 if (filename) 1340 { 1341 image = load_add_on (filename); 1342 } 1343 else 1344 { 1345 image_info info; 1346 int32 cookie = 0; 1347 if (get_next_image_info (0, &cookie, &info) == B_OK) 1348 image = load_add_on (info.name); 1349 } 1350 1351 if (image <= 0) 1352 { 1353 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1354 image = 0; 1355 } 1356 1357 return (lt_module) image; 1358 } 1359 1360 static int 1361 sys_bedl_close (loader_data, module) 1362 lt_user_data loader_data; 1363 lt_module module; 1364 { 1365 int errors = 0; 1366 1367 if (unload_add_on ((image_id) module) != B_OK) 1368 { 1369 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1370 ++errors; 1371 } 1372 1373 return errors; 1374 } 1375 1376 static lt_ptr 1377 sys_bedl_sym (loader_data, module, symbol) 1378 lt_user_data loader_data; 1379 lt_module module; 1380 const char *symbol; 1381 { 1382 lt_ptr address = 0; 1383 image_id image = (image_id) module; 1384 1385 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) 1386 { 1387 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1388 address = 0; 1389 } 1390 1391 return address; 1392 } 1393 1394 static struct lt_user_dlloader sys_bedl = { 1395 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 1396 }; 1397 1398 #endif /* __BEOS__ */ 1399 1400 1401 1402 1403 /* --- DLD_LINK() INTERFACE LOADER --- */ 1404 1405 1406 #if HAVE_DLD 1407 1408 /* dynamic linking with dld */ 1409 1410 #if HAVE_DLD_H 1411 #include <dld.h> 1412 #endif 1413 1414 static lt_module 1415 sys_dld_open (loader_data, filename) 1416 lt_user_data loader_data; 1417 const char *filename; 1418 { 1419 lt_module module = strdup (filename); 1420 1421 if (dld_link (filename) != 0) 1422 { 1423 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1424 LT_DLFREE (module); 1425 module = 0; 1426 } 1427 1428 return module; 1429 } 1430 1431 static int 1432 sys_dld_close (loader_data, module) 1433 lt_user_data loader_data; 1434 lt_module module; 1435 { 1436 int errors = 0; 1437 1438 if (dld_unlink_by_file ((char*)(module), 1) != 0) 1439 { 1440 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1441 ++errors; 1442 } 1443 else 1444 { 1445 LT_DLFREE (module); 1446 } 1447 1448 return errors; 1449 } 1450 1451 static lt_ptr 1452 sys_dld_sym (loader_data, module, symbol) 1453 lt_user_data loader_data; 1454 lt_module module; 1455 const char *symbol; 1456 { 1457 lt_ptr address = dld_get_func (symbol); 1458 1459 if (!address) 1460 { 1461 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1462 } 1463 1464 return address; 1465 } 1466 1467 static struct lt_user_dlloader sys_dld = { 1468 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 1469 }; 1470 1471 #endif /* HAVE_DLD */ 1472 1473 1474 1475 1476 /* --- DLPREOPEN() INTERFACE LOADER --- */ 1477 1478 1479 /* emulate dynamic linking using preloaded_symbols */ 1480 1481 typedef struct lt_dlsymlists_t 1482 { 1483 struct lt_dlsymlists_t *next; 1484 const lt_dlsymlist *syms; 1485 } lt_dlsymlists_t; 1486 1487 static const lt_dlsymlist *default_preloaded_symbols = 0; 1488 static lt_dlsymlists_t *preloaded_symbols = 0; 1489 1490 static int 1491 presym_init (loader_data) 1492 lt_user_data loader_data; 1493 { 1494 int errors = 0; 1495 1496 LT_DLMUTEX_LOCK (); 1497 1498 preloaded_symbols = 0; 1499 if (default_preloaded_symbols) 1500 { 1501 errors = lt_dlpreload (default_preloaded_symbols); 1502 } 1503 1504 LT_DLMUTEX_UNLOCK (); 1505 1506 return errors; 1507 } 1508 1509 static int 1510 presym_free_symlists () 1511 { 1512 lt_dlsymlists_t *lists; 1513 1514 LT_DLMUTEX_LOCK (); 1515 1516 lists = preloaded_symbols; 1517 while (lists) 1518 { 1519 lt_dlsymlists_t *tmp = lists; 1520 1521 lists = lists->next; 1522 LT_DLFREE (tmp); 1523 } 1524 preloaded_symbols = 0; 1525 1526 LT_DLMUTEX_UNLOCK (); 1527 1528 return 0; 1529 } 1530 1531 static int 1532 presym_exit (loader_data) 1533 lt_user_data loader_data; 1534 { 1535 presym_free_symlists (); 1536 return 0; 1537 } 1538 1539 static int 1540 presym_add_symlist (preloaded) 1541 const lt_dlsymlist *preloaded; 1542 { 1543 lt_dlsymlists_t *tmp; 1544 lt_dlsymlists_t *lists; 1545 int errors = 0; 1546 1547 LT_DLMUTEX_LOCK (); 1548 1549 lists = preloaded_symbols; 1550 while (lists) 1551 { 1552 if (lists->syms == preloaded) 1553 { 1554 goto done; 1555 } 1556 lists = lists->next; 1557 } 1558 1559 tmp = LT_EMALLOC (lt_dlsymlists_t, 1); 1560 if (tmp) 1561 { 1562 memset (tmp, 0, sizeof(lt_dlsymlists_t)); 1563 tmp->syms = preloaded; 1564 tmp->next = preloaded_symbols; 1565 preloaded_symbols = tmp; 1566 } 1567 else 1568 { 1569 ++errors; 1570 } 1571 1572 done: 1573 LT_DLMUTEX_UNLOCK (); 1574 return errors; 1575 } 1576 1577 static lt_module 1578 presym_open (loader_data, filename) 1579 lt_user_data loader_data; 1580 const char *filename; 1581 { 1582 lt_dlsymlists_t *lists; 1583 lt_module module = (lt_module) 0; 1584 1585 LT_DLMUTEX_LOCK (); 1586 lists = preloaded_symbols; 1587 1588 if (!lists) 1589 { 1590 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); 1591 goto done; 1592 } 1593 1594 /* Can't use NULL as the reflective symbol header, as NULL is 1595 used to mark the end of the entire symbol list. Self-dlpreopened 1596 symbols follow this magic number, chosen to be an unlikely 1597 clash with a real module name. */ 1598 if (!filename) 1599 { 1600 filename = "@PROGRAM@"; 1601 } 1602 1603 while (lists) 1604 { 1605 const lt_dlsymlist *syms = lists->syms; 1606 1607 while (syms->name) 1608 { 1609 if (!syms->address && strcmp(syms->name, filename) == 0) 1610 { 1611 module = (lt_module) syms; 1612 goto done; 1613 } 1614 ++syms; 1615 } 1616 1617 lists = lists->next; 1618 } 1619 1620 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 1621 1622 done: 1623 LT_DLMUTEX_UNLOCK (); 1624 return module; 1625 } 1626 1627 static int 1628 presym_close (loader_data, module) 1629 lt_user_data loader_data; 1630 lt_module module; 1631 { 1632 /* Just to silence gcc -Wall */ 1633 module = 0; 1634 return 0; 1635 } 1636 1637 static lt_ptr 1638 presym_sym (loader_data, module, symbol) 1639 lt_user_data loader_data; 1640 lt_module module; 1641 const char *symbol; 1642 { 1643 lt_dlsymlist *syms = (lt_dlsymlist*) module; 1644 1645 ++syms; 1646 while (syms->address) 1647 { 1648 if (strcmp(syms->name, symbol) == 0) 1649 { 1650 return syms->address; 1651 } 1652 1653 ++syms; 1654 } 1655 1656 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1657 1658 return 0; 1659 } 1660 1661 static struct lt_user_dlloader presym = { 1662 0, presym_open, presym_close, presym_sym, presym_exit, 0 1663 }; 1664 1665 1666 1667 1668 1669 /* --- DYNAMIC MODULE LOADING --- */ 1670 1671 1672 /* The type of a function used at each iteration of foreach_dirinpath(). */ 1673 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, 1674 lt_ptr data2)); 1675 1676 static int foreach_dirinpath LT_PARAMS((const char *search_path, 1677 const char *base_name, 1678 foreach_callback_func *func, 1679 lt_ptr data1, lt_ptr data2)); 1680 1681 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, 1682 lt_ptr ignored)); 1683 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, 1684 lt_ptr ignored)); 1685 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, 1686 lt_ptr data2)); 1687 1688 1689 static int canonicalize_path LT_PARAMS((const char *path, 1690 char **pcanonical)); 1691 static int argzize_path LT_PARAMS((const char *path, 1692 char **pargz, 1693 size_t *pargz_len)); 1694 static FILE *find_file LT_PARAMS((const char *search_path, 1695 const char *base_name, 1696 char **pdir)); 1697 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, 1698 const char *base_name, 1699 lt_dlhandle *handle)); 1700 static int find_module LT_PARAMS((lt_dlhandle *handle, 1701 const char *dir, 1702 const char *libdir, 1703 const char *dlname, 1704 const char *old_name, 1705 int installed)); 1706 static int free_vars LT_PARAMS((char *dlname, char *oldname, 1707 char *libdir, char *deplibs)); 1708 static int load_deplibs LT_PARAMS((lt_dlhandle handle, 1709 char *deplibs)); 1710 static int trim LT_PARAMS((char **dest, 1711 const char *str)); 1712 static int try_dlopen LT_PARAMS((lt_dlhandle *handle, 1713 const char *filename)); 1714 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, 1715 const char *filename)); 1716 static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); 1717 static int lt_argz_insert LT_PARAMS((char **pargz, 1718 size_t *pargz_len, 1719 char *before, 1720 const char *entry)); 1721 static int lt_argz_insertinorder LT_PARAMS((char **pargz, 1722 size_t *pargz_len, 1723 const char *entry)); 1724 static int lt_dlpath_insertdir LT_PARAMS((char **ppath, 1725 char *before, 1726 const char *dir)); 1727 1728 static char *user_search_path= 0; 1729 static lt_dlloader *loaders = 0; 1730 static lt_dlhandle handles = 0; 1731 static int initialized = 0; 1732 1733 /* Initialize libltdl. */ 1734 int 1735 lt_dlinit () 1736 { 1737 int errors = 0; 1738 1739 LT_DLMUTEX_LOCK (); 1740 1741 /* Initialize only at first call. */ 1742 if (++initialized == 1) 1743 { 1744 handles = 0; 1745 user_search_path = 0; /* empty search path */ 1746 1747 #if HAVE_LIBDL && !defined(__CYGWIN__) 1748 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); 1749 #endif 1750 #if HAVE_SHL_LOAD 1751 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); 1752 #endif 1753 #ifdef __WINDOWS__ 1754 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); 1755 #endif 1756 #ifdef __BEOS__ 1757 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); 1758 #endif 1759 #if HAVE_DLD 1760 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); 1761 #endif 1762 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); 1763 1764 if (presym_init (presym.dlloader_data)) 1765 { 1766 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); 1767 ++errors; 1768 } 1769 else if (errors != 0) 1770 { 1771 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); 1772 ++errors; 1773 } 1774 } 1775 1776 LT_DLMUTEX_UNLOCK (); 1777 1778 return errors; 1779 } 1780 1781 int 1782 lt_dlpreload (preloaded) 1783 const lt_dlsymlist *preloaded; 1784 { 1785 int errors = 0; 1786 1787 if (preloaded) 1788 { 1789 errors = presym_add_symlist (preloaded); 1790 } 1791 else 1792 { 1793 presym_free_symlists(); 1794 1795 LT_DLMUTEX_LOCK (); 1796 if (default_preloaded_symbols) 1797 { 1798 errors = lt_dlpreload (default_preloaded_symbols); 1799 } 1800 LT_DLMUTEX_UNLOCK (); 1801 } 1802 1803 return errors; 1804 } 1805 1806 int 1807 lt_dlpreload_default (preloaded) 1808 const lt_dlsymlist *preloaded; 1809 { 1810 LT_DLMUTEX_LOCK (); 1811 default_preloaded_symbols = preloaded; 1812 LT_DLMUTEX_UNLOCK (); 1813 return 0; 1814 } 1815 1816 int 1817 lt_dlexit () 1818 { 1819 /* shut down libltdl */ 1820 lt_dlloader *loader; 1821 int errors = 0; 1822 1823 LT_DLMUTEX_LOCK (); 1824 loader = loaders; 1825 1826 if (!initialized) 1827 { 1828 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); 1829 ++errors; 1830 goto done; 1831 } 1832 1833 /* shut down only at last call. */ 1834 if (--initialized == 0) 1835 { 1836 int level; 1837 1838 while (handles && LT_DLIS_RESIDENT (handles)) 1839 { 1840 handles = handles->next; 1841 } 1842 1843 /* close all modules */ 1844 for (level = 1; handles; ++level) 1845 { 1846 lt_dlhandle cur = handles; 1847 int saw_nonresident = 0; 1848 1849 while (cur) 1850 { 1851 lt_dlhandle tmp = cur; 1852 cur = cur->next; 1853 if (!LT_DLIS_RESIDENT (tmp)) 1854 saw_nonresident = 1; 1855 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) 1856 { 1857 if (lt_dlclose (tmp)) 1858 { 1859 ++errors; 1860 } 1861 } 1862 } 1863 /* done if only resident modules are left */ 1864 if (!saw_nonresident) 1865 break; 1866 } 1867 1868 /* close all loaders */ 1869 while (loader) 1870 { 1871 lt_dlloader *next = loader->next; 1872 lt_user_data data = loader->dlloader_data; 1873 if (loader->dlloader_exit && loader->dlloader_exit (data)) 1874 { 1875 ++errors; 1876 } 1877 1878 LT_DLMEM_REASSIGN (loader, next); 1879 } 1880 loaders = 0; 1881 } 1882 1883 done: 1884 LT_DLMUTEX_UNLOCK (); 1885 return errors; 1886 } 1887 1888 // returns number of errors, so 0=success 1889 // returns handle in *handle, if one is found. 1890 static int 1891 tryall_dlopen (handle, filename) 1892 lt_dlhandle *handle; 1893 const char *filename; 1894 { 1895 lt_dlhandle cur; 1896 lt_dlloader *loader; 1897 const char *saved_error; 1898 int errors = 0; 1899 1900 LT_DLMUTEX_GETERROR (saved_error); 1901 LT_DLMUTEX_LOCK (); 1902 1903 cur = handles; 1904 loader = loaders; 1905 1906 /* check whether the module was already opened */ 1907 while (cur) 1908 { 1909 /* try to dlopen the program itself? */ 1910 if (!cur->info.filename && !filename) 1911 { 1912 break; 1913 } 1914 1915 if (cur->info.filename && filename 1916 && strcmp (cur->info.filename, filename) == 0) 1917 { 1918 break; 1919 } 1920 1921 cur = cur->next; 1922 } 1923 1924 if (cur) 1925 { 1926 ++cur->info.ref_count; 1927 *handle = cur; 1928 goto done; 1929 } 1930 1931 cur = *handle; 1932 if (filename) 1933 { 1934 cur->info.filename = lt_estrdup (filename); 1935 if (!cur->info.filename) 1936 { 1937 ++errors; 1938 goto done; 1939 } 1940 } 1941 else 1942 { 1943 cur->info.filename = 0; 1944 } 1945 1946 // Call access() to see if it exists first. If not return FILE_NOT_FOUND 1947 // instead of CANNOT_OPEN. 1948 if (access (cur->info.filename, R_OK) != 0) { 1949 LT_DLFREE (cur->info.filename); 1950 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 1951 ++errors; 1952 goto done; 1953 } 1954 1955 while (loader) 1956 { 1957 lt_user_data data = loader->dlloader_data; 1958 LTDEBUG_PRINTF(("Trying to open '%s' using loader '%s'\n", filename, loader->loader_name)); 1959 cur->module = loader->module_open (data, filename); 1960 1961 if (cur->module != 0) 1962 { 1963 LTDEBUG_PRINTF(("Load '%s' succeeded.\n", filename)); 1964 break; 1965 } 1966 loader = loader->next; 1967 } 1968 1969 if (!loader) 1970 { 1971 LT_DLFREE (cur->info.filename); 1972 ++errors; 1973 goto done; 1974 } 1975 1976 cur->loader = loader; 1977 LT_DLMUTEX_SETERROR (saved_error); 1978 1979 done: 1980 LT_DLMUTEX_UNLOCK (); 1981 1982 return errors; 1983 } 1984 1985 static int 1986 tryall_dlopen_module (handle, prefix, dirname, dlname) 1987 lt_dlhandle *handle; 1988 const char *prefix; 1989 const char *dirname; 1990 const char *dlname; 1991 { 1992 int error = 0; 1993 char *filename = 0; 1994 size_t filename_len = 0; 1995 #ifdef __GNUC__ 1996 #warning dirname could be null 1997 #endif 1998 size_t dirname_len = LT_STRLEN (dirname); 1999 2000 if (dirname == NULL) { 2001 LTDEBUG_PRINTF(("leaving tryall_dlopen_module early because dirname is NULL\n")); 2002 return 1; 2003 } 2004 2005 assert (handle); 2006 assert (dirname); 2007 assert (dlname); 2008 #ifdef LT_DIRSEP_CHAR 2009 /* Only canonicalized names (i.e. with DIRSEP chars already converted) 2010 should make it into this function: */ 2011 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); 2012 #endif 2013 2014 if (dirname[dirname_len -1] == '/') 2015 --dirname_len; 2016 filename_len = dirname_len + 1 + LT_STRLEN (dlname); 2017 2018 /* Allocate memory, and combine DIRNAME and MODULENAME into it. 2019 The PREFIX (if any) is handled below. */ 2020 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); 2021 if (!filename) 2022 return 1; 2023 2024 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); 2025 2026 /* Now that we have combined DIRNAME and MODULENAME, if there is 2027 also a PREFIX to contend with, simply recurse with the arguments 2028 shuffled. Otherwise, attempt to open FILENAME as a module. */ 2029 if (prefix) 2030 { 2031 error += tryall_dlopen_module (handle, 2032 (const char *) 0, prefix, filename); 2033 } 2034 else if (tryall_dlopen (handle, filename) != 0) 2035 { 2036 ++error; 2037 } 2038 2039 LT_DLFREE (filename); 2040 return error; 2041 } 2042 2043 static int 2044 find_module (handle, dir, libdir, dlname, old_name, installed) 2045 lt_dlhandle *handle; 2046 const char *dir; 2047 const char *libdir; 2048 const char *dlname; 2049 const char *old_name; 2050 int installed; 2051 { 2052 /* Try to open the old library first; if it was dlpreopened, 2053 we want the preopened version of it, even if a dlopenable 2054 module is available. */ 2055 if (old_name && tryall_dlopen (handle, old_name) == 0) 2056 { 2057 return 0; 2058 } 2059 2060 /* Try to open the dynamic library. */ 2061 if (dlname) 2062 { 2063 /* try to open the installed module */ 2064 if (installed && libdir) 2065 { 2066 if (tryall_dlopen_module (handle, 2067 (const char *) 0, libdir, dlname) == 0) 2068 return 0; 2069 } 2070 2071 /* try to open the not-installed module */ 2072 if (!installed) 2073 { 2074 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) 2075 return 0; 2076 } 2077 2078 /* maybe it was moved to another directory */ 2079 { 2080 if (tryall_dlopen_module (handle, 2081 (const char *) 0, dir, dlname) == 0) 2082 return 0; 2083 } 2084 } 2085 2086 return 1; 2087 } 2088 2089 2090 static int 2091 canonicalize_path (path, pcanonical) 2092 const char *path; 2093 char **pcanonical; 2094 { 2095 char *canonical = 0; 2096 2097 assert (path && *path); 2098 assert (pcanonical); 2099 2100 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); 2101 if (!canonical) 2102 return 1; 2103 2104 { 2105 size_t dest = 0; 2106 size_t src; 2107 for (src = 0; path[src] != LT_EOS_CHAR; ++src) 2108 { 2109 /* Path separators are not copied to the beginning or end of 2110 the destination, or if another separator would follow 2111 immediately. */ 2112 if (path[src] == LT_PATHSEP_CHAR) 2113 { 2114 if ((dest == 0) 2115 || (path[1+ src] == LT_PATHSEP_CHAR) 2116 || (path[1+ src] == LT_EOS_CHAR)) 2117 continue; 2118 } 2119 2120 /* Anything other than a directory separator is copied verbatim. */ 2121 if ((path[src] != '/') 2122 #ifdef LT_DIRSEP_CHAR 2123 && (path[src] != LT_DIRSEP_CHAR) 2124 #endif 2125 ) 2126 { 2127 canonical[dest++] = path[src]; 2128 } 2129 /* Directory separators are converted and copied only if they are 2130 not at the end of a path -- i.e. before a path separator or 2131 NULL terminator. */ 2132 else if ((path[1+ src] != LT_PATHSEP_CHAR) 2133 && (path[1+ src] != LT_EOS_CHAR) 2134 #ifdef LT_DIRSEP_CHAR 2135 && (path[1+ src] != LT_DIRSEP_CHAR) 2136 #endif 2137 && (path[1+ src] != '/')) 2138 { 2139 canonical[dest++] = '/'; 2140 } 2141 } 2142 2143 /* Add an end-of-string marker at the end. */ 2144 canonical[dest] = LT_EOS_CHAR; 2145 } 2146 2147 /* Assign new value. */ 2148 *pcanonical = canonical; 2149 2150 return 0; 2151 } 2152 2153 static int 2154 argzize_path (path, pargz, pargz_len) 2155 const char *path; 2156 char **pargz; 2157 size_t *pargz_len; 2158 { 2159 error_t error; 2160 2161 assert (path); 2162 assert (pargz); 2163 assert (pargz_len); 2164 2165 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) 2166 { 2167 switch (error) 2168 { 2169 case ENOMEM: 2170 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 2171 break; 2172 default: 2173 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); 2174 break; 2175 } 2176 2177 return 1; 2178 } 2179 2180 return 0; 2181 } 2182 2183 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element 2184 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns 2185 non-zero or all elements are exhausted. If BASE_NAME is non-NULL, 2186 it is appended to each SEARCH_PATH element before FUNC is called. */ 2187 static int 2188 foreach_dirinpath (search_path, base_name, func, data1, data2) 2189 const char *search_path; 2190 const char *base_name; 2191 foreach_callback_func *func; 2192 lt_ptr data1; 2193 lt_ptr data2; 2194 { 2195 int result = 0; 2196 int filenamesize = 0; 2197 int lenbase = LT_STRLEN (base_name); 2198 size_t argz_len = 0; 2199 char * argz = 0; 2200 char * filename = 0; 2201 char * canonical = 0; 2202 2203 LT_DLMUTEX_LOCK (); 2204 2205 if (!search_path || !*search_path) 2206 { 2207 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 2208 goto cleanup; 2209 } 2210 2211 if (canonicalize_path (search_path, &canonical) != 0) 2212 goto cleanup; 2213 2214 if (argzize_path (canonical, &argz, &argz_len) != 0) 2215 goto cleanup; 2216 2217 { 2218 char *dir_name = 0; 2219 while ((dir_name = argz_next (argz, argz_len, dir_name))) 2220 { 2221 int lendir = LT_STRLEN (dir_name); 2222 2223 if (lendir +1 +lenbase >= filenamesize) 2224 { 2225 LT_DLFREE (filename); 2226 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ 2227 filename = LT_EMALLOC (char, filenamesize); 2228 if (!filename) 2229 goto cleanup; 2230 } 2231 2232 strncpy (filename, dir_name, lendir); 2233 if (base_name && *base_name) 2234 { 2235 if (filename[lendir -1] != '/') 2236 filename[lendir++] = '/'; 2237 strcpy (filename +lendir, base_name); 2238 } 2239 2240 if ((result = (*func) (filename, data1, data2))) 2241 { 2242 break; 2243 } 2244 } 2245 } 2246 2247 cleanup: 2248 LT_DLFREE (argz); 2249 LT_DLFREE (canonical); 2250 LT_DLFREE (filename); 2251 2252 LT_DLMUTEX_UNLOCK (); 2253 2254 return result; 2255 } 2256 2257 /* If FILEPATH can be opened, store the name of the directory component 2258 in DATA1, and the opened FILE* structure address in DATA2. Otherwise 2259 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ 2260 static int 2261 find_file_callback (filename, data1, data2) 2262 char *filename; 2263 lt_ptr data1; 2264 lt_ptr data2; 2265 { 2266 char **pdir = (char **) data1; 2267 FILE **pfile = (FILE **) data2; 2268 int is_done = 0; 2269 2270 assert (filename && *filename); 2271 assert (pdir); 2272 assert (pfile); 2273 2274 if ((*pfile = fopen (filename, LT_READTEXT_MODE))) 2275 { 2276 char *dirend = strrchr (filename, '/'); 2277 LTDEBUG_PRINTF(("find_file_callback opening file '%s'...ok\n", filename)); 2278 2279 if (dirend > filename) 2280 *dirend = LT_EOS_CHAR; 2281 2282 LT_DLFREE (*pdir); 2283 *pdir = lt_estrdup (filename); 2284 is_done = (*pdir == 0) ? -1 : 1; 2285 } 2286 else 2287 { 2288 LTDEBUG_PRINTF(("find_file_callback opening file '%s'...failed\n", filename)); 2289 } 2290 2291 return is_done; 2292 } 2293 2294 static FILE * 2295 find_file (search_path, base_name, pdir) 2296 const char *search_path; 2297 const char *base_name; 2298 char **pdir; 2299 { 2300 FILE *file = 0; 2301 2302 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); 2303 2304 return file; 2305 } 2306 2307 static int 2308 find_handle_callback (filename, data, ignored) 2309 char *filename; 2310 lt_ptr data; 2311 lt_ptr ignored; 2312 { 2313 lt_dlhandle *handle = (lt_dlhandle *) data; 2314 int found = (0 == access (filename, R_OK)); 2315 LTDEBUG_PRINTF(("find_handle_callback searching for '%s'...%s\n", filename, found?"found":"not found")); 2316 2317 /* Bail out if file cannot be read... */ 2318 if (!found) 2319 return 0; 2320 2321 /* Try to dlopen the file, but do not continue searching in any 2322 case. */ 2323 if (tryall_dlopen (handle, filename) != 0) 2324 *handle = 0; 2325 2326 return 1; 2327 } 2328 2329 /* If HANDLE was found return it, otherwise return 0. If HANDLE was 2330 found but could not be opened, *HANDLE will be set to 0. */ 2331 static lt_dlhandle * 2332 find_handle (search_path, base_name, handle) 2333 const char *search_path; 2334 const char *base_name; 2335 lt_dlhandle *handle; 2336 { 2337 if (!search_path) 2338 return 0; 2339 2340 if (!foreach_dirinpath (search_path, base_name, find_handle_callback, 2341 handle, 0)) 2342 return 0; 2343 2344 return handle; 2345 } 2346 2347 static int 2348 load_deplibs (handle, deplibs) 2349 lt_dlhandle handle; 2350 char *deplibs; 2351 { 2352 #if LTDL_DLOPEN_DEPLIBS 2353 char *p, *save_search_path = 0; 2354 int depcount = 0; 2355 int i; 2356 char **names = 0; 2357 #endif 2358 int errors = 0; 2359 2360 handle->depcount = 0; 2361 2362 #if LTDL_DLOPEN_DEPLIBS 2363 if (!deplibs) 2364 { 2365 return errors; 2366 } 2367 ++errors; 2368 2369 LT_DLMUTEX_LOCK (); 2370 if (user_search_path) 2371 { 2372 save_search_path = lt_estrdup (user_search_path); 2373 if (!save_search_path) 2374 goto cleanup; 2375 } 2376 2377 /* extract search paths and count deplibs */ 2378 p = deplibs; 2379 while (*p) 2380 { 2381 if (!isspace ((int) *p)) 2382 { 2383 char *end = p+1; 2384 while (*end && !isspace((int) *end)) 2385 { 2386 ++end; 2387 } 2388 2389 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) 2390 { 2391 char save = *end; 2392 *end = 0; /* set a temporary string terminator */ 2393 if (lt_dladdsearchdir(p+2)) 2394 { 2395 goto cleanup; 2396 } 2397 *end = save; 2398 } 2399 else 2400 { 2401 ++depcount; 2402 } 2403 2404 p = end; 2405 } 2406 else 2407 { 2408 ++p; 2409 } 2410 } 2411 2412 /* restore the old search path */ 2413 LT_DLFREE (user_search_path); 2414 user_search_path = save_search_path; 2415 2416 LT_DLMUTEX_UNLOCK (); 2417 2418 if (!depcount) 2419 { 2420 errors = 0; 2421 goto cleanup; 2422 } 2423 2424 names = LT_EMALLOC (char *, depcount * sizeof (char*)); 2425 if (!names) 2426 goto cleanup; 2427 2428 /* now only extract the actual deplibs */ 2429 depcount = 0; 2430 p = deplibs; 2431 while (*p) 2432 { 2433 if (isspace ((int) *p)) 2434 { 2435 ++p; 2436 } 2437 else 2438 { 2439 char *end = p+1; 2440 while (*end && !isspace ((int) *end)) 2441 { 2442 ++end; 2443 } 2444 2445 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) 2446 { 2447 char *name; 2448 char save = *end; 2449 *end = 0; /* set a temporary string terminator */ 2450 if (strncmp(p, "-l", 2) == 0) 2451 { 2452 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); 2453 name = LT_EMALLOC (char, 1+ name_len); 2454 if (name) 2455 sprintf (name, "lib%s", p+2); 2456 } 2457 else 2458 name = lt_estrdup(p); 2459 2460 if (!name) 2461 goto cleanup_names; 2462 2463 names[depcount++] = name; 2464 *end = save; 2465 } 2466 p = end; 2467 } 2468 } 2469 2470 /* load the deplibs (in reverse order) 2471 At this stage, don't worry if the deplibs do not load correctly, 2472 they may already be statically linked into the loading application 2473 for instance. There will be a more enlightening error message 2474 later on if the loaded module cannot resolve all of its symbols. */ 2475 if (depcount) 2476 { 2477 int j = 0; 2478 2479 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); 2480 if (!handle->deplibs) 2481 goto cleanup; 2482 2483 for (i = 0; i < depcount; ++i) 2484 { 2485 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); 2486 if (handle->deplibs[j]) 2487 { 2488 ++j; 2489 } 2490 } 2491 2492 handle->depcount = j; /* Number of successfully loaded deplibs */ 2493 errors = 0; 2494 } 2495 2496 cleanup_names: 2497 for (i = 0; i < depcount; ++i) 2498 { 2499 LT_DLFREE (names[i]); 2500 } 2501 2502 cleanup: 2503 LT_DLFREE (names); 2504 #endif 2505 2506 return errors; 2507 } 2508 2509 static int 2510 unload_deplibs (handle) 2511 lt_dlhandle handle; 2512 { 2513 int i; 2514 int errors = 0; 2515 2516 if (handle->depcount) 2517 { 2518 for (i = 0; i < handle->depcount; ++i) 2519 { 2520 if (!LT_DLIS_RESIDENT (handle->deplibs[i])) 2521 { 2522 errors += lt_dlclose (handle->deplibs[i]); 2523 } 2524 } 2525 } 2526 2527 return errors; 2528 } 2529 2530 static int 2531 trim (dest, str) 2532 char **dest; 2533 const char *str; 2534 { 2535 /* remove the leading and trailing "'" from str 2536 and store the result in dest */ 2537 const char *end = strrchr (str, '\''); 2538 int len = LT_STRLEN (str); 2539 char *tmp; 2540 2541 LT_DLFREE (*dest); 2542 2543 if (len > 3 && str[0] == '\'') 2544 { 2545 tmp = LT_EMALLOC (char, end - str); 2546 if (!tmp) 2547 return 1; 2548 2549 strncpy(tmp, &str[1], (end - str) - 1); 2550 tmp[len-3] = LT_EOS_CHAR; 2551 *dest = tmp; 2552 } 2553 else 2554 { 2555 *dest = 0; 2556 } 2557 2558 return 0; 2559 } 2560 2561 static int 2562 free_vars (dlname, oldname, libdir, deplibs) 2563 char *dlname; 2564 char *oldname; 2565 char *libdir; 2566 char *deplibs; 2567 { 2568 LT_DLFREE (dlname); 2569 LT_DLFREE (oldname); 2570 LT_DLFREE (libdir); 2571 LT_DLFREE (deplibs); 2572 2573 return 0; 2574 } 2575 2576 // returns number of errors, so 0=success. 2577 // phandle is a pointer to an lt_dlhandle, which must initially be NULL. 2578 // On success (return value=0), *phandle is changed to point to the new 2579 // lt_dlhandle. 2580 int 2581 try_dlopen (phandle, filename) 2582 lt_dlhandle *phandle; 2583 const char *filename; 2584 { 2585 const char * ext = 0; 2586 const char * saved_error = 0; 2587 char * canonical = 0; 2588 char * base_name = 0; 2589 char * dir = 0; 2590 char * name = 0; 2591 int errors = 0; 2592 lt_dlhandle newhandle; 2593 2594 assert (phandle); 2595 assert (*phandle == 0); 2596 2597 LT_DLMUTEX_GETERROR (saved_error); 2598 2599 /* dlopen self? */ 2600 if (!filename) 2601 { 2602 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 2603 if (*phandle == 0) 2604 return 1; 2605 2606 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); 2607 newhandle = *phandle; 2608 2609 /* lt_dlclose()ing yourself is very bad! Disallow it. */ 2610 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); 2611 2612 if (tryall_dlopen (&newhandle, 0) != 0) 2613 { 2614 LT_DLFREE (*phandle); // this sets *phandle=NULL 2615 return 1; 2616 } 2617 2618 goto register_handle; 2619 } 2620 2621 assert (filename && *filename); 2622 2623 /* Doing this immediately allows internal functions to safely 2624 assume only canonicalized paths are passed. */ 2625 if (canonicalize_path (filename, &canonical) != 0) 2626 { 2627 ++errors; 2628 goto cleanup; 2629 } 2630 2631 /* If the canonical module name is a path (relative or absolute) 2632 then split it into a directory part and a name part. */ 2633 base_name = strrchr (canonical, '/'); 2634 if (base_name) 2635 { 2636 size_t dirlen = (1+ base_name) - canonical; 2637 2638 dir = LT_EMALLOC (char, 1+ dirlen); 2639 if (!dir) 2640 { 2641 ++errors; 2642 goto cleanup; 2643 } 2644 2645 strncpy (dir, canonical, dirlen); 2646 dir[dirlen] = LT_EOS_CHAR; 2647 2648 ++base_name; 2649 LTDEBUG_PRINTF(("in base_name not NULL section. dir='%s', base_name='%s', canonical='%s'\n", dir, base_name, canonical)); 2650 } 2651 else { 2652 LT_DLMEM_REASSIGN (base_name, canonical); 2653 LTDEBUG_PRINTF(("in base_name=NULL section. dir=NULL, base_name='%s', canonical='%s'\n", base_name, canonical)); 2654 } 2655 2656 assert (base_name && *base_name); 2657 2658 /* Check whether we are opening a libtool module (.la extension). */ 2659 ext = strrchr (base_name, '.'); 2660 if (ext && strcmp (ext, archive_ext) == 0) 2661 { 2662 /* this seems to be a libtool module */ 2663 FILE * file = 0; 2664 char * dlname = 0; 2665 char * old_name = 0; 2666 char * libdir = 0; 2667 char * deplibs = 0; 2668 char * line = 0; 2669 size_t line_len; 2670 int i; 2671 2672 /* if we can't find the installed flag, it is probably an 2673 installed libtool archive, produced with an old version 2674 of libtool */ 2675 int installed = 1; 2676 2677 /* extract the module name from the file name */ 2678 name = LT_EMALLOC (char, ext - base_name + 1); 2679 if (!name) 2680 { 2681 ++errors; 2682 goto cleanup; 2683 } 2684 2685 /* canonicalize the module name */ 2686 for (i = 0; i < ext - base_name; ++i) 2687 { 2688 if (isalnum ((int)(base_name[i]))) 2689 { 2690 name[i] = base_name[i]; 2691 } 2692 else 2693 { 2694 name[i] = '_'; 2695 } 2696 } 2697 name[ext - base_name] = LT_EOS_CHAR; 2698 2699 /* Now try to open the .la file. If there is no directory name 2700 component, try to find it first in user_search_path and then other 2701 prescribed paths. Otherwise (or in any case if the module was not 2702 yet found) try opening just the module name as passed. */ 2703 if (!dir) 2704 { 2705 const char *search_path; 2706 2707 LT_DLMUTEX_LOCK (); 2708 search_path = user_search_path; 2709 if (search_path) 2710 file = find_file (user_search_path, base_name, &dir); 2711 LT_DLMUTEX_UNLOCK (); 2712 2713 if (!file) 2714 { 2715 search_path = getenv (LTDL_SEARCHPATH_VAR); 2716 if (search_path) 2717 file = find_file (search_path, base_name, &dir); 2718 } 2719 2720 #ifdef LTDL_SHLIBPATH_VAR 2721 if (!file) 2722 { 2723 search_path = getenv (LTDL_SHLIBPATH_VAR); 2724 if (search_path) 2725 file = find_file (search_path, base_name, &dir); 2726 } 2727 #endif 2728 #ifdef LTDL_SYSSEARCHPATH 2729 if (!file && sys_search_path) 2730 { 2731 file = find_file (sys_search_path, base_name, &dir); 2732 } 2733 #endif 2734 } 2735 if (!file) 2736 { 2737 LTDEBUG_PRINTF(("try_dlopen opening file '%s'\n", filename)); 2738 file = fopen (filename, LT_READTEXT_MODE); 2739 #ifdef __GNUC__ 2740 #warning dir is still NULL 2741 #endif 2742 } 2743 2744 /* If we didn't find the file by now, it really isn't there. Set 2745 the status flag, and bail out. */ 2746 if (!file) 2747 { 2748 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 2749 ++errors; 2750 goto cleanup; 2751 } 2752 2753 line_len = LT_FILENAME_MAX; 2754 line = LT_EMALLOC (char, line_len); 2755 if (!line) 2756 { 2757 fclose (file); 2758 ++errors; 2759 goto cleanup; 2760 } 2761 2762 /* read the .la file */ 2763 while (!feof (file)) 2764 { 2765 if (!fgets (line, line_len, file)) 2766 { 2767 break; 2768 } 2769 2770 /* Handle the case where we occasionally need to read a line 2771 that is longer than the initial buffer size. */ 2772 while (line[LT_STRLEN(line) -1] != '\n') 2773 { 2774 line = LT_DLREALLOC (char, line, line_len *2); 2775 if (!fgets (&line[line_len -1], line_len +1, file)) 2776 { 2777 break; 2778 } 2779 line_len *= 2; 2780 } 2781 2782 if (line[0] == '\n' || line[0] == '#') 2783 { 2784 continue; 2785 } 2786 2787 #undef STR_DLNAME 2788 #define STR_DLNAME "dlname=" 2789 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) 2790 { 2791 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); 2792 } 2793 2794 #undef STR_OLD_LIBRARY 2795 #define STR_OLD_LIBRARY "old_library=" 2796 else if (strncmp (line, STR_OLD_LIBRARY, 2797 sizeof (STR_OLD_LIBRARY) - 1) == 0) 2798 { 2799 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); 2800 } 2801 #undef STR_LIBDIR 2802 #define STR_LIBDIR "libdir=" 2803 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) 2804 { 2805 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); 2806 } 2807 2808 #undef STR_DL_DEPLIBS 2809 #define STR_DL_DEPLIBS "dependency_libs=" 2810 else if (strncmp (line, STR_DL_DEPLIBS, 2811 sizeof (STR_DL_DEPLIBS) - 1) == 0) 2812 { 2813 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); 2814 } 2815 else if (strcmp (line, "installed=yes\n") == 0) 2816 { 2817 installed = 1; 2818 } 2819 else if (strcmp (line, "installed=no\n") == 0) 2820 { 2821 installed = 0; 2822 } 2823 2824 #undef STR_LIBRARY_NAMES 2825 #define STR_LIBRARY_NAMES "library_names=" 2826 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, 2827 sizeof (STR_LIBRARY_NAMES) - 1) == 0) 2828 { 2829 char *last_libname; 2830 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); 2831 if (!errors 2832 && dlname 2833 && (last_libname = strrchr (dlname, ' ')) != 0) 2834 { 2835 last_libname = lt_estrdup (last_libname + 1); 2836 if (!last_libname) 2837 { 2838 ++errors; 2839 goto cleanup; 2840 } 2841 LT_DLMEM_REASSIGN (dlname, last_libname); 2842 } 2843 } 2844 2845 if (errors) 2846 break; 2847 } 2848 2849 fclose (file); 2850 LT_DLFREE (line); 2851 2852 /* allocate the handle */ 2853 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 2854 if (*phandle == 0) 2855 ++errors; 2856 2857 if (errors) 2858 { 2859 free_vars (dlname, old_name, libdir, deplibs); 2860 LT_DLFREE (*phandle); 2861 goto cleanup; 2862 } 2863 2864 assert (*phandle); 2865 2866 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); 2867 if (load_deplibs (*phandle, deplibs) == 0) 2868 { 2869 newhandle = *phandle; 2870 /* find_module may replace newhandle */ 2871 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) 2872 { 2873 unload_deplibs (*phandle); 2874 ++errors; 2875 } 2876 } 2877 else 2878 { 2879 ++errors; 2880 } 2881 2882 free_vars (dlname, old_name, libdir, deplibs); 2883 if (errors) 2884 { 2885 LT_DLFREE (*phandle); // sets *phandle=NULL 2886 goto cleanup; 2887 } 2888 2889 if (*phandle != newhandle) 2890 { 2891 unload_deplibs (*phandle); 2892 } 2893 } 2894 else 2895 { 2896 /* not a libtool module */ 2897 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 2898 if (*phandle == 0) 2899 { 2900 ++errors; 2901 goto cleanup; 2902 } 2903 2904 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); 2905 newhandle = *phandle; 2906 2907 /* If the module has no directory name component, try to find it 2908 first in user_search_path and then other prescribed paths. 2909 Otherwise (or in any case if the module was not yet found) try 2910 opening just the module name as passed. */ 2911 if ((dir || (!find_handle (user_search_path, base_name, &newhandle) 2912 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, 2913 &newhandle) 2914 #ifdef LTDL_SHLIBPATH_VAR 2915 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, 2916 &newhandle) 2917 #endif 2918 #ifdef LTDL_SYSSEARCHPATH 2919 && !find_handle (sys_search_path, base_name, &newhandle) 2920 #endif 2921 ))) 2922 { 2923 // Directory component was specified, or all find_handle() calls 2924 // failed to find the lib. This is our last try. 2925 errors = tryall_dlopen (&newhandle, filename); 2926 } 2927 2928 if (!newhandle || errors>0) 2929 { 2930 LT_DLFREE (*phandle); 2931 ++errors; 2932 goto cleanup; 2933 } 2934 } 2935 2936 register_handle: 2937 LT_DLMEM_REASSIGN (*phandle, newhandle); 2938 2939 if ((*phandle)->info.ref_count == 0) 2940 { 2941 (*phandle)->info.ref_count = 1; 2942 LT_DLMEM_REASSIGN ((*phandle)->info.name, name); 2943 2944 LT_DLMUTEX_LOCK (); 2945 (*phandle)->next = handles; 2946 handles = *phandle; 2947 LT_DLMUTEX_UNLOCK (); 2948 } 2949 2950 LT_DLMUTEX_SETERROR (saved_error); 2951 2952 cleanup: 2953 LT_DLFREE (dir); 2954 LT_DLFREE (name); 2955 LT_DLFREE (canonical); 2956 2957 return errors; 2958 } 2959 2960 lt_dlhandle 2961 lt_dlopen (filename) 2962 const char *filename; 2963 { 2964 lt_dlhandle handle = 0; 2965 2966 /* Just incase we missed a code path in try_dlopen() that reports 2967 an error, but forgets to reset handle... */ 2968 if (try_dlopen (&handle, filename) != 0) 2969 return 0; 2970 2971 // If we're going to return a handle, be sure that has its loader 2972 // field filled in. This is in response to some bugs in which dlopen() 2973 // would return valid-looking handle with NULL loader, causing crashes 2974 // later. 2975 if (handle) assert (handle->loader != NULL); 2976 2977 return handle; 2978 } 2979 2980 /* If the last error messge store was `FILE_NOT_FOUND', then return 2981 non-zero. */ 2982 int 2983 file_not_found () 2984 { 2985 const char *error = 0; 2986 2987 LT_DLMUTEX_GETERROR (error); 2988 if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) 2989 return 1; 2990 2991 return 0; 2992 } 2993 2994 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to 2995 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, 2996 and if a file is still not found try again with SHLIB_EXT appended 2997 instead. */ 2998 lt_dlhandle 2999 lt_dlopenext (filename) 3000 const char *filename; 3001 { 3002 lt_dlhandle handle = 0; 3003 char * tmp = 0; 3004 char * ext = 0; 3005 int len; 3006 int errors = 0; 3007 int file_found = 1; /* until proven otherwise */ 3008 3009 if (!filename) 3010 { 3011 return lt_dlopen (filename); 3012 } 3013 3014 assert (filename); 3015 3016 len = LT_STRLEN (filename); 3017 ext = strrchr (filename, '.'); 3018 3019 /* If FILENAME already bears a suitable extension, there is no need 3020 to try appending additional extensions. */ 3021 if (ext && ((strcmp (ext, archive_ext) == 0) 3022 #ifdef LTDL_SHLIB_EXT 3023 || (strcmp (ext, shlib_ext) == 0) 3024 #endif 3025 )) 3026 { 3027 return lt_dlopen (filename); 3028 } 3029 3030 /* First try appending ARCHIVE_EXT. */ 3031 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1); 3032 if (!tmp) 3033 return 0; 3034 3035 strcpy (tmp, filename); 3036 strcat (tmp, archive_ext); 3037 errors = try_dlopen (&handle, tmp); 3038 3039 /* If we found FILENAME, stop searching -- whether we were able to 3040 load the file as a module or not. If the file exists but loading 3041 failed, it is better to return an error message here than to 3042 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not 3043 in the module search path. */ 3044 if (handle || ((errors > 0) && !file_not_found ())) 3045 { 3046 LT_DLFREE (tmp); 3047 3048 // If we're going to return a handle, be sure that has its loader 3049 // field filled in. This is in response to some bugs in which dlopen() 3050 // would return valid-looking handle with NULL loader, causing crashes 3051 // later. 3052 if (handle) assert (handle->loader != NULL); 3053 3054 return handle; 3055 } 3056 3057 #ifdef LTDL_SHLIB_EXT 3058 /* Try appending SHLIB_EXT. */ 3059 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext)) 3060 { 3061 LT_DLFREE (tmp); 3062 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); 3063 if (!tmp) 3064 return 0; 3065 3066 strcpy (tmp, filename); 3067 } 3068 else 3069 { 3070 tmp[len] = LT_EOS_CHAR; 3071 } 3072 3073 strcat(tmp, shlib_ext); 3074 errors = try_dlopen (&handle, tmp); 3075 3076 /* As before, if the file was found but loading failed, return now 3077 with the current error message. */ 3078 if (handle || ((errors > 0) && !file_not_found ())) 3079 { 3080 LT_DLFREE (tmp); 3081 // If we're going to return a handle, be sure that has its loader 3082 // field filled in. This is in response to some bugs in which dlopen() 3083 // would return valid-looking handle with NULL loader, causing crashes 3084 // later. 3085 if (handle) assert (handle->loader != NULL); 3086 return handle; 3087 } 3088 #endif 3089 3090 /* Still here? Then we really did fail to locate any of the file 3091 names we tried. */ 3092 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 3093 LT_DLFREE (tmp); 3094 return 0; 3095 } 3096 3097 3098 int 3099 lt_argz_insert (pargz, pargz_len, before, entry) 3100 char **pargz; 3101 size_t *pargz_len; 3102 char *before; 3103 const char *entry; 3104 { 3105 error_t error; 3106 3107 if ((error = argz_insert (pargz, pargz_len, before, entry))) 3108 { 3109 switch (error) 3110 { 3111 case ENOMEM: 3112 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 3113 break; 3114 default: 3115 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); 3116 break; 3117 } 3118 return 1; 3119 } 3120 3121 return 0; 3122 } 3123 3124 int 3125 lt_argz_insertinorder (pargz, pargz_len, entry) 3126 char **pargz; 3127 size_t *pargz_len; 3128 const char *entry; 3129 { 3130 char *before = 0; 3131 3132 assert (pargz); 3133 assert (pargz_len); 3134 assert (entry && *entry); 3135 3136 if (*pargz) 3137 while ((before = argz_next (*pargz, *pargz_len, before))) 3138 { 3139 int cmp = strcmp (entry, before); 3140 3141 if (cmp < 0) break; 3142 if (cmp == 0) return 0; /* No duplicates! */ 3143 } 3144 3145 return lt_argz_insert (pargz, pargz_len, before, entry); 3146 } 3147 3148 int 3149 lt_argz_insertdir (pargz, pargz_len, dirnam, dp) 3150 char **pargz; 3151 size_t *pargz_len; 3152 const char *dirnam; 3153 struct dirent *dp; 3154 { 3155 char *buf = 0; 3156 size_t buf_len = 0; 3157 char *end = 0; 3158 size_t end_offset = 0; 3159 size_t dir_len = 0; 3160 int errors = 0; 3161 3162 assert (pargz); 3163 assert (pargz_len); 3164 assert (dp); 3165 3166 dir_len = LT_STRLEN (dirnam); 3167 end = dp->d_name + LT_D_NAMLEN(dp); 3168 3169 /* Ignore version numbers. */ 3170 { 3171 char *p; 3172 for (p = end; p -1 > dp->d_name; --p) 3173 if (strchr (".0123456789", p[-1]) == 0) 3174 break; 3175 3176 if (*p == '.') 3177 end = p; 3178 } 3179 3180 /* Ignore filename extension. */ 3181 { 3182 char *p; 3183 for (p = end -1; p > dp->d_name; --p) 3184 if (*p == '.') 3185 { 3186 end = p; 3187 break; 3188 } 3189 } 3190 3191 /* Prepend the directory name. */ 3192 end_offset = end - dp->d_name; 3193 buf_len = dir_len + 1+ end_offset; 3194 buf = LT_EMALLOC (char, 1+ buf_len); 3195 if (!buf) 3196 return ++errors; 3197 3198 assert (buf); 3199 3200 strcpy (buf, dirnam); 3201 strcat (buf, "/"); 3202 strncat (buf, dp->d_name, end_offset); 3203 buf[buf_len] = LT_EOS_CHAR; 3204 3205 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ 3206 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) 3207 ++errors; 3208 3209 LT_DLFREE (buf); 3210 3211 return errors; 3212 } 3213 3214 int 3215 list_files_by_dir (dirnam, pargz, pargz_len) 3216 const char *dirnam; 3217 char **pargz; 3218 size_t *pargz_len; 3219 { 3220 DIR *dirp = 0; 3221 int errors = 0; 3222 3223 assert (dirnam && *dirnam); 3224 assert (pargz); 3225 assert (pargz_len); 3226 assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); 3227 3228 dirp = opendir (dirnam); 3229 if (dirp) 3230 { 3231 struct dirent *dp = 0; 3232 3233 while ((dp = readdir (dirp))) 3234 if (dp->d_name[0] != '.') 3235 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) 3236 { 3237 ++errors; 3238 break; 3239 } 3240 3241 closedir (dirp); 3242 } 3243 else 3244 ++errors; 3245 3246 return errors; 3247 } 3248 3249 3250 /* If there are any files in DIRNAME, call the function passed in 3251 DATA1 (with the name of each file and DATA2 as arguments). */ 3252 static int 3253 foreachfile_callback (dirname, data1, data2) 3254 char *dirname; 3255 lt_ptr data1; 3256 lt_ptr data2; 3257 { 3258 int (*func) LT_PARAMS((const char *filename, lt_ptr data)) 3259 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; 3260 3261 int is_done = 0; 3262 char *argz = 0; 3263 size_t argz_len = 0; 3264 3265 if (list_files_by_dir (dirname, &argz, &argz_len) != 0) 3266 goto cleanup; 3267 if (!argz) 3268 goto cleanup; 3269 3270 { 3271 char *filename = 0; 3272 while ((filename = argz_next (argz, argz_len, filename))) 3273 if ((is_done = (*func) (filename, data2))) 3274 break; 3275 } 3276 3277 cleanup: 3278 LT_DLFREE (argz); 3279 3280 return is_done; 3281 } 3282 3283 3284 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along 3285 with DATA. The filenames passed to FUNC would be suitable for 3286 passing to lt_dlopenext. The extensions are stripped so that 3287 individual modules do not generate several entries (e.g. libfoo.la, 3288 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, 3289 then the same directories that lt_dlopen would search are examined. */ 3290 int 3291 lt_dlforeachfile (search_path, func, data) 3292 const char *search_path; 3293 int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); 3294 lt_ptr data; 3295 { 3296 int is_done = 0; 3297 3298 if (search_path) 3299 { 3300 /* If a specific path was passed, search only the directories 3301 listed in it. */ 3302 is_done = foreach_dirinpath (search_path, 0, 3303 foreachfile_callback, func, data); 3304 } 3305 else 3306 { 3307 /* Otherwise search the default paths. */ 3308 is_done = foreach_dirinpath (user_search_path, 0, 3309 foreachfile_callback, func, data); 3310 if (!is_done) 3311 { 3312 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, 3313 foreachfile_callback, func, data); 3314 } 3315 3316 #ifdef LTDL_SHLIBPATH_VAR 3317 if (!is_done) 3318 { 3319 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, 3320 foreachfile_callback, func, data); 3321 } 3322 #endif 3323 #ifdef LTDL_SYSSEARCHPATH 3324 if (!is_done) 3325 { 3326 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, 3327 foreachfile_callback, func, data); 3328 } 3329 #endif 3330 } 3331 3332 return is_done; 3333 } 3334 3335 int 3336 lt_dlclose (handle) 3337 lt_dlhandle handle; 3338 { 3339 lt_dlhandle cur, last; 3340 int errors = 0; 3341 3342 LT_DLMUTEX_LOCK (); 3343 3344 /* check whether the handle is valid */ 3345 last = cur = handles; 3346 while (cur && handle != cur) 3347 { 3348 last = cur; 3349 cur = cur->next; 3350 } 3351 3352 if (!cur) 3353 { 3354 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 3355 ++errors; 3356 goto done; 3357 } 3358 3359 handle->info.ref_count--; 3360 3361 /* Note that even with resident modules, we must track the ref_count 3362 correctly incase the user decides to reset the residency flag 3363 later (even though the API makes no provision for that at the 3364 moment). */ 3365 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) 3366 { 3367 lt_user_data data = handle->loader->dlloader_data; 3368 3369 if (handle != handles) 3370 { 3371 last->next = handle->next; 3372 } 3373 else 3374 { 3375 handles = handle->next; 3376 } 3377 3378 errors += handle->loader->module_close (data, handle->module); 3379 errors += unload_deplibs(handle); 3380 3381 LT_DLFREE (handle->info.filename); 3382 LT_DLFREE (handle->info.name); 3383 LT_DLFREE (handle); 3384 3385 goto done; 3386 } 3387 3388 if (LT_DLIS_RESIDENT (handle)) 3389 { 3390 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); 3391 ++errors; 3392 } 3393 3394 done: 3395 LT_DLMUTEX_UNLOCK (); 3396 3397 return errors; 3398 } 3399 3400 lt_ptr 3401 lt_dlsym (handle, symbol) 3402 lt_dlhandle handle; 3403 const char *symbol; 3404 { 3405 int lensym; 3406 char lsym[LT_SYMBOL_LENGTH]; 3407 char *sym; 3408 lt_ptr address; 3409 lt_user_data data; 3410 3411 if (!handle) 3412 { 3413 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 3414 return 0; 3415 } 3416 3417 if (!symbol) 3418 { 3419 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 3420 return 0; 3421 } 3422 3423 // Due to bugs in lt_dlopen*, some handles were being returned that have a 3424 // NULL loader field. Check for this. 3425 assert (handle->loader); 3426 3427 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) 3428 + LT_STRLEN (handle->info.name); 3429 3430 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) 3431 { 3432 sym = lsym; 3433 } 3434 else 3435 { 3436 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); 3437 if (!sym) 3438 { 3439 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); 3440 return 0; 3441 } 3442 } 3443 3444 data = handle->loader->dlloader_data; 3445 if (handle->info.name) 3446 { 3447 const char *saved_error; 3448 3449 LT_DLMUTEX_GETERROR (saved_error); 3450 3451 /* this is a libtool module */ 3452 if (handle->loader->sym_prefix) 3453 { 3454 strcpy(sym, handle->loader->sym_prefix); 3455 strcat(sym, handle->info.name); 3456 } 3457 else 3458 { 3459 strcpy(sym, handle->info.name); 3460 } 3461 3462 strcat(sym, "_LTX_"); 3463 strcat(sym, symbol); 3464 3465 /* try "modulename_LTX_symbol" */ 3466 LTDEBUG_PRINTF(("dlsym looking for '%s'\n", sym)); 3467 address = handle->loader->find_sym (data, handle->module, sym); 3468 if (address) 3469 { 3470 if (sym != lsym) 3471 { 3472 LT_DLFREE (sym); 3473 } 3474 return address; 3475 } 3476 LT_DLMUTEX_SETERROR (saved_error); 3477 } 3478 3479 /* otherwise try "symbol" */ 3480 if (handle->loader->sym_prefix) 3481 { 3482 strcpy(sym, handle->loader->sym_prefix); 3483 strcat(sym, symbol); 3484 } 3485 else 3486 { 3487 strcpy(sym, symbol); 3488 } 3489 3490 LTDEBUG_PRINTF(("dlsym looking for '%s'\n", sym)); 3491 address = handle->loader->find_sym (data, handle->module, sym); 3492 if (sym != lsym) 3493 { 3494 LT_DLFREE (sym); 3495 } 3496 3497 return address; 3498 } 3499 3500 const char * 3501 lt_dlerror () 3502 { 3503 const char *error; 3504 3505 LT_DLMUTEX_GETERROR (error); 3506 LT_DLMUTEX_SETERROR (0); 3507 3508 return error ? error : LT_DLSTRERROR (UNKNOWN); 3509 } 3510 3511 int 3512 lt_dlpath_insertdir (ppath, before, dir) 3513 char **ppath; 3514 char *before; 3515 const char *dir; 3516 { 3517 int errors = 0; 3518 char *canonical = 0; 3519 char *argz = 0; 3520 size_t argz_len = 0; 3521 3522 assert (ppath); 3523 assert (dir && *dir); 3524 3525 if (canonicalize_path (dir, &canonical) != 0) 3526 { 3527 ++errors; 3528 goto cleanup; 3529 } 3530 3531 assert (canonical && *canonical); 3532 3533 /* If *PPATH is empty, set it to DIR. */ 3534 if (*ppath == 0) 3535 { 3536 assert (!before); /* BEFORE cannot be set without PPATH. */ 3537 assert (dir); /* Without DIR, don't call this function! */ 3538 3539 *ppath = lt_estrdup (dir); 3540 if (*ppath == 0) 3541 ++errors; 3542 3543 return errors; 3544 } 3545 3546 assert (ppath && *ppath); 3547 3548 if (argzize_path (*ppath, &argz, &argz_len) != 0) 3549 { 3550 ++errors; 3551 goto cleanup; 3552 } 3553 3554 /* Convert BEFORE into an equivalent offset into ARGZ. This only works 3555 if *PPATH is already canonicalized, and hence does not change length 3556 with respect to ARGZ. We canonicalize each entry as it is added to 3557 the search path, and don't call this function with (uncanonicalized) 3558 user paths, so this is a fair assumption. */ 3559 if (before) 3560 { 3561 assert (*ppath <= before); 3562 assert (before - *ppath <= strlen (*ppath)); 3563 3564 before = before - *ppath + argz; 3565 } 3566 3567 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) 3568 { 3569 ++errors; 3570 goto cleanup; 3571 } 3572 3573 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); 3574 LT_DLMEM_REASSIGN (*ppath, argz); 3575 3576 cleanup: 3577 LT_DLFREE (canonical); 3578 LT_DLFREE (argz); 3579 3580 return errors; 3581 } 3582 3583 int 3584 lt_dladdsearchdir (search_dir) 3585 const char *search_dir; 3586 { 3587 int errors = 0; 3588 3589 if (search_dir && *search_dir) 3590 { 3591 LT_DLMUTEX_LOCK (); 3592 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) 3593 ++errors; 3594 LT_DLMUTEX_UNLOCK (); 3595 } 3596 3597 return errors; 3598 } 3599 3600 int 3601 lt_dlinsertsearchdir (before, search_dir) 3602 const char *before; 3603 const char *search_dir; 3604 { 3605 int errors = 0; 3606 3607 if (before) 3608 { 3609 LT_DLMUTEX_LOCK (); 3610 if ((before < user_search_path) 3611 || (before >= user_search_path + LT_STRLEN (user_search_path))) 3612 { 3613 LT_DLMUTEX_UNLOCK (); 3614 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); 3615 return 1; 3616 } 3617 LT_DLMUTEX_UNLOCK (); 3618 } 3619 3620 if (search_dir && *search_dir) 3621 { 3622 LT_DLMUTEX_LOCK (); 3623 if (lt_dlpath_insertdir (&user_search_path, 3624 (char *) before, search_dir) != 0) 3625 { 3626 ++errors; 3627 } 3628 LT_DLMUTEX_UNLOCK (); 3629 } 3630 3631 return errors; 3632 } 3633 3634 int 3635 lt_dlsetsearchpath (search_path) 3636 const char *search_path; 3637 { 3638 int errors = 0; 3639 3640 LT_DLMUTEX_LOCK (); 3641 LT_DLFREE (user_search_path); 3642 LT_DLMUTEX_UNLOCK (); 3643 3644 if (!search_path || !LT_STRLEN (search_path)) 3645 { 3646 return errors; 3647 } 3648 3649 LT_DLMUTEX_LOCK (); 3650 if (canonicalize_path (search_path, &user_search_path) != 0) 3651 ++errors; 3652 LT_DLMUTEX_UNLOCK (); 3653 3654 return errors; 3655 } 3656 3657 const char * 3658 lt_dlgetsearchpath () 3659 { 3660 const char *saved_path; 3661 3662 LT_DLMUTEX_LOCK (); 3663 saved_path = user_search_path; 3664 LT_DLMUTEX_UNLOCK (); 3665 3666 return saved_path; 3667 } 3668 3669 int 3670 lt_dlmakeresident (handle) 3671 lt_dlhandle handle; 3672 { 3673 int errors = 0; 3674 3675 if (!handle) 3676 { 3677 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 3678 ++errors; 3679 } 3680 else 3681 { 3682 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); 3683 } 3684 3685 return errors; 3686 } 3687 3688 int 3689 lt_dlisresident (handle) 3690 lt_dlhandle handle; 3691 { 3692 if (!handle) 3693 { 3694 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 3695 return -1; 3696 } 3697 3698 return LT_DLIS_RESIDENT (handle); 3699 } 3700 3701 3702 3703 3704 /* --- MODULE INFORMATION --- */ 3705 3706 const lt_dlinfo * 3707 lt_dlgetinfo (handle) 3708 lt_dlhandle handle; 3709 { 3710 if (!handle) 3711 { 3712 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 3713 return 0; 3714 } 3715 3716 return &(handle->info); 3717 } 3718 3719 lt_dlhandle 3720 lt_dlhandle_next (place) 3721 lt_dlhandle place; 3722 { 3723 return place ? place->next : handles; 3724 } 3725 3726 int 3727 lt_dlforeach (func, data) 3728 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); 3729 lt_ptr data; 3730 { 3731 int errors = 0; 3732 lt_dlhandle cur; 3733 3734 LT_DLMUTEX_LOCK (); 3735 3736 cur = handles; 3737 while (cur) 3738 { 3739 lt_dlhandle tmp = cur; 3740 3741 cur = cur->next; 3742 if ((*func) (tmp, data)) 3743 { 3744 ++errors; 3745 break; 3746 } 3747 } 3748 3749 LT_DLMUTEX_UNLOCK (); 3750 3751 return errors; 3752 } 3753 3754 lt_dlcaller_id 3755 lt_dlcaller_register () 3756 { 3757 static lt_dlcaller_id last_caller_id = 0; 3758 int result; 3759 3760 LT_DLMUTEX_LOCK (); 3761 result = ++last_caller_id; 3762 LT_DLMUTEX_UNLOCK (); 3763 3764 return result; 3765 } 3766 3767 lt_ptr 3768 lt_dlcaller_set_data (key, handle, data) 3769 lt_dlcaller_id key; 3770 lt_dlhandle handle; 3771 lt_ptr data; 3772 { 3773 int n_elements = 0; 3774 lt_ptr stale = (lt_ptr) 0; 3775 int i; 3776 3777 /* This needs to be locked so that the caller data can be updated 3778 simultaneously by different threads. */ 3779 LT_DLMUTEX_LOCK (); 3780 3781 if (handle->caller_data) 3782 while (handle->caller_data[n_elements].key) 3783 ++n_elements; 3784 3785 for (i = 0; i < n_elements; ++i) 3786 { 3787 if (handle->caller_data[i].key == key) 3788 { 3789 stale = handle->caller_data[i].data; 3790 break; 3791 } 3792 } 3793 3794 /* Ensure that there is enough room in this handle's caller_data 3795 array to accept a new element (and an empty end marker). */ 3796 if (i == n_elements) 3797 { 3798 lt_caller_data *temp 3799 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); 3800 3801 if (!temp) 3802 { 3803 stale = 0; 3804 goto done; 3805 } 3806 3807 handle->caller_data = temp; 3808 3809 /* We only need this if we needed to allocate a new caller_data. */ 3810 handle->caller_data[i].key = key; 3811 handle->caller_data[1+ i].key = 0; 3812 } 3813 3814 handle->caller_data[i].data = data; 3815 3816 done: 3817 LT_DLMUTEX_UNLOCK (); 3818 3819 return stale; 3820 } 3821 3822 lt_ptr 3823 lt_dlcaller_get_data (key, handle) 3824 lt_dlcaller_id key; 3825 lt_dlhandle handle; 3826 { 3827 lt_ptr result = (lt_ptr) 0; 3828 3829 /* This needs to be locked so that the caller data isn't updated by 3830 another thread part way through this function. */ 3831 LT_DLMUTEX_LOCK (); 3832 3833 /* Locate the index of the element with a matching KEY. */ 3834 { 3835 int i; 3836 for (i = 0; handle->caller_data[i].key; ++i) 3837 { 3838 if (handle->caller_data[i].key == key) 3839 { 3840 result = handle->caller_data[i].data; 3841 break; 3842 } 3843 } 3844 } 3845 3846 LT_DLMUTEX_UNLOCK (); 3847 3848 return result; 3849 } 3850 3851 3852 3853 /* --- USER MODULE LOADER API --- */ 3854 3855 3856 int 3857 lt_dlloader_add (place, dlloader, loader_name) 3858 lt_dlloader *place; 3859 const struct lt_user_dlloader *dlloader; 3860 const char *loader_name; 3861 { 3862 int errors = 0; 3863 lt_dlloader *node = 0, *ptr = 0; 3864 3865 if ((dlloader == 0) /* diagnose null parameters */ 3866 || (dlloader->module_open == 0) 3867 || (dlloader->module_close == 0) 3868 || (dlloader->find_sym == 0)) 3869 { 3870 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 3871 return 1; 3872 } 3873 3874 /* Create a new dlloader node with copies of the user callbacks. */ 3875 node = LT_EMALLOC (lt_dlloader, 1); 3876 if (!node) 3877 return 1; 3878 3879 node->next = 0; 3880 node->loader_name = loader_name; 3881 node->sym_prefix = dlloader->sym_prefix; 3882 node->dlloader_exit = dlloader->dlloader_exit; 3883 node->module_open = dlloader->module_open; 3884 node->module_close = dlloader->module_close; 3885 node->find_sym = dlloader->find_sym; 3886 node->dlloader_data = dlloader->dlloader_data; 3887 3888 LT_DLMUTEX_LOCK (); 3889 if (!loaders) 3890 { 3891 /* If there are no loaders, NODE becomes the list! */ 3892 loaders = node; 3893 } 3894 else if (!place) 3895 { 3896 /* If PLACE is not set, add NODE to the end of the 3897 LOADERS list. */ 3898 for (ptr = loaders; ptr->next; ptr = ptr->next) 3899 { 3900 /*NOWORK*/; 3901 } 3902 3903 ptr->next = node; 3904 } 3905 else if (loaders == place) 3906 { 3907 /* If PLACE is the first loader, NODE goes first. */ 3908 node->next = place; 3909 loaders = node; 3910 } 3911 else 3912 { 3913 /* Find the node immediately preceding PLACE. */ 3914 for (ptr = loaders; ptr->next != place; ptr = ptr->next) 3915 { 3916 /*NOWORK*/; 3917 } 3918 3919 if (ptr->next != place) 3920 { 3921 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 3922 ++errors; 3923 } 3924 else 3925 { 3926 /* Insert NODE between PTR and PLACE. */ 3927 node->next = place; 3928 ptr->next = node; 3929 } 3930 } 3931 3932 LT_DLMUTEX_UNLOCK (); 3933 3934 return errors; 3935 } 3936 3937 int 3938 lt_dlloader_remove (loader_name) 3939 const char *loader_name; 3940 { 3941 lt_dlloader *place = lt_dlloader_find (loader_name); 3942 lt_dlhandle handle; 3943 int errors = 0; 3944 3945 if (!place) 3946 { 3947 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 3948 return 1; 3949 } 3950 3951 LT_DLMUTEX_LOCK (); 3952 3953 /* Fail if there are any open modules which use this loader. */ 3954 for (handle = handles; handle; handle = handle->next) 3955 { 3956 if (handle->loader == place) 3957 { 3958 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); 3959 ++errors; 3960 goto done; 3961 } 3962 } 3963 3964 if (place == loaders) 3965 { 3966 /* PLACE is the first loader in the list. */ 3967 loaders = loaders->next; 3968 } 3969 else 3970 { 3971 /* Find the loader before the one being removed. */ 3972 lt_dlloader *prev; 3973 for (prev = loaders; prev->next; prev = prev->next) 3974 { 3975 if (!strcmp (prev->next->loader_name, loader_name)) 3976 { 3977 break; 3978 } 3979 } 3980 3981 place = prev->next; 3982 prev->next = prev->next->next; 3983 } 3984 3985 if (place->dlloader_exit) 3986 { 3987 errors = place->dlloader_exit (place->dlloader_data); 3988 } 3989 3990 LT_DLFREE (place); 3991 3992 done: 3993 LT_DLMUTEX_UNLOCK (); 3994 3995 return errors; 3996 } 3997 3998 lt_dlloader * 3999 lt_dlloader_next (place) 4000 lt_dlloader *place; 4001 { 4002 lt_dlloader *next; 4003 4004 LT_DLMUTEX_LOCK (); 4005 next = place ? place->next : loaders; 4006 LT_DLMUTEX_UNLOCK (); 4007 4008 return next; 4009 } 4010 4011 const char * 4012 lt_dlloader_name (place) 4013 lt_dlloader *place; 4014 { 4015 const char *name = 0; 4016 4017 if (place) 4018 { 4019 LT_DLMUTEX_LOCK (); 4020 name = place ? place->loader_name : 0; 4021 LT_DLMUTEX_UNLOCK (); 4022 } 4023 else 4024 { 4025 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 4026 } 4027 4028 return name; 4029 } 4030 4031 lt_user_data * 4032 lt_dlloader_data (place) 4033 lt_dlloader *place; 4034 { 4035 lt_user_data *data = 0; 4036 4037 if (place) 4038 { 4039 LT_DLMUTEX_LOCK (); 4040 data = place ? &(place->dlloader_data) : 0; 4041 LT_DLMUTEX_UNLOCK (); 4042 } 4043 else 4044 { 4045 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 4046 } 4047 4048 return data; 4049 } 4050 4051 lt_dlloader * 4052 lt_dlloader_find (loader_name) 4053 const char *loader_name; 4054 { 4055 lt_dlloader *place = 0; 4056 4057 LT_DLMUTEX_LOCK (); 4058 for (place = loaders; place; place = place->next) 4059 { 4060 if (strcmp (place->loader_name, loader_name) == 0) 4061 { 4062 break; 4063 } 4064 } 4065 LT_DLMUTEX_UNLOCK (); 4066 4067 return place; 4068 } 4069

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.