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