1 /* libxml2 - Library for parsing XML documents 2 * Copyright (C) 2006-2019 Free Software Foundation, Inc. 3 * 4 * This file is not part of the GNU gettext program, but is used with 5 * GNU gettext. 6 * 7 * The original copyright notice is as follows: 8 */ 9 10 /* 11 * Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy 14 * of this software and associated documentation files (the "Software"), to deal 15 * in the Software without restriction, including without limitation the rights 16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 * copies of the Software, and to permit persons to whom the Software is fur- 18 * nished to do so, subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in 21 * all copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 25 * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 * THE SOFTWARE. 30 * 31 * joelwreed@comcast.net 32 * 33 * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html 34 */ 35 36 /* 37 * xmlmodule.c : basic API for dynamic module loading added 2.6.17 38 */ 39 40 /* In order RTLD_GLOBAL and RTLD_NOW to be defined on zOS */ 41 #if defined(__MVS__) 42 #define _UNIX03_SOURCE 43 #endif 44 45 #define IN_LIBXML 46 #include "libxml.h" 47 48 #include <string.h> 49 #include <libxml/xmlmemory.h> 50 #include <libxml/xmlerror.h> 51 #include <libxml/xmlmodule.h> 52 #include <libxml/globals.h> 53 54 #ifdef LIBXML_MODULES_ENABLED 55 56 struct _xmlModule { 57 unsigned char *name; 58 void *handle; 59 }; 60 61 static void *xmlModulePlatformOpen(const char *name); 62 static int xmlModulePlatformClose(void *handle); 63 static int xmlModulePlatformSymbol(void *handle, const char *name, void **result); 64 65 /************************************************************************ 66 * * 67 * module memory error handler * 68 * * 69 ************************************************************************/ 70 71 /** 72 * xmlModuleErrMemory: 73 * @extra: extra information 74 * 75 * Handle an out of memory condition 76 */ 77 static void xmlModuleErrMemory(xmlModulePtr module,const char * extra)78 xmlModuleErrMemory(xmlModulePtr module, const char *extra) 79 { 80 const char *name = NULL; 81 82 if (module != NULL) { 83 name = (const char *) module->name; 84 } 85 86 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 87 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, 88 name, NULL, 0, 0, 89 "Memory allocation failed : %s\n", extra); 90 } 91 92 /** 93 * xmlModuleOpen: 94 * @name: the module name 95 * @options: a set of xmlModuleOption 96 * 97 * Opens a module/shared library given its name or path 98 * NOTE: that due to portability issues, behaviour can only be 99 * guaranteed with @name using ASCII. We canot guarantee that 100 * an UTF-8 string would work, which is why name is a const char * 101 * and not a const xmlChar * . 102 * TODO: options are not yet implemented. 103 * 104 * Returns a handle for the module or NULL in case of error 105 */ 106 xmlModulePtr xmlModuleOpen(const char * name,int options ATTRIBUTE_UNUSED)107 xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED) 108 { 109 xmlModulePtr module; 110 111 module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule)); 112 if (module == NULL) { 113 xmlModuleErrMemory(NULL, "creating module"); 114 return (NULL); 115 } 116 117 memset(module, 0, sizeof(xmlModule)); 118 119 module->handle = xmlModulePlatformOpen(name); 120 121 if (module->handle == NULL) { 122 xmlFree(module); 123 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 124 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 125 name, NULL, 0, 0, "failed to open %s\n", name); 126 return(NULL); 127 } 128 129 module->name = xmlStrdup((const xmlChar *) name); 130 return (module); 131 } 132 133 /** 134 * xmlModuleSymbol: 135 * @module: the module 136 * @name: the name of the symbol 137 * @symbol: the resulting symbol address 138 * 139 * Lookup for a symbol address in the given module 140 * NOTE: that due to portability issues, behaviour can only be 141 * guaranteed with @name using ASCII. We canot guarantee that 142 * an UTF-8 string would work, which is why name is a const char * 143 * and not a const xmlChar * . 144 * 145 * Returns 0 if the symbol was found, or -1 in case of error 146 */ 147 int xmlModuleSymbol(xmlModulePtr module,const char * name,void ** symbol)148 xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol) 149 { 150 int rc = -1; 151 152 if ((NULL == module) || (symbol == NULL) || (name == NULL)) { 153 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 154 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 155 NULL, NULL, 0, 0, "null parameter\n"); 156 return rc; 157 } 158 159 rc = xmlModulePlatformSymbol(module->handle, name, symbol); 160 161 if (rc == -1) { 162 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 163 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, 164 name, NULL, 0, 0, 165 "failed to find symbol: %s\n", 166 (name == NULL ? "NULL" : name)); 167 return rc; 168 } 169 170 return rc; 171 } 172 173 /** 174 * xmlModuleClose: 175 * @module: the module handle 176 * 177 * The close operations unload the associated module and free the 178 * data associated to the module. 179 * 180 * Returns 0 in case of success, -1 in case of argument error and -2 181 * if the module could not be closed/unloaded. 182 */ 183 int xmlModuleClose(xmlModulePtr module)184 xmlModuleClose(xmlModulePtr module) 185 { 186 int rc; 187 188 if (NULL == module) { 189 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 190 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, 191 NULL, NULL, 0, 0, "null module pointer\n"); 192 return -1; 193 } 194 195 rc = xmlModulePlatformClose(module->handle); 196 197 if (rc != 0) { 198 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 199 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, 200 (const char *) module->name, NULL, 0, 0, 201 "failed to close: %s\n", module->name); 202 return -2; 203 } 204 205 rc = xmlModuleFree(module); 206 return (rc); 207 } 208 209 /** 210 * xmlModuleFree: 211 * @module: the module handle 212 * 213 * The free operations free the data associated to the module 214 * but does not unload the associated shared library which may still 215 * be in use. 216 * 217 * Returns 0 in case of success, -1 in case of argument error 218 */ 219 int xmlModuleFree(xmlModulePtr module)220 xmlModuleFree(xmlModulePtr module) 221 { 222 if (NULL == module) { 223 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, 224 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL, 225 NULL, NULL, 0, 0, "null module pointer\n"); 226 return -1; 227 } 228 229 xmlFree(module->name); 230 xmlFree(module); 231 232 return (0); 233 } 234 235 #if defined(HAVE_DLOPEN) && !defined(_WIN32) 236 #ifdef HAVE_DLFCN_H 237 #include <dlfcn.h> 238 #endif 239 240 #ifndef RTLD_GLOBAL /* For Tru64 UNIX 4.0 */ 241 #define RTLD_GLOBAL 0 242 #endif 243 244 /** 245 * xmlModulePlatformOpen: 246 * @name: path to the module 247 * 248 * returns a handle on success, and zero on error. 249 */ 250 251 static void * xmlModulePlatformOpen(const char * name)252 xmlModulePlatformOpen(const char *name) 253 { 254 return dlopen(name, RTLD_GLOBAL | RTLD_NOW); 255 } 256 257 /* 258 * xmlModulePlatformClose: 259 * @handle: handle to the module 260 * 261 * returns 0 on success, and non-zero on error. 262 */ 263 264 static int xmlModulePlatformClose(void * handle)265 xmlModulePlatformClose(void *handle) 266 { 267 return dlclose(handle); 268 } 269 270 /* 271 * xmlModulePlatformSymbol: 272 * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html 273 * returns 0 on success and the loaded symbol in result, and -1 on error. 274 */ 275 276 static int xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)277 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) 278 { 279 *symbol = dlsym(handle, name); 280 if (dlerror() != NULL) { 281 return -1; 282 } 283 return 0; 284 } 285 286 #else /* ! HAVE_DLOPEN */ 287 288 #ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */ 289 #ifdef HAVE_DL_H 290 #include <dl.h> 291 #endif 292 /* 293 * xmlModulePlatformOpen: 294 * returns a handle on success, and zero on error. 295 */ 296 297 static void * xmlModulePlatformOpen(const char * name)298 xmlModulePlatformOpen(const char *name) 299 { 300 return shl_load(name, BIND_IMMEDIATE, 0L); 301 } 302 303 /* 304 * xmlModulePlatformClose: 305 * returns 0 on success, and non-zero on error. 306 */ 307 308 static int xmlModulePlatformClose(void * handle)309 xmlModulePlatformClose(void *handle) 310 { 311 return shl_unload(handle); 312 } 313 314 /* 315 * xmlModulePlatformSymbol: 316 * http://docs.hp.com/en/B2355-90683/shl_load.3X.html 317 * returns 0 on success and the loaded symbol in result, and -1 on error. 318 */ 319 320 static int xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)321 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) 322 { 323 int rc; 324 325 errno = 0; 326 rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol); 327 return rc; 328 } 329 330 #endif /* HAVE_SHLLOAD */ 331 #endif /* ! HAVE_DLOPEN */ 332 333 #if defined(_WIN32) && !defined(__CYGWIN__) 334 335 #define WIN32_LEAN_AND_MEAN 336 #include <windows.h> 337 338 /* 339 * xmlModulePlatformOpen: 340 * returns a handle on success, and zero on error. 341 */ 342 343 static void * xmlModulePlatformOpen(const char * name)344 xmlModulePlatformOpen(const char *name) 345 { 346 return LoadLibraryA(name); 347 } 348 349 /* 350 * xmlModulePlatformClose: 351 * returns 0 on success, and non-zero on error. 352 */ 353 354 static int xmlModulePlatformClose(void * handle)355 xmlModulePlatformClose(void *handle) 356 { 357 int rc; 358 359 rc = FreeLibrary(handle); 360 return (0 == rc); 361 } 362 363 /* 364 * xmlModulePlatformSymbol: 365 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp 366 * returns 0 on success and the loaded symbol in result, and -1 on error. 367 */ 368 369 static int xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)370 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) 371 { 372 XML_IGNORE_PEDANTIC_WARNINGS 373 #ifdef _WIN32_WCE 374 /* 375 * GetProcAddressA seems only available on WinCE 376 */ 377 *symbol = GetProcAddressA(handle, name); 378 #else 379 *symbol = GetProcAddress(handle, name); 380 #endif 381 return (NULL == *symbol) ? -1 : 0; 382 XML_POP_WARNINGS 383 } 384 385 #endif /* _WIN32 */ 386 387 #ifdef HAVE_BEOS 388 389 #include <kernel/image.h> 390 391 /* 392 * xmlModulePlatformOpen: 393 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 394 * returns a handle on success, and zero on error. 395 */ 396 397 static void * xmlModulePlatformOpen(const char * name)398 xmlModulePlatformOpen(const char *name) 399 { 400 return (void *) load_add_on(name); 401 } 402 403 /* 404 * xmlModulePlatformClose: 405 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 406 * returns 0 on success, and non-zero on error. 407 */ 408 409 static int xmlModulePlatformClose(void * handle)410 xmlModulePlatformClose(void *handle) 411 { 412 status_t rc; 413 414 rc = unload_add_on((image_id) handle); 415 416 if (rc == B_OK) 417 return 0; 418 else 419 return -1; 420 } 421 422 /* 423 * xmlModulePlatformSymbol: 424 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html 425 * returns 0 on success and the loaded symbol in result, and -1 on error. 426 */ 427 428 static int xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)429 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) 430 { 431 status_t rc; 432 433 rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol); 434 435 return (rc == B_OK) ? 0 : -1; 436 } 437 438 #endif /* HAVE_BEOS */ 439 440 #ifdef HAVE_OS2 441 442 #include <os2.h> 443 444 /* 445 * xmlModulePlatformOpen: 446 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html 447 * returns a handle on success, and zero on error. 448 */ 449 450 static void * xmlModulePlatformOpen(const char * name)451 xmlModulePlatformOpen(const char *name) 452 { 453 char errbuf[256]; 454 void *handle; 455 int rc; 456 457 rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle); 458 459 if (rc) 460 return 0; 461 else 462 return (handle); 463 } 464 465 /* 466 * xmlModulePlatformClose: 467 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html 468 * returns 0 on success, and non-zero on error. 469 */ 470 471 static int xmlModulePlatformClose(void * handle)472 xmlModulePlatformClose(void *handle) 473 { 474 return DosFreeModule(handle); 475 } 476 477 /* 478 * xmlModulePlatformSymbol: 479 * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html 480 * returns 0 on success and the loaded symbol in result, and -1 on error. 481 */ 482 483 static int xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)484 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) 485 { 486 int rc; 487 488 rc = DosQueryProcAddr(handle, 0, name, symbol); 489 490 return (rc == NO_ERROR) ? 0 : -1; 491 } 492 493 #endif /* HAVE_OS2 */ 494 495 #define bottom_xmlmodule 496 #include "elfgcchack.h" 497 #endif /* LIBXML_MODULES_ENABLED */ 498