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