Home | History | Annotate | Download | only in libxml2
      1 /*
      2  * xmlmodule.c : basic API for dynamic module loading added 2.6.17
      3  *
      4  * See Copyright for the status of this software.
      5  *
      6  * joelwreed (at) comcast.net
      7  *
      8  * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
      9  */
     10 
     11 /* In order RTLD_GLOBAL and RTLD_NOW to be defined on zOS */
     12 #if defined(__MVS__)
     13 #define _UNIX03_SOURCE
     14 #endif
     15 
     16 #define IN_LIBXML
     17 #include "libxml.h"
     18 
     19 #include <string.h>
     20 #include <libxml/xmlmemory.h>
     21 #include <libxml/xmlerror.h>
     22 #include <libxml/xmlmodule.h>
     23 #include <libxml/globals.h>
     24 
     25 #ifdef LIBXML_MODULES_ENABLED
     26 
     27 struct _xmlModule {
     28     unsigned char *name;
     29     void *handle;
     30 };
     31 
     32 static void *xmlModulePlatformOpen(const char *name);
     33 static int xmlModulePlatformClose(void *handle);
     34 static int xmlModulePlatformSymbol(void *handle, const char *name, void **result);
     35 
     36 /************************************************************************
     37  *									*
     38  *		module memory error handler				*
     39  *									*
     40  ************************************************************************/
     41 
     42 /**
     43  * xmlModuleErrMemory:
     44  * @extra:  extra information
     45  *
     46  * Handle an out of memory condition
     47  */
     48 static void
     49 xmlModuleErrMemory(xmlModulePtr module, const char *extra)
     50 {
     51     const char *name = NULL;
     52 
     53     if (module != NULL) {
     54         name = (const char *) module->name;
     55     }
     56 
     57     __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
     58                     XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
     59                     name, NULL, 0, 0,
     60                     "Memory allocation failed : %s\n", extra);
     61 }
     62 
     63 /**
     64  * xmlModuleOpen:
     65  * @name: the module name
     66  * @options: a set of xmlModuleOption
     67  *
     68  * Opens a module/shared library given its name or path
     69  * NOTE: that due to portability issues, behaviour can only be
     70  * guaranteed with @name using ASCII. We canot guarantee that
     71  * an UTF-8 string would work, which is why name is a const char *
     72  * and not a const xmlChar * .
     73  * TODO: options are not yet implemented.
     74  *
     75  * Returns a handle for the module or NULL in case of error
     76  */
     77 xmlModulePtr
     78 xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
     79 {
     80     xmlModulePtr module;
     81 
     82     module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
     83     if (module == NULL) {
     84         xmlModuleErrMemory(NULL, "creating module");
     85         return (NULL);
     86     }
     87 
     88     memset(module, 0, sizeof(xmlModule));
     89 
     90     module->handle = xmlModulePlatformOpen(name);
     91 
     92     if (module->handle == NULL) {
     93         xmlFree(module);
     94         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
     95                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
     96                         name, NULL, 0, 0, "failed to open %s\n", name);
     97         return(NULL);
     98     }
     99 
    100     module->name = xmlStrdup((const xmlChar *) name);
    101     return (module);
    102 }
    103 
    104 /**
    105  * xmlModuleSymbol:
    106  * @module: the module
    107  * @name: the name of the symbol
    108  * @symbol: the resulting symbol address
    109  *
    110  * Lookup for a symbol address in the given module
    111  * NOTE: that due to portability issues, behaviour can only be
    112  * guaranteed with @name using ASCII. We canot guarantee that
    113  * an UTF-8 string would work, which is why name is a const char *
    114  * and not a const xmlChar * .
    115  *
    116  * Returns 0 if the symbol was found, or -1 in case of error
    117  */
    118 int
    119 xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
    120 {
    121     int rc = -1;
    122 
    123     if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
    124         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
    125                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
    126                         NULL, NULL, 0, 0, "null parameter\n");
    127         return rc;
    128     }
    129 
    130     rc = xmlModulePlatformSymbol(module->handle, name, symbol);
    131 
    132     if (rc == -1) {
    133         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
    134                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
    135                         name, NULL, 0, 0,
    136                         "failed to find symbol: %s\n",
    137 			(name == NULL ? "NULL" : name));
    138         return rc;
    139     }
    140 
    141     return rc;
    142 }
    143 
    144 /**
    145  * xmlModuleClose:
    146  * @module: the module handle
    147  *
    148  * The close operations unload the associated module and free the
    149  * data associated to the module.
    150  *
    151  * Returns 0 in case of success, -1 in case of argument error and -2
    152  *         if the module could not be closed/unloaded.
    153  */
    154 int
    155 xmlModuleClose(xmlModulePtr module)
    156 {
    157     int rc;
    158 
    159     if (NULL == module) {
    160         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
    161                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
    162                         NULL, NULL, 0, 0, "null module pointer\n");
    163         return -1;
    164     }
    165 
    166     rc = xmlModulePlatformClose(module->handle);
    167 
    168     if (rc != 0) {
    169         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
    170                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
    171                         (const char *) module->name, NULL, 0, 0,
    172                         "failed to close: %s\n", module->name);
    173         return -2;
    174     }
    175 
    176     rc = xmlModuleFree(module);
    177     return (rc);
    178 }
    179 
    180 /**
    181  * xmlModuleFree:
    182  * @module: the module handle
    183  *
    184  * The free operations free the data associated to the module
    185  * but does not unload the associated shared library which may still
    186  * be in use.
    187  *
    188  * Returns 0 in case of success, -1 in case of argument error
    189  */
    190 int
    191 xmlModuleFree(xmlModulePtr module)
    192 {
    193     if (NULL == module) {
    194         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
    195                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
    196                         NULL, NULL, 0, 0, "null module pointer\n");
    197         return -1;
    198     }
    199 
    200     xmlFree(module->name);
    201     xmlFree(module);
    202 
    203     return (0);
    204 }
    205 
    206 #if defined(HAVE_DLOPEN) && !defined(_WIN32)
    207 #ifdef HAVE_DLFCN_H
    208 #include <dlfcn.h>
    209 #endif
    210 
    211 #ifndef RTLD_GLOBAL            /* For Tru64 UNIX 4.0 */
    212 #define RTLD_GLOBAL 0
    213 #endif
    214 
    215 /**
    216  * xmlModulePlatformOpen:
    217  * @name: path to the module
    218  *
    219  * returns a handle on success, and zero on error.
    220  */
    221 
    222 static void *
    223 xmlModulePlatformOpen(const char *name)
    224 {
    225     return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
    226 }
    227 
    228 /*
    229  * xmlModulePlatformClose:
    230  * @handle: handle to the module
    231  *
    232  * returns 0 on success, and non-zero on error.
    233  */
    234 
    235 static int
    236 xmlModulePlatformClose(void *handle)
    237 {
    238     return dlclose(handle);
    239 }
    240 
    241 /*
    242  * xmlModulePlatformSymbol:
    243  * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
    244  * returns 0 on success and the loaded symbol in result, and -1 on error.
    245  */
    246 
    247 static int
    248 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
    249 {
    250     *symbol = dlsym(handle, name);
    251     if (dlerror() != NULL) {
    252 	return -1;
    253     }
    254     return 0;
    255 }
    256 
    257 #else /* ! HAVE_DLOPEN */
    258 
    259 #ifdef HAVE_SHLLOAD             /* HAVE_SHLLOAD */
    260 #ifdef HAVE_DL_H
    261 #include <dl.h>
    262 #endif
    263 /*
    264  * xmlModulePlatformOpen:
    265  * returns a handle on success, and zero on error.
    266  */
    267 
    268 static void *
    269 xmlModulePlatformOpen(const char *name)
    270 {
    271     return shl_load(name, BIND_IMMEDIATE, 0L);
    272 }
    273 
    274 /*
    275  * xmlModulePlatformClose:
    276  * returns 0 on success, and non-zero on error.
    277  */
    278 
    279 static int
    280 xmlModulePlatformClose(void *handle)
    281 {
    282     return shl_unload(handle);
    283 }
    284 
    285 /*
    286  * xmlModulePlatformSymbol:
    287  * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
    288  * returns 0 on success and the loaded symbol in result, and -1 on error.
    289  */
    290 
    291 static int
    292 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
    293 {
    294     int rc;
    295 
    296     errno = 0;
    297     rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol);
    298     return rc;
    299 }
    300 
    301 #endif /* HAVE_SHLLOAD */
    302 #endif /* ! HAVE_DLOPEN */
    303 
    304 #if defined(_WIN32) && !defined(__CYGWIN__)
    305 
    306 #define WIN32_LEAN_AND_MEAN
    307 #include <windows.h>
    308 
    309 /*
    310  * xmlModulePlatformOpen:
    311  * returns a handle on success, and zero on error.
    312  */
    313 
    314 static void *
    315 xmlModulePlatformOpen(const char *name)
    316 {
    317     return LoadLibraryA(name);
    318 }
    319 
    320 /*
    321  * xmlModulePlatformClose:
    322  * returns 0 on success, and non-zero on error.
    323  */
    324 
    325 static int
    326 xmlModulePlatformClose(void *handle)
    327 {
    328     int rc;
    329 
    330     rc = FreeLibrary(handle);
    331     return (0 == rc);
    332 }
    333 
    334 /*
    335  * xmlModulePlatformSymbol:
    336  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
    337  * returns 0 on success and the loaded symbol in result, and -1 on error.
    338  */
    339 
    340 static int
    341 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
    342 {
    343 XML_IGNORE_PEDANTIC_WARNINGS
    344 #ifdef _WIN32_WCE
    345     /*
    346      * GetProcAddressA seems only available on WinCE
    347      */
    348     *symbol = GetProcAddressA(handle, name);
    349 #else
    350     *symbol = GetProcAddress(handle, name);
    351 #endif
    352     return (NULL == *symbol) ? -1 : 0;
    353 XML_POP_WARNINGS
    354 }
    355 
    356 #endif /* _WIN32 */
    357 
    358 #ifdef HAVE_BEOS
    359 
    360 #include <kernel/image.h>
    361 
    362 /*
    363  * xmlModulePlatformOpen:
    364  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
    365  * returns a handle on success, and zero on error.
    366  */
    367 
    368 static void *
    369 xmlModulePlatformOpen(const char *name)
    370 {
    371     return (void *) load_add_on(name);
    372 }
    373 
    374 /*
    375  * xmlModulePlatformClose:
    376  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
    377  * returns 0 on success, and non-zero on error.
    378  */
    379 
    380 static int
    381 xmlModulePlatformClose(void *handle)
    382 {
    383     status_t rc;
    384 
    385     rc = unload_add_on((image_id) handle);
    386 
    387     if (rc == B_OK)
    388         return 0;
    389     else
    390         return -1;
    391 }
    392 
    393 /*
    394  * xmlModulePlatformSymbol:
    395  * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
    396  * returns 0 on success and the loaded symbol in result, and -1 on error.
    397  */
    398 
    399 static int
    400 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
    401 {
    402     status_t rc;
    403 
    404     rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
    405 
    406     return (rc == B_OK) ? 0 : -1;
    407 }
    408 
    409 #endif /* HAVE_BEOS */
    410 
    411 #ifdef HAVE_OS2
    412 
    413 #include <os2.h>
    414 
    415 /*
    416  * xmlModulePlatformOpen:
    417  * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
    418  * returns a handle on success, and zero on error.
    419  */
    420 
    421 static void *
    422 xmlModulePlatformOpen(const char *name)
    423 {
    424     char errbuf[256];
    425     void *handle;
    426     int rc;
    427 
    428     rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
    429 
    430     if (rc)
    431         return 0;
    432     else
    433         return (handle);
    434 }
    435 
    436 /*
    437  * xmlModulePlatformClose:
    438  * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
    439  * returns 0 on success, and non-zero on error.
    440  */
    441 
    442 static int
    443 xmlModulePlatformClose(void *handle)
    444 {
    445     return DosFreeModule(handle);
    446 }
    447 
    448 /*
    449  * xmlModulePlatformSymbol:
    450  * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
    451  * returns 0 on success and the loaded symbol in result, and -1 on error.
    452  */
    453 
    454 static int
    455 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
    456 {
    457     int rc;
    458 
    459     rc = DosQueryProcAddr(handle, 0, name, symbol);
    460 
    461     return (rc == NO_ERROR) ? 0 : -1;
    462 }
    463 
    464 #endif /* HAVE_OS2 */
    465 
    466 #define bottom_xmlmodule
    467 #include "elfgcchack.h"
    468 #endif /* LIBXML_MODULES_ENABLED */
    469