/
niceSOFT
/
wget2
Обзор
Документация
Войти
/
niceSOFT
/
wget2
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/dl.c
392 строки
8 KB
Tim Rühsen
* src/dl.c (convert_to_path_if_not): Add semicolon
31 июл 2026, 20:44
Не верифицирован
31 июл 2026, 20:44
094bb7c
Код
Авторство
О чём код?
/* * Copyright (c) 2017-2026 Free Software Foundation, Inc. * * This file is part of Wget. * * Wget is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Wget is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Wget. If not, see <https://www.gnu.org/licenses/>. * * * Dynamic loading abstraction for object files * */ #include <config.h> #include <string.h> #include <sys/stat.h> #include <dirent.h> #include <stdarg.h> #include <wget.h> #include "wget_main.h" #include "wget_dl.h" // Error reporting functions static void dl_error_set_noalloc(dl_error_t *e, const char *msg) { if (msg && e->msg) wget_error_printf(_("Piling up error '%s' over error '%s'"), msg, e->msg); wget_free((void *) e->msg); e->msg = msg; } // Set an error message. Call with msg=NULL to clear error. void dl_error_set(dl_error_t *e, const char *msg) { dl_error_set_noalloc(e, wget_strdup(msg)); } // Set an error message with printf format. void dl_error_set_printf (dl_error_t *e, const char *format, ...) { va_list arglist; va_start(arglist, format); dl_error_set_noalloc(e, wget_vaprintf(format, arglist)); va_end(arglist); } #ifdef PLUGIN_SUPPORT // If the string is not a path, converts to path by prepending "./" to it, // else returns NULL static char *convert_to_path_if_not(const char *str) { if (!str || strchr(str, '/')) return NULL; #if defined _WIN32 if (strchr(str, '\\')) return NULL; #endif return wget_aprintf("./%s", str); } #endif #if defined PLUGIN_SUPPORT_LIBDL #include <dlfcn.h> int dl_supported(void) { return 1; } struct dl_file_st { void *handle; }; // Opens an object file dl_file_t *dl_file_open(const char *filename, dl_error_t *e) { dl_file_t *dm = NULL; dl_file_t dm_st; char *buf = convert_to_path_if_not(filename); dm_st.handle = dlopen(buf ? buf : filename, RTLD_LAZY | RTLD_LOCAL); wget_xfree(buf); if (dm_st.handle) dm = wget_memdup(&dm_st, sizeof(dl_file_t)); else dl_error_set(e, dlerror()); return dm; } void *dl_file_lookup(dl_file_t *dm, const char *symbol, dl_error_t *e) { void *res; char *error; #ifdef __OS2__ // On OS/2, symbols may have underscore('_') prefix. { char *os2_symbol; wget_asprintf(&os2_symbol, "_%s", symbol); if (os2_symbol) { res = dlsym(dm->handle, os2_symbol); xfree(os2_symbol); if (res) return res; } // fall back } #endif res = dlsym(dm->handle, symbol); error = dlerror(); if (error) { dl_error_set(e, error); return NULL; } return res; } void dl_file_close(dl_file_t *dm) { dlclose(dm->handle); wget_free(dm); } #elif defined PLUGIN_SUPPORT_WINDOWS #include <windows.h> int dl_supported(void) { return 1; } struct dl_file_st { HMODULE handle; }; static void dl_win32_set_last_error(dl_error_t *e) { char *buf; DWORD error_code = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0, (LPTSTR) &buf, 0, NULL); if (buf) { dl_error_set(e, buf); LocalFree(buf); } else { dl_error_set_printf(e, "Unknown error %d", (int) error_code); } } dl_file_t *dl_file_open(const char *filename, dl_error_t *e) { dl_file_t *dm = NULL; dl_file_t dm_st; char *buf = convert_to_path_if_not(filename); dm_st.handle = LoadLibrary(buf ? buf : filename); wget_xfree(buf); if (dm_st.handle) dm = wget_memdup(&dm_st, sizeof(dl_file_t)); else dl_win32_set_last_error(e); return dm; } void *dl_file_lookup(dl_file_t *dm, const char *symbol, dl_error_t *e) { void *res = GetProcAddress(dm->handle, symbol); if (! res) dl_win32_set_last_error(e); return res; } void dl_file_close(dl_file_t *dm) { FreeLibrary(dm->handle); wget_free(dm); } #else static const char *dl_unsupported = "Dynamic loading is not supported on the current platform."; int dl_supported(void) { return 0; } dl_file_t *dl_file_open(WGET_GCC_UNUSED const char *filename, dl_error_t *e) { dl_error_set(e, dl_unsupported); return NULL; } void *dl_file_lookup(WGET_GCC_UNUSED dl_file_t *dm, WGET_GCC_UNUSED const char *symbol, dl_error_t *e) { dl_error_set(e, dl_unsupported); return NULL; } void dl_file_close(WGET_GCC_UNUSED dl_file_t *dm) { } #endif typedef struct { const char *prefix; const char *suffix; } object_pattern_t; #if defined _WIN32 #define PATTERNS {"lib", ".dll"}, {"", ".dll"} #elif defined __APPLE__ #define PATTERNS {"lib", ".so"}, {"lib", ".bundle"}, {"lib", ".dylib"} #elif defined __CYGWIN__ #define PATTERNS {"cyg", ".dll"} #elif defined __OS2__ #define PATTERNS {"lib", ".dll"}, {"", ".dll"} #else #define PATTERNS {"lib", ".so"} #endif static const object_pattern_t dl_patterns[] = {PATTERNS, {NULL, NULL}}; #undef PATTERNS // Matches the given path with the patterns of a loadable object file // and returns a range to use as a name static int dl_match(const char *path, size_t *start_out, size_t *len_out) { size_t i, mark; size_t start, len; // Strip everything but the filename mark = 0; for (i = 0; path[i]; i++) { if (path[i] == '/') mark = i + 1; #if defined _WIN32 || defined __OS2__ if (path[i] == '\\') mark = i + 1; #endif // _WIN32 } start = mark; len = i - start; // Match for the pattern and extract the name for (i = 0; dl_patterns[i].prefix; i++) { const char *p = dl_patterns[i].prefix; const char *s = dl_patterns[i].suffix; size_t pl = strlen(p); size_t sl = strlen(s); if (pl + sl >= len) continue; if (memcmp(path + start + len - sl, s, sl) == 0 && memcmp(path + start, p, pl) == 0) { start += pl; len -= (pl + sl); break; } } *start_out = start; *len_out = len; return dl_patterns[i].prefix ? 1 : 0; } static int is_regular_file(const char *filename) { struct stat statbuf; if (stat(filename, &statbuf) < 0) return 0; if (S_ISREG(statbuf.st_mode)) return 1; return 0; } char *dl_get_name_from_path(const char *path, int strict) { size_t start, len; int match = dl_match(path, &start, &len); if (!match && strict) return NULL; else return wget_strmemdup(path + start, len); } char *dl_search(const char *name, const wget_vector *dirs) { int n_dirs = wget_vector_size(dirs); for (int i = 0; i < n_dirs; i++) { const char *dir = wget_vector_get(dirs, i); if (dir && *dir) { for (int j = 0; dl_patterns[j].prefix; j++) { char *filename = wget_aprintf("%s/%s%s%s", dir, dl_patterns[j].prefix, name, dl_patterns[j].suffix); if (is_regular_file(filename)) return filename; wget_free(filename); } } else { for (int j = 0; dl_patterns[j].prefix; j++) { char *filename = wget_aprintf("%s%s%s", dl_patterns[j].prefix, name, dl_patterns[j].suffix); if (is_regular_file(filename)) return filename; wget_free(filename); } } } return NULL; } void dl_list(const wget_vector *dirs, wget_vector *names_out) { int n_dirs = wget_vector_size(dirs); for (int i = 0; i < n_dirs; i++) { DIR *dirp; struct dirent *ent; const char *dir = wget_vector_get(dirs, i); dirp = opendir(dir); if (!dirp) continue; while((ent = readdir(dirp)) != NULL) { char *fname; char *name; fname = ent->d_name; // Ignore entries that don't match the pattern name = dl_get_name_from_path(fname, 1); if (! name) continue; // Ignore entries that are not regular files { char *sfname = wget_aprintf("%s/%s", dir, fname); int x = is_regular_file(sfname); wget_free(sfname); if (!x) { wget_free(name); continue; } } // Add to the list wget_vector_add(names_out, name); } closedir(dirp); } }