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 /* 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