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 LoadLibraryA(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