📄 ltdl.c
字号:
if (list_files_by_dir (dirname, &argz, &argz_len) != 0) goto cleanup; if (!argz) goto cleanup; { char *filename = 0; while ((filename = argz_next (argz, argz_len, filename))) if ((is_done = (*func) (filename, data2))) break; } cleanup: FREE (argz); return is_done;}/* Call FUNC for each unique extensionless file in SEARCH_PATH, along with DATA. The filenames passed to FUNC would be suitable for passing to lt_dlopenext. The extensions are stripped so that individual modules do not generate several entries (e.g. libfoo.la, libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, then the same directories that lt_dlopen would search are examined. */intlt_dlforeachfile (const char *search_path, int (*func) (const char *filename, void *data), void *data){ int is_done = 0; file_worker_func **fpptr = &func; if (search_path) { /* If a specific path was passed, search only the directories listed in it. */ is_done = foreach_dirinpath (search_path, 0, foreachfile_callback, fpptr, data); } else { /* Otherwise search the default paths. */ is_done = foreach_dirinpath (user_search_path, 0, foreachfile_callback, fpptr, data); if (!is_done) { is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0, foreachfile_callback, fpptr, data); }#if defined(LT_MODULE_PATH_VAR) if (!is_done) { is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0, foreachfile_callback, fpptr, data); }#endif#if defined(LT_DLSEARCH_PATH) if (!is_done && sys_dlsearch_path) { is_done = foreach_dirinpath (sys_dlsearch_path, 0, foreachfile_callback, fpptr, data); }#endif } return is_done;}intlt_dlclose (lt_dlhandle handle){ lt__handle *cur, *last; int errors = 0; /* check whether the handle is valid */ last = cur = (lt__handle *) handles; while (cur && handle != cur) { last = cur; cur = cur->next; } if (!cur) { LT__SETERROR (INVALID_HANDLE); ++errors; goto done; } cur = (lt__handle *) handle; cur->info.ref_count--; /* Note that even with resident modules, we must track the ref_count correctly incase the user decides to reset the residency flag later (even though the API makes no provision for that at the moment). */ if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur)) { lt_user_data data = cur->vtable->dlloader_data; if (cur != handles) { last->next = cur->next; } else { handles = cur->next; } errors += cur->vtable->module_close (data, cur->module); errors += unload_deplibs (handle); /* It is up to the callers to free the data itself. */ FREE (cur->interface_data); FREE (cur->info.filename); FREE (cur->info.name); FREE (cur); goto done; } if (LT_DLIS_RESIDENT (handle)) { LT__SETERROR (CLOSE_RESIDENT_MODULE); ++errors; } done: return errors;}void *lt_dlsym (lt_dlhandle place, const char *symbol){ size_t lensym; char lsym[LT_SYMBOL_LENGTH]; char *sym; void *address; lt_user_data data; lt__handle *handle; if (!place) { LT__SETERROR (INVALID_HANDLE); return 0; } handle = (lt__handle *) place; if (!symbol) { LT__SETERROR (SYMBOL_NOT_FOUND); return 0; } lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix) + LT_STRLEN (handle->info.name); if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) { sym = lsym; } else { sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); if (!sym) { LT__SETERROR (BUFFER_OVERFLOW); return 0; } } data = handle->vtable->dlloader_data; if (handle->info.name) { const char *saved_error; LT__GETERROR (saved_error); /* this is a libtool module */ if (handle->vtable->sym_prefix) { strcpy(sym, handle->vtable->sym_prefix); strcat(sym, handle->info.name); } else { strcpy(sym, handle->info.name); } strcat(sym, "_LTX_"); strcat(sym, symbol); /* try "modulename_LTX_symbol" */ address = handle->vtable->find_sym (data, handle->module, sym); if (address) { if (sym != lsym) { FREE (sym); } return address; } LT__SETERRORSTR (saved_error); } /* otherwise try "symbol" */ if (handle->vtable->sym_prefix) { strcpy(sym, handle->vtable->sym_prefix); strcat(sym, symbol); } else { strcpy(sym, symbol); } address = handle->vtable->find_sym (data, handle->module, sym); if (sym != lsym) { FREE (sym); } return address;}const char *lt_dlerror (void){ const char *error; LT__GETERROR (error); LT__SETERRORSTR (0); return error ? error : NULL;}static intlt_dlpath_insertdir (char **ppath, char *before, const char *dir){ int errors = 0; char *canonical = 0; char *argz = 0; size_t argz_len = 0; assert (ppath); assert (dir && *dir); if (canonicalize_path (dir, &canonical) != 0) { ++errors; goto cleanup; } assert (canonical && *canonical); /* If *PPATH is empty, set it to DIR. */ if (*ppath == 0) { assert (!before); /* BEFORE cannot be set without PPATH. */ assert (dir); /* Without DIR, don't call this function! */ *ppath = lt__strdup (dir); if (*ppath == 0) ++errors; goto cleanup; } assert (ppath && *ppath); if (argzize_path (*ppath, &argz, &argz_len) != 0) { ++errors; goto cleanup; } /* Convert BEFORE into an equivalent offset into ARGZ. This only works if *PPATH is already canonicalized, and hence does not change length with respect to ARGZ. We canonicalize each entry as it is added to the search path, and don't call this function with (uncanonicalized) user paths, so this is a fair assumption. */ if (before) { assert (*ppath <= before); assert ((int) (before - *ppath) <= (int) strlen (*ppath)); before = before - *ppath + argz; } if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) { ++errors; goto cleanup; } argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); MEMREASSIGN(*ppath, argz); cleanup: FREE (argz); FREE (canonical); return errors;}intlt_dladdsearchdir (const char *search_dir){ int errors = 0; if (search_dir && *search_dir) { if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) ++errors; } return errors;}intlt_dlinsertsearchdir (const char *before, const char *search_dir){ int errors = 0; if (before) { if ((before < user_search_path) || (before >= user_search_path + LT_STRLEN (user_search_path))) { LT__SETERROR (INVALID_POSITION); return 1; } } if (search_dir && *search_dir) { if (lt_dlpath_insertdir (&user_search_path, (char *) before, search_dir) != 0) { ++errors; } } return errors;}intlt_dlsetsearchpath (const char *search_path){ int errors = 0; FREE (user_search_path); if (!search_path || !LT_STRLEN (search_path)) { return errors; } if (canonicalize_path (search_path, &user_search_path) != 0) ++errors; return errors;}const char *lt_dlgetsearchpath (void){ const char *saved_path; saved_path = user_search_path; return saved_path;}intlt_dlmakeresident (lt_dlhandle handle){ int errors = 0; if (!handle) { LT__SETERROR (INVALID_HANDLE); ++errors; } else { ((lt__handle *) handle)->info.is_resident = 1; } return errors;}intlt_dlisresident (lt_dlhandle handle){ if (!handle) { LT__SETERROR (INVALID_HANDLE); return -1; } return LT_DLIS_RESIDENT (handle);}/* --- MODULE INFORMATION --- */typedef struct { const char *id_string; lt_dlhandle_interface *iface;} lt__interface_id;lt_dlinterface_idlt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface){ lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id); /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which can then be detected with lt_dlerror() if we return 0. */ if (interface_id) { interface_id->id_string = lt__strdup (id_string); if (!interface_id->id_string) FREE (interface_id); else interface_id->iface = iface; } return (lt_dlinterface_id) interface_id;}void lt_dlinterface_free (lt_dlinterface_id key){ lt__interface_id *interface_id = (lt__interface_id *)key; FREE (interface_id->id_string); FREE (interface_id);}void *lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data){ int n_elements = 0; void *stale = (void *) 0; lt__handle *cur = (lt__handle *) handle; int i; if (cur->interface_data) while (cur->interface_data[n_elements].key) ++n_elements; for (i = 0; i < n_elements; ++i) { if (cur->interface_data[i].key == key) { stale = cur->interface_data[i].data; break; } } /* Ensure that there is enough room in this handle's interface_data array to accept a new element (and an empty end marker). */ if (i == n_elements) { lt_interface_data *temp = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements); if (!temp) { stale = 0; goto done; } cur->interface_data = temp; /* We only need this if we needed to allocate a new interface_data. */ cur->interface_data[i].key = key; cur->interface_data[1+ i].key = 0; } cur->interface_data[i].data = data; done: return stale;}void *lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle){ void *result = (void *) 0; lt__handle *cur = (lt__handle *) handle; /* Locate the index of the element with a matching KEY. */ { int i; for (i = 0; cur->interface_data[i].key; ++i) { if (cur->interface_data[i].key == key) { result = cur->interface_data[i].data; break; } } } return result;}const lt_dlinfo *lt_dlgetinfo (lt_dlhandle handle){ if (!handle) { LT__SETERROR (INVALID_HANDLE); return 0; } return &(((lt__handle *) handle)->info);}lt_dlhandlelt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place){ lt__handle *handle = (lt__handle *) place; lt__interface_id *iterator = (lt__interface_id *) iface; assert (iface); /* iface is a required argument */ if (!handle) handle = (lt__handle *) handles; else handle = handle->next; /* advance while the interface check fails */ while (handle && iterator->iface && ((*iterator->iface) (handle, iterator->id_string) != 0)) { handle = handle->next; } return (lt_dlhandle) handle;}lt_dlhandlelt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name){ lt_dlhandle handle = 0; assert (iface); /* iface is a required argument */ while ((handle = lt_dlhandle_iterate (iface, handle))) { lt__handle *cur = (lt__handle *) handle; if (cur && cur->info.name && streq (cur->info.name, module_name)) break; } return handle;}intlt_dlhandle_map (lt_dlinterface_id iface, int (*func) (lt_dlhandle handle, void *data), void *data){ lt__interface_id *iterator = (lt__interface_id *) iface; lt__handle *cur = (lt__handle *) handles; assert (iface); /* iface is a required argument */ while (cur) { int errorcode = 0; /* advance while the interface check fails */ while (cur && iterator->iface && ((*iterator->iface) (cur, iterator->id_string) != 0)) { cur = cur->next; } if ((errorcode = (*func) (cur, data)) != 0) return errorcode; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -