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 #ifdef _WIN32_WCE 344 /* 345 * GetProcAddressA seems only available on WinCE 346 */ 347 *symbol = GetProcAddressA(handle, name); 348 #else 349 *symbol = GetProcAddress(handle, name); 350 #endif 351 return (NULL == *symbol) ? -1 : 0; 352 } 353 354 #endif /* _WIN32 */ 355 356 #ifdef HAVE_BEOS 357 358 #include <kernel/image.h> 359 360 /* 361 * xmlModulePlatformOpen: 362 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 363 * returns a handle on success, and zero on error. 364 */ 365 366 static void * 367 xmlModulePlatformOpen(const char *name) 368 { 369 return (void *) load_add_on(name); 370 } 371 372 /* 373 * xmlModulePlatformClose: 374 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 375 * returns 0 on success, and non-zero on error. 376 */ 377 378 static int 379 xmlModulePlatformClose(void *handle) 380 { 381 status_t rc; 382 383 rc = unload_add_on((image_id) handle); 384 385 if (rc == B_OK) 386 return 0; 387 else 388 return -1; 389 } 390 391 /* 392 * xmlModulePlatformSymbol: 393 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 394 * returns 0 on success and the loaded symbol in result, and -1 on error. 395 */ 396 397 static int 398 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) 399 { 400 status_t rc; 401 402 rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol); 403 404 return (rc == B_OK) ? 0 : -1; 405 } 406 407 #endif /* HAVE_BEOS */ 408 409 #ifdef HAVE_OS2 410 411 #include <os2.h> 412 413 /* 414 * xmlModulePlatformOpen: 415 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html 416 * returns a handle on success, and zero on error. 417 */ 418 419 static void * 420 xmlModulePlatformOpen(const char *name) 421 { 422 char errbuf[256]; 423 void *handle; 424 int rc; 425 426 rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle); 427 428 if (rc) 429 return 0; 430 else 431 return (handle); 432 } 433 434 /* 435 * xmlModulePlatformClose: 436 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html 437 * returns 0 on success, and non-zero on error. 438 */ 439 440 static int 441 xmlModulePlatformClose(void *handle) 442 { 443 return DosFreeModule(handle); 444 } 445 446 /* 447 * xmlModulePlatformSymbol: 448 * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html 449 * returns 0 on success and the loaded symbol in result, and -1 on error. 450 */ 451 452 static int 453 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) 454 { 455 int rc; 456 457 rc = DosQueryProcAddr(handle, 0, name, symbol); 458 459 return (rc == NO_ERROR) ? 0 : -1; 460 } 461 462 #endif /* HAVE_OS2 */ 463 464 #define bottom_xmlmodule 465 #include "elfgcchack.h" 466 #endif /* LIBXML_MODULES_ENABLED */ 467