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