xmlmodule.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  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. /* In order RTLD_GLOBAL and RTLD_NOW to be defined on zOS */
  11. #if defined(__MVS__)
  12. #define _UNIX03_SOURCE
  13. #endif
  14. #define IN_LIBXML
  15. #include "libxml.h"
  16. #include <string.h>
  17. #include <libxml/xmlmemory.h>
  18. #include <libxml/xmlerror.h>
  19. #include <libxml/xmlmodule.h>
  20. #include <libxml/globals.h>
  21. #ifdef LIBXML_MODULES_ENABLED
  22. struct _xmlModule {
  23. unsigned char *name;
  24. void *handle;
  25. };
  26. static void *xmlModulePlatformOpen(const char *name);
  27. static int xmlModulePlatformClose(void *handle);
  28. static int xmlModulePlatformSymbol(void *handle, const char *name, void **result);
  29. /************************************************************************
  30. * *
  31. * module memory error handler *
  32. * *
  33. ************************************************************************/
  34. /**
  35. * xmlModuleErrMemory:
  36. * @extra: extra information
  37. *
  38. * Handle an out of memory condition
  39. */
  40. static void
  41. xmlModuleErrMemory(xmlModulePtr module, const char *extra)
  42. {
  43. const char *name = NULL;
  44. if (module != NULL) {
  45. name = (const char *) module->name;
  46. }
  47. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  48. XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
  49. name, NULL, 0, 0,
  50. "Memory allocation failed : %s\n", extra);
  51. }
  52. /**
  53. * xmlModuleOpen:
  54. * @name: the module name
  55. * @options: a set of xmlModuleOption
  56. *
  57. * Opens a module/shared library given its name or path
  58. * NOTE: that due to portability issues, behaviour can only be
  59. * guaranteed with @name using ASCII. We cannot guarantee that
  60. * an UTF-8 string would work, which is why name is a const char *
  61. * and not a const xmlChar * .
  62. * TODO: options are not yet implemented.
  63. *
  64. * Returns a handle for the module or NULL in case of error
  65. */
  66. xmlModulePtr
  67. xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
  68. {
  69. xmlModulePtr module;
  70. module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
  71. if (module == NULL) {
  72. xmlModuleErrMemory(NULL, "creating module");
  73. return (NULL);
  74. }
  75. memset(module, 0, sizeof(xmlModule));
  76. module->handle = xmlModulePlatformOpen(name);
  77. if (module->handle == NULL) {
  78. xmlFree(module);
  79. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  80. XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
  81. name, NULL, 0, 0, "failed to open %s\n", name);
  82. return(NULL);
  83. }
  84. module->name = xmlStrdup((const xmlChar *) name);
  85. return (module);
  86. }
  87. /**
  88. * xmlModuleSymbol:
  89. * @module: the module
  90. * @name: the name of the symbol
  91. * @symbol: the resulting symbol address
  92. *
  93. * Lookup for a symbol address in the given module
  94. * NOTE: that due to portability issues, behaviour can only be
  95. * guaranteed with @name using ASCII. We cannot guarantee that
  96. * an UTF-8 string would work, which is why name is a const char *
  97. * and not a const xmlChar * .
  98. *
  99. * Returns 0 if the symbol was found, or -1 in case of error
  100. */
  101. int
  102. xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
  103. {
  104. int rc = -1;
  105. if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
  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 parameter\n");
  109. return rc;
  110. }
  111. rc = xmlModulePlatformSymbol(module->handle, name, symbol);
  112. if (rc == -1) {
  113. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  114. XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
  115. name, NULL, 0, 0,
  116. "failed to find symbol: %s\n",
  117. (name == NULL ? "NULL" : name));
  118. return rc;
  119. }
  120. return rc;
  121. }
  122. /**
  123. * xmlModuleClose:
  124. * @module: the module handle
  125. *
  126. * The close operations unload the associated module and free the
  127. * data associated to the module.
  128. *
  129. * Returns 0 in case of success, -1 in case of argument error and -2
  130. * if the module could not be closed/unloaded.
  131. */
  132. int
  133. xmlModuleClose(xmlModulePtr module)
  134. {
  135. int rc;
  136. if (NULL == module) {
  137. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  138. XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
  139. NULL, NULL, 0, 0, "null module pointer\n");
  140. return -1;
  141. }
  142. rc = xmlModulePlatformClose(module->handle);
  143. if (rc != 0) {
  144. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  145. XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
  146. (const char *) module->name, NULL, 0, 0,
  147. "failed to close: %s\n", module->name);
  148. return -2;
  149. }
  150. rc = xmlModuleFree(module);
  151. return (rc);
  152. }
  153. /**
  154. * xmlModuleFree:
  155. * @module: the module handle
  156. *
  157. * The free operations free the data associated to the module
  158. * but does not unload the associated shared library which may still
  159. * be in use.
  160. *
  161. * Returns 0 in case of success, -1 in case of argument error
  162. */
  163. int
  164. xmlModuleFree(xmlModulePtr module)
  165. {
  166. if (NULL == module) {
  167. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  168. XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
  169. NULL, NULL, 0, 0, "null module pointer\n");
  170. return -1;
  171. }
  172. xmlFree(module->name);
  173. xmlFree(module);
  174. return (0);
  175. }
  176. #if defined(HAVE_DLOPEN) && !defined(_WIN32)
  177. #ifdef HAVE_DLFCN_H
  178. #include <dlfcn.h>
  179. #endif
  180. #ifndef RTLD_GLOBAL /* For Tru64 UNIX 4.0 */
  181. #define RTLD_GLOBAL 0
  182. #endif
  183. /**
  184. * xmlModulePlatformOpen:
  185. * @name: path to the module
  186. *
  187. * returns a handle on success, and zero on error.
  188. */
  189. static void *
  190. xmlModulePlatformOpen(const char *name)
  191. {
  192. return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
  193. }
  194. /*
  195. * xmlModulePlatformClose:
  196. * @handle: handle to the module
  197. *
  198. * returns 0 on success, and non-zero on error.
  199. */
  200. static int
  201. xmlModulePlatformClose(void *handle)
  202. {
  203. return dlclose(handle);
  204. }
  205. /*
  206. * xmlModulePlatformSymbol:
  207. * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
  208. * returns 0 on success and the loaded symbol in result, and -1 on error.
  209. */
  210. static int
  211. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  212. {
  213. *symbol = dlsym(handle, name);
  214. if (dlerror() != NULL) {
  215. return -1;
  216. }
  217. return 0;
  218. }
  219. #else /* ! HAVE_DLOPEN */
  220. #ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */
  221. #ifdef HAVE_DL_H
  222. #include <dl.h>
  223. #endif
  224. /*
  225. * xmlModulePlatformOpen:
  226. * returns a handle on success, and zero on error.
  227. */
  228. static void *
  229. xmlModulePlatformOpen(const char *name)
  230. {
  231. return shl_load(name, BIND_IMMEDIATE, 0L);
  232. }
  233. /*
  234. * xmlModulePlatformClose:
  235. * returns 0 on success, and non-zero on error.
  236. */
  237. static int
  238. xmlModulePlatformClose(void *handle)
  239. {
  240. return shl_unload(handle);
  241. }
  242. /*
  243. * xmlModulePlatformSymbol:
  244. * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
  245. * returns 0 on success and the loaded symbol in result, and -1 on error.
  246. */
  247. static int
  248. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  249. {
  250. int rc;
  251. errno = 0;
  252. rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol);
  253. return rc;
  254. }
  255. #endif /* HAVE_SHLLOAD */
  256. #endif /* ! HAVE_DLOPEN */
  257. #if defined(_WIN32) && !defined(__CYGWIN__)
  258. #define WIN32_LEAN_AND_MEAN
  259. #include <windows.h>
  260. /*
  261. * xmlModulePlatformOpen:
  262. * returns a handle on success, and zero on error.
  263. */
  264. static void *
  265. xmlModulePlatformOpen(const char *name)
  266. {
  267. return LoadLibraryA(name);
  268. }
  269. /*
  270. * xmlModulePlatformClose:
  271. * returns 0 on success, and non-zero on error.
  272. */
  273. static int
  274. xmlModulePlatformClose(void *handle)
  275. {
  276. int rc;
  277. rc = FreeLibrary(handle);
  278. return (0 == rc);
  279. }
  280. /*
  281. * xmlModulePlatformSymbol:
  282. * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
  283. * returns 0 on success and the loaded symbol in result, and -1 on error.
  284. */
  285. static int
  286. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  287. {
  288. XML_IGNORE_PEDANTIC_WARNINGS
  289. #ifdef _WIN32_WCE
  290. /*
  291. * GetProcAddressA seems only available on WinCE
  292. */
  293. *symbol = GetProcAddressA(handle, name);
  294. #else
  295. *symbol = GetProcAddress(handle, name);
  296. #endif
  297. return (NULL == *symbol) ? -1 : 0;
  298. XML_POP_WARNINGS
  299. }
  300. #endif /* _WIN32 */
  301. #ifdef HAVE_BEOS
  302. #include <kernel/image.h>
  303. /*
  304. * xmlModulePlatformOpen:
  305. * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
  306. * returns a handle on success, and zero on error.
  307. */
  308. static void *
  309. xmlModulePlatformOpen(const char *name)
  310. {
  311. return (void *) load_add_on(name);
  312. }
  313. /*
  314. * xmlModulePlatformClose:
  315. * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
  316. * returns 0 on success, and non-zero on error.
  317. */
  318. static int
  319. xmlModulePlatformClose(void *handle)
  320. {
  321. status_t rc;
  322. rc = unload_add_on((image_id) handle);
  323. if (rc == B_OK)
  324. return 0;
  325. else
  326. return -1;
  327. }
  328. /*
  329. * xmlModulePlatformSymbol:
  330. * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
  331. * returns 0 on success and the loaded symbol in result, and -1 on error.
  332. */
  333. static int
  334. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  335. {
  336. status_t rc;
  337. rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
  338. return (rc == B_OK) ? 0 : -1;
  339. }
  340. #endif /* HAVE_BEOS */
  341. #ifdef HAVE_OS2
  342. #include <os2.h>
  343. /*
  344. * xmlModulePlatformOpen:
  345. * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
  346. * returns a handle on success, and zero on error.
  347. */
  348. static void *
  349. xmlModulePlatformOpen(const char *name)
  350. {
  351. char errbuf[256];
  352. void *handle;
  353. int rc;
  354. rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
  355. if (rc)
  356. return 0;
  357. else
  358. return (handle);
  359. }
  360. /*
  361. * xmlModulePlatformClose:
  362. * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
  363. * returns 0 on success, and non-zero on error.
  364. */
  365. static int
  366. xmlModulePlatformClose(void *handle)
  367. {
  368. return DosFreeModule(handle);
  369. }
  370. /*
  371. * xmlModulePlatformSymbol:
  372. * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
  373. * returns 0 on success and the loaded symbol in result, and -1 on error.
  374. */
  375. static int
  376. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  377. {
  378. int rc;
  379. rc = DosQueryProcAddr(handle, 0, name, symbol);
  380. return (rc == NO_ERROR) ? 0 : -1;
  381. }
  382. #endif /* HAVE_OS2 */
  383. #define bottom_xmlmodule
  384. #include "elfgcchack.h"
  385. #endif /* LIBXML_MODULES_ENABLED */