xmlmodule.c revision f6b71bd176bf2a48e052740f0b58c8f69bd07781
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 9#define IN_LIBXML 10#include "libxml.h" 11 12#include <string.h> 13#include <libxml/xmlmemory.h> 14#include <libxml/xmlerror.h> 15#include <libxml/xmlmodule.h> 16#include <libxml/globals.h> 17 18#ifdef LIBXML_MODULES_ENABLED 19 20struct _xmlModule { 21 unsigned char *name; 22 void *handle; 23}; 24 25static void *xmlModulePlatformOpen(const char *name); 26static int xmlModulePlatformClose(void *handle); 27static void *xmlModulePlatformSymbol(void *handle, const char *name); 28 29/************************************************************************ 30 * * 31 * module memory error handler * 32 * * 33 ************************************************************************/ 34 35/** 36 * xmlModuleErrMemory: 37 * @extra: extra information 38 * 39 * Handle an out of memory condition 40 */ 41static void 42xmlModuleErrMemory(xmlModulePtr module, const char *extra) 43{ 44 const char *name = NULL; 45 46 if (module != NULL) { 47 name = (const char *) module->name; 48 } 49 50 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 51 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, 52 name, NULL, 0, 0, 53 "Memory allocation failed : %s\n", extra); 54} 55 56/** 57 * xmlModuleOpen: 58 * @name: the module name 59 * 60 * Opens a module/shared library given its name or path 61 * 62 * Returns a handle for the module or NULL in case of error 63 */ 64xmlModulePtr 65xmlModuleOpen(const char *name) 66{ 67 xmlModulePtr module; 68 69 module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule)); 70 if (module == NULL) { 71 xmlModuleErrMemory(NULL, "creating module"); 72 return (NULL); 73 } 74 75 memset(module, 0, sizeof(xmlModule)); 76 77 module->handle = xmlModulePlatformOpen(name); 78 79 if (module->handle == NULL) { 80 xmlFree(module); 81 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 82 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 83 name, NULL, 0, 0, "failed to open %s\n", name); 84 return 0; 85 } 86 87 module->name = xmlStrdup((const xmlChar *) name); 88 return (module); 89} 90 91/** 92 * xmlModuleSymbol: 93 * @module: the module 94 * @name: the name of the symbol 95 * 96 * Lookup for a symbol address in the given module 97 * 98 * Returns the pointer to the symbol object or NULL in case of error 99 */ 100void * 101xmlModuleSymbol(xmlModulePtr module, const char *name) 102{ 103 void *symbol; 104 105 if (NULL == module) { 106 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 107 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 108 NULL, NULL, 0, 0, "null module pointer\n", 0); 109 return 0; 110 } 111 112 symbol = xmlModulePlatformSymbol(module->handle, name); 113 114 if (symbol == 0) { 115 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 116 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 117 symbol, NULL, 0, 0, 118 "failed to find symbol: %s\n", 0); 119 return 0; 120 } 121 122 return (symbol); 123} 124 125/** 126 * xmlModuleClose: 127 * @module: the module handle 128 * 129 * The close operations unload the associated module and free the 130 * data associated to the module. 131 * 132 * Returns 0 in case of success, -1 in case of argument error and -2 133 * if the module could not be closed/unloaded. 134 */ 135int 136xmlModuleClose(xmlModulePtr module) 137{ 138 int rc; 139 140 if (NULL == module) { 141 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 142 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 143 NULL, NULL, 0, 0, "null module pointer\n", 0); 144 return -1; 145 } 146 147 rc = xmlModulePlatformClose(module->handle); 148 149 if (rc != 0) { 150 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 151 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 152 (const char *) module->name, NULL, 0, 0, 153 "failed to close: %s\n", 0); 154 return -2; 155 } 156 157 rc = xmlModuleFree(module); 158 return (rc); 159} 160 161/** 162 * xmlModuleFree: 163 * @module: the module handle 164 * 165 * The free operations free the data associated to the module 166 * but does not unload the associated shared library which may still 167 * be in use. 168 * 169 * Returns 0 in case of success, -1 in case of argument error 170 */ 171int 172xmlModuleFree(xmlModulePtr module) 173{ 174 if (NULL == module) { 175 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 176 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 177 NULL, NULL, 0, 0, "null module pointer\n", 0); 178 return -1; 179 } 180 181 xmlFree(module->name); 182 xmlFree(module); 183 184 return (0); 185} 186 187#ifdef HAVE_DLOPEN 188 189#include <dlfcn.h> 190 191/** 192 * xmlModulePlatformOpen: 193 * @name: path to the module 194 * 195 * returns a handle on success, and zero on error. 196 */ 197 198static void * 199xmlModulePlatformOpen(const char *name) 200{ 201 void *handle; 202 203 handle = dlopen(name, RTLD_GLOBAL | RTLD_NOW); 204 return (handle); 205} 206 207/* 208 * xmlModulePlatformClose: 209 * @handle: handle to the module 210 * 211 * returns 0 on success, and non-zero on error. 212 */ 213 214static int 215xmlModulePlatformClose(void *handle) 216{ 217 int rc; 218 219 rc = dlclose(handle); 220 return (rc); 221} 222 223/* 224 * xmlModulePlatformSymbol: 225 * returns loaded symbol on success, and zero on error. 226 */ 227 228static void * 229xmlModulePlatformSymbol(void *handle, const char *name) 230{ 231 void *sym; 232 233 sym = dlsym(handle, name); 234 return (sym); 235} 236 237#endif /* HAVE_DLOPEN */ 238 239#ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */ 240 241/* 242 * xmlModulePlatformOpen: 243 * returns a handle on success, and zero on error. 244 */ 245 246static void * 247xmlModulePlatformOpen(const char *name) 248{ 249 void *handle; 250 251 handle = shl_load(name, BIND_IMMEDIATE, 0L); 252 return (handle); 253} 254 255/* 256 * xmlModulePlatformClose: 257 * returns 0 on success, and non-zero on error. 258 */ 259 260static int 261xmlModulePlatformClose(void *handle) 262{ 263 int rc; 264 265 rc = shl_unload(handle); 266 return (rc); 267} 268 269/* 270 * xmlModulePlatformSymbol: 271 * returns loaded symbol on success, and zero on error. 272 */ 273 274static void * 275xmlModulePlatformSymbol(void *handle, const char *name) 276{ 277 void *sym; 278 int rc; 279 280 errno = 0; 281 rc = shl_findsym(handle, name, TYPE_PROCEDURE, &sym); 282 if (-1 == rc && 0 == errno) { 283 rc = shl_findsym(handle, sym, TYPE_DATA, &sym); 284 } 285 return (sym); 286} 287 288#endif /* HAVE_SHLLOAD */ 289 290#ifdef _WIN32 291 292#include <windows.h> 293 294/* 295 * xmlModulePlatformOpen: 296 * returns a handle on success, and zero on error. 297 */ 298 299static void * 300xmlModulePlatformOpen(const char *name) 301{ 302 void *handle; 303 304 handle = LoadLibrary(name); 305 return (handle); 306} 307 308/* 309 * xmlModulePlatformClose: 310 * returns 0 on success, and non-zero on error. 311 */ 312 313static int 314xmlModulePlatformClose(void *handle) 315{ 316 int rc; 317 318 rc = FreeLibrary(handle); 319 return (0 == rc); 320} 321 322/* 323 * xmlModulePlatformSymbol: 324 * returns loaded symbol on success, and zero on error. 325 */ 326 327static void * 328xmlModulePlatformSymbol(void *handle, const char *name) 329{ 330 void *sym; 331 332 sym = GetProcAddress(handle, name); 333 return (sym); 334} 335 336#endif /* _WIN32 */ 337 338#ifdef HAVE_BEOS 339 340#include <kernel/image.h> 341 342/* 343 * xmlModulePlatformOpen: 344 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 345 * returns a handle on success, and zero on error. 346 */ 347 348static void * 349xmlModulePlatformOpen(const char *name) 350{ 351 void *handle; 352 353 handle = (void *) load_add_on(name); 354 return (handle); 355} 356 357/* 358 * xmlModulePlatformClose: 359 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 360 * returns 0 on success, and non-zero on error. 361 */ 362 363static int 364xmlModulePlatformClose(void *handle) 365{ 366 status_t rc; 367 368 rc = unload_add_on((image_id) handle); 369 370 if (rc == B_OK) 371 return 0; 372 else 373 return -1; 374} 375 376/* 377 * xmlModulePlatformSymbol: 378 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 379 * returns loaded symbol on success, and zero on error. 380 */ 381 382static void * 383xmlModulePlatformSymbol(void *handle, const char *name) 384{ 385 void *sym; 386 status_t rc; 387 388 rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, 389 &sym); 390 391 if (rc == B_OK) 392 return sym; 393 else 394 return 0; 395} 396 397#endif /* HAVE_BEOS */ 398 399#ifdef HAVE_OS2 400 401#include <os2.h> 402 403/* 404 * xmlModulePlatformOpen: 405 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html 406 * returns a handle on success, and zero on error. 407 */ 408 409static void * 410xmlModulePlatformOpen(const char *name) 411{ 412 char errbuf[255]; 413 void *handle; 414 int rc; 415 416 rc = DosLoadModule(errbuf, sizeof(errbuf), name, &handle); 417 418 if (rc) 419 return 0; 420 else 421 return (handle); 422} 423 424/* 425 * xmlModulePlatformClose: 426 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html 427 * returns 0 on success, and non-zero on error. 428 */ 429 430static int 431xmlModulePlatformClose(void *handle) 432{ 433 int rc; 434 435 rc = DosFreeModule(handle); 436 return (rc); 437} 438 439/* 440 * xmlModulePlatformSymbol: 441 * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html 442 * returns loaded symbol on success, and zero on error. 443 */ 444 445static void * 446xmlModulePlatformSymbol(void *handle, const char *name) 447{ 448 void *sym; 449 int rc; 450 451 rc = DosQueryProcAddr(handle, 0, name, &sym); 452 453 if (rc) 454 return 0; 455 else 456 return (sym); 457} 458 459#endif /* HAVE_OS2 */ 460 461#endif /* LIBXML_MODULES_ENABLED */ 462