| /* |
| * xmlmodule.c : basic API for dynamic module loading added 2.6.17 |
| * |
| * See Copyright for the status of this software. |
| * |
| * joelwreed@comcast.net |
| * |
| * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html |
| */ |
| |
| #define IN_LIBXML |
| #include "libxml.h" |
| |
| #include <string.h> |
| #include <libxml/xmlmemory.h> |
| #include <libxml/xmlerror.h> |
| #include <libxml/xmlmodule.h> |
| #include <libxml/globals.h> |
| |
| #ifdef LIBXML_MODULES_ENABLED |
| |
| struct _xmlModule { |
| unsigned char *name; |
| void *handle; |
| }; |
| |
| static void *xmlModulePlatformOpen(const char *name); |
| static int xmlModulePlatformClose(void *handle); |
| static int xmlModulePlatformSymbol(void *handle, const char *name, void **result); |
| |
| /************************************************************************ |
| * * |
| * module memory error handler * |
| * * |
| ************************************************************************/ |
| |
| /** |
| * xmlModuleErrMemory: |
| * @extra: extra information |
| * |
| * Handle an out of memory condition |
| */ |
| static void |
| xmlModuleErrMemory(xmlModulePtr module, const char *extra) |
| { |
| const char *name = NULL; |
| |
| if (module != NULL) { |
| name = (const char *) module->name; |
| } |
| |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, |
| XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, |
| name, NULL, 0, 0, |
| "Memory allocation failed : %s\n", extra); |
| } |
| |
| /** |
| * xmlModuleOpen: |
| * @name: the module name |
| * @options: a set of xmlModuleOption |
| * |
| * Opens a module/shared library given its name or path |
| * NOTE: that due to portability issues, behaviour can only be |
| * guaranteed with @name using ASCII. We canot guarantee that |
| * an UTF-8 string would work, which is why name is a const char * |
| * and not a const xmlChar * . |
| * TODO: options are not yet implemented. |
| * |
| * Returns a handle for the module or NULL in case of error |
| */ |
| xmlModulePtr |
| xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED) |
| { |
| xmlModulePtr module; |
| |
| module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule)); |
| if (module == NULL) { |
| xmlModuleErrMemory(NULL, "creating module"); |
| return (NULL); |
| } |
| |
| memset(module, 0, sizeof(xmlModule)); |
| |
| module->handle = xmlModulePlatformOpen(name); |
| |
| if (module->handle == NULL) { |
| xmlFree(module); |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, |
| XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, |
| name, NULL, 0, 0, "failed to open %s\n", name); |
| return(NULL); |
| } |
| |
| module->name = xmlStrdup((const xmlChar *) name); |
| return (module); |
| } |
| |
| /** |
| * xmlModuleSymbol: |
| * @module: the module |
| * @name: the name of the symbol |
| * @symbol: the resulting symbol address |
| * |
| * Lookup for a symbol address in the given module |
| * NOTE: that due to portability issues, behaviour can only be |
| * guaranteed with @name using ASCII. We canot guarantee that |
| * an UTF-8 string would work, which is why name is a const char * |
| * and not a const xmlChar * . |
| * |
| * Returns 0 if the symbol was found, or -1 in case of error |
| */ |
| int |
| xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol) |
| { |
| int rc = -1; |
| |
| if ((NULL == module) || (symbol == NULL) || (name == NULL)) { |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, |
| XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, |
| NULL, NULL, 0, 0, "null parameter\n"); |
| return rc; |
| } |
| |
| rc = xmlModulePlatformSymbol(module->handle, name, symbol); |
| |
| if (rc == -1) { |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, |
| XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, |
| name, NULL, 0, 0, |
| "failed to find symbol: %s\n", |
| (name == NULL ? "NULL" : name)); |
| return rc; |
| } |
| |
| return rc; |
| } |
| |
| /** |
| * xmlModuleClose: |
| * @module: the module handle |
| * |
| * The close operations unload the associated module and free the |
| * data associated to the module. |
| * |
| * Returns 0 in case of success, -1 in case of argument error and -2 |
| * if the module could not be closed/unloaded. |
| */ |
| int |
| xmlModuleClose(xmlModulePtr module) |
| { |
| int rc; |
| |
| if (NULL == module) { |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, |
| XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, |
| NULL, NULL, 0, 0, "null module pointer\n"); |
| return -1; |
| } |
| |
| rc = xmlModulePlatformClose(module->handle); |
| |
| if (rc != 0) { |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, |
| XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, |
| (const char *) module->name, NULL, 0, 0, |
| "failed to close: %s\n", module->name); |
| return -2; |
| } |
| |
| rc = xmlModuleFree(module); |
| return (rc); |
| } |
| |
| /** |
| * xmlModuleFree: |
| * @module: the module handle |
| * |
| * The free operations free the data associated to the module |
| * but does not unload the associated shared library which may still |
| * be in use. |
| * |
| * Returns 0 in case of success, -1 in case of argument error |
| */ |
| int |
| xmlModuleFree(xmlModulePtr module) |
| { |
| if (NULL == module) { |
| __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, |
| XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL, |
| NULL, NULL, 0, 0, "null module pointer\n"); |
| return -1; |
| } |
| |
| xmlFree(module->name); |
| xmlFree(module); |
| |
| return (0); |
| } |
| |
| #if defined(HAVE_DLOPEN) && !defined(_WIN32) |
| #ifdef HAVE_DLFCN_H |
| #include <dlfcn.h> |
| #endif |
| |
| #ifndef RTLD_GLOBAL /* For Tru64 UNIX 4.0 */ |
| #define RTLD_GLOBAL 0 |
| #endif |
| |
| /** |
| * xmlModulePlatformOpen: |
| * @name: path to the module |
| * |
| * returns a handle on success, and zero on error. |
| */ |
| |
| static void * |
| xmlModulePlatformOpen(const char *name) |
| { |
| return dlopen(name, RTLD_GLOBAL | RTLD_NOW); |
| } |
| |
| /* |
| * xmlModulePlatformClose: |
| * @handle: handle to the module |
| * |
| * returns 0 on success, and non-zero on error. |
| */ |
| |
| static int |
| xmlModulePlatformClose(void *handle) |
| { |
| return dlclose(handle); |
| } |
| |
| /* |
| * xmlModulePlatformSymbol: |
| * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html |
| * returns 0 on success and the loaded symbol in result, and -1 on error. |
| */ |
| |
| static int |
| xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) |
| { |
| *symbol = dlsym(handle, name); |
| if (dlerror() != NULL) { |
| return -1; |
| } |
| return 0; |
| } |
| |
| #else /* ! HAVE_DLOPEN */ |
| |
| #ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */ |
| #ifdef HAVE_DL_H |
| #include <dl.h> |
| #endif |
| /* |
| * xmlModulePlatformOpen: |
| * returns a handle on success, and zero on error. |
| */ |
| |
| static void * |
| xmlModulePlatformOpen(const char *name) |
| { |
| return shl_load(name, BIND_IMMEDIATE, 0L); |
| } |
| |
| /* |
| * xmlModulePlatformClose: |
| * returns 0 on success, and non-zero on error. |
| */ |
| |
| static int |
| xmlModulePlatformClose(void *handle) |
| { |
| return shl_unload(handle); |
| } |
| |
| /* |
| * xmlModulePlatformSymbol: |
| * http://docs.hp.com/en/B2355-90683/shl_load.3X.html |
| * returns 0 on success and the loaded symbol in result, and -1 on error. |
| */ |
| |
| static int |
| xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) |
| { |
| int rc; |
| |
| errno = 0; |
| rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol); |
| return rc; |
| } |
| |
| #endif /* HAVE_SHLLOAD */ |
| #endif /* ! HAVE_DLOPEN */ |
| |
| #ifdef _WIN32 |
| |
| #include <windows.h> |
| |
| /* |
| * xmlModulePlatformOpen: |
| * returns a handle on success, and zero on error. |
| */ |
| |
| static void * |
| xmlModulePlatformOpen(const char *name) |
| { |
| return LoadLibraryA(name); |
| } |
| |
| /* |
| * xmlModulePlatformClose: |
| * returns 0 on success, and non-zero on error. |
| */ |
| |
| static int |
| xmlModulePlatformClose(void *handle) |
| { |
| int rc; |
| |
| rc = FreeLibrary(handle); |
| return (0 == rc); |
| } |
| |
| /* |
| * xmlModulePlatformSymbol: |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp |
| * returns 0 on success and the loaded symbol in result, and -1 on error. |
| */ |
| |
| static int |
| xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) |
| { |
| #ifdef _WIN32_WCE |
| /* |
| * GetProcAddressA seems only available on WinCE |
| */ |
| *symbol = GetProcAddressA(handle, name); |
| #else |
| *symbol = GetProcAddress(handle, name); |
| #endif |
| return (NULL == *symbol) ? -1 : 0; |
| } |
| |
| #endif /* _WIN32 */ |
| |
| #ifdef HAVE_BEOS |
| |
| #include <kernel/image.h> |
| |
| /* |
| * xmlModulePlatformOpen: |
| * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html |
| * returns a handle on success, and zero on error. |
| */ |
| |
| static void * |
| xmlModulePlatformOpen(const char *name) |
| { |
| return (void *) load_add_on(name); |
| } |
| |
| /* |
| * xmlModulePlatformClose: |
| * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html |
| * returns 0 on success, and non-zero on error. |
| */ |
| |
| static int |
| xmlModulePlatformClose(void *handle) |
| { |
| status_t rc; |
| |
| rc = unload_add_on((image_id) handle); |
| |
| if (rc == B_OK) |
| return 0; |
| else |
| return -1; |
| } |
| |
| /* |
| * xmlModulePlatformSymbol: |
| * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html |
| * returns 0 on success and the loaded symbol in result, and -1 on error. |
| */ |
| |
| static int |
| xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) |
| { |
| status_t rc; |
| |
| rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol); |
| |
| return (rc == B_OK) ? 0 : -1; |
| } |
| |
| #endif /* HAVE_BEOS */ |
| |
| #ifdef HAVE_OS2 |
| |
| #include <os2.h> |
| |
| /* |
| * xmlModulePlatformOpen: |
| * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html |
| * returns a handle on success, and zero on error. |
| */ |
| |
| static void * |
| xmlModulePlatformOpen(const char *name) |
| { |
| char errbuf[256]; |
| void *handle; |
| int rc; |
| |
| rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle); |
| |
| if (rc) |
| return 0; |
| else |
| return (handle); |
| } |
| |
| /* |
| * xmlModulePlatformClose: |
| * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html |
| * returns 0 on success, and non-zero on error. |
| */ |
| |
| static int |
| xmlModulePlatformClose(void *handle) |
| { |
| return DosFreeModule(handle); |
| } |
| |
| /* |
| * xmlModulePlatformSymbol: |
| * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html |
| * returns 0 on success and the loaded symbol in result, and -1 on error. |
| */ |
| |
| static int |
| xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) |
| { |
| int rc; |
| |
| rc = DosQueryProcAddr(handle, 0, name, symbol); |
| |
| return (rc == NO_ERROR) ? 0 : -1; |
| } |
| |
| #endif /* HAVE_OS2 */ |
| |
| #define bottom_xmlmodule |
| #include "elfgcchack.h" |
| #endif /* LIBXML_MODULES_ENABLED */ |