xmlmodule.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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/xmlmodule.h>
  18. #include <libxml/xmlmemory.h>
  19. #include <libxml/xmlerror.h>
  20. #include <libxml/xmlstring.h>
  21. #include "private/error.h"
  22. #ifdef LIBXML_MODULES_ENABLED
  23. struct _xmlModule {
  24. unsigned char *name;
  25. void *handle;
  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. * module memory error handler *
  33. * *
  34. ************************************************************************/
  35. /**
  36. * xmlModuleErrMemory:
  37. * @extra: extra information
  38. *
  39. * Handle an out of memory condition
  40. */
  41. static void
  42. xmlModuleErrMemory(xmlModulePtr module, const char *extra)
  43. {
  44. const char *name = NULL;
  45. if (module != NULL) {
  46. name = (const char *) module->name;
  47. }
  48. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  49. XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
  50. name, NULL, 0, 0,
  51. "Memory allocation failed : %s\n", extra);
  52. }
  53. /**
  54. * xmlModuleOpen:
  55. * @name: the module name
  56. * @options: a set of xmlModuleOption
  57. *
  58. * Opens a module/shared library given its name or path
  59. * NOTE: that due to portability issues, behaviour can only be
  60. * guaranteed with @name using ASCII. We cannot guarantee that
  61. * an UTF-8 string would work, which is why name is a const char *
  62. * and not a const xmlChar * .
  63. * TODO: options are not yet implemented.
  64. *
  65. * Returns a handle for the module or NULL in case of error
  66. */
  67. xmlModulePtr
  68. xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
  69. {
  70. xmlModulePtr module;
  71. module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
  72. if (module == NULL) {
  73. xmlModuleErrMemory(NULL, "creating module");
  74. return (NULL);
  75. }
  76. memset(module, 0, sizeof(xmlModule));
  77. module->handle = xmlModulePlatformOpen(name);
  78. if (module->handle == NULL) {
  79. xmlFree(module);
  80. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  81. XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
  82. name, NULL, 0, 0, "failed to open %s\n", name);
  83. return(NULL);
  84. }
  85. module->name = xmlStrdup((const xmlChar *) name);
  86. return (module);
  87. }
  88. /**
  89. * xmlModuleSymbol:
  90. * @module: the module
  91. * @name: the name of the symbol
  92. * @symbol: the resulting symbol address
  93. *
  94. * Lookup for a symbol address in the given module
  95. * NOTE: that due to portability issues, behaviour can only be
  96. * guaranteed with @name using ASCII. We cannot guarantee that
  97. * an UTF-8 string would work, which is why name is a const char *
  98. * and not a const xmlChar * .
  99. *
  100. * Returns 0 if the symbol was found, or -1 in case of error
  101. */
  102. int
  103. xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
  104. {
  105. int rc = -1;
  106. if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
  107. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  108. XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
  109. NULL, NULL, 0, 0, "null parameter\n");
  110. return rc;
  111. }
  112. rc = xmlModulePlatformSymbol(module->handle, name, symbol);
  113. if (rc == -1) {
  114. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  115. XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
  116. name, NULL, 0, 0,
  117. "failed to find symbol: %s\n",
  118. (name == NULL ? "NULL" : name));
  119. return rc;
  120. }
  121. return rc;
  122. }
  123. /**
  124. * xmlModuleClose:
  125. * @module: the module handle
  126. *
  127. * The close operations unload the associated module and free the
  128. * data associated to the module.
  129. *
  130. * Returns 0 in case of success, -1 in case of argument error and -2
  131. * if the module could not be closed/unloaded.
  132. */
  133. int
  134. xmlModuleClose(xmlModulePtr module)
  135. {
  136. int rc;
  137. if (NULL == module) {
  138. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  139. XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
  140. NULL, NULL, 0, 0, "null module pointer\n");
  141. return -1;
  142. }
  143. rc = xmlModulePlatformClose(module->handle);
  144. if (rc != 0) {
  145. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  146. XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
  147. (const char *) module->name, NULL, 0, 0,
  148. "failed to close: %s\n", module->name);
  149. return -2;
  150. }
  151. rc = xmlModuleFree(module);
  152. return (rc);
  153. }
  154. /**
  155. * xmlModuleFree:
  156. * @module: the module handle
  157. *
  158. * The free operations free the data associated to the module
  159. * but does not unload the associated shared library which may still
  160. * be in use.
  161. *
  162. * Returns 0 in case of success, -1 in case of argument error
  163. */
  164. int
  165. xmlModuleFree(xmlModulePtr module)
  166. {
  167. if (NULL == module) {
  168. __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
  169. XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
  170. NULL, NULL, 0, 0, "null module pointer\n");
  171. return -1;
  172. }
  173. xmlFree(module->name);
  174. xmlFree(module);
  175. return (0);
  176. }
  177. #if defined(HAVE_DLOPEN) && !defined(_WIN32)
  178. #ifdef HAVE_DLFCN_H
  179. #include <dlfcn.h>
  180. #endif
  181. #ifndef RTLD_GLOBAL /* For Tru64 UNIX 4.0 */
  182. #define RTLD_GLOBAL 0
  183. #endif
  184. /**
  185. * xmlModulePlatformOpen:
  186. * @name: path to the module
  187. *
  188. * returns a handle on success, and zero on error.
  189. */
  190. static void *
  191. xmlModulePlatformOpen(const char *name)
  192. {
  193. return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
  194. }
  195. /*
  196. * xmlModulePlatformClose:
  197. * @handle: handle to the module
  198. *
  199. * returns 0 on success, and non-zero on error.
  200. */
  201. static int
  202. xmlModulePlatformClose(void *handle)
  203. {
  204. return dlclose(handle);
  205. }
  206. /*
  207. * xmlModulePlatformSymbol:
  208. * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
  209. * returns 0 on success and the loaded symbol in result, and -1 on error.
  210. */
  211. static int
  212. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  213. {
  214. *symbol = dlsym(handle, name);
  215. if (dlerror() != NULL) {
  216. return -1;
  217. }
  218. return 0;
  219. }
  220. #else /* ! HAVE_DLOPEN */
  221. #ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */
  222. #ifdef HAVE_DL_H
  223. #include <dl.h>
  224. #endif
  225. /*
  226. * xmlModulePlatformOpen:
  227. * returns a handle on success, and zero on error.
  228. */
  229. static void *
  230. xmlModulePlatformOpen(const char *name)
  231. {
  232. return shl_load(name, BIND_IMMEDIATE, 0L);
  233. }
  234. /*
  235. * xmlModulePlatformClose:
  236. * returns 0 on success, and non-zero on error.
  237. */
  238. static int
  239. xmlModulePlatformClose(void *handle)
  240. {
  241. return shl_unload(handle);
  242. }
  243. /*
  244. * xmlModulePlatformSymbol:
  245. * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
  246. * returns 0 on success and the loaded symbol in result, and -1 on error.
  247. */
  248. static int
  249. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  250. {
  251. int rc;
  252. errno = 0;
  253. rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol);
  254. return rc;
  255. }
  256. #endif /* HAVE_SHLLOAD */
  257. #endif /* ! HAVE_DLOPEN */
  258. #if defined(_WIN32)
  259. #define WIN32_LEAN_AND_MEAN
  260. #include <windows.h>
  261. /*
  262. * xmlModulePlatformOpen:
  263. * returns a handle on success, and zero on error.
  264. */
  265. static void *
  266. xmlModulePlatformOpen(const char *name)
  267. {
  268. return LoadLibraryA(name);
  269. }
  270. /*
  271. * xmlModulePlatformClose:
  272. * returns 0 on success, and non-zero on error.
  273. */
  274. static int
  275. xmlModulePlatformClose(void *handle)
  276. {
  277. int rc;
  278. rc = FreeLibrary(handle);
  279. return (0 == rc);
  280. }
  281. /*
  282. * xmlModulePlatformSymbol:
  283. * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
  284. * returns 0 on success and the loaded symbol in result, and -1 on error.
  285. */
  286. static int
  287. xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
  288. {
  289. XML_IGNORE_FPTR_CAST_WARNINGS
  290. *symbol = GetProcAddress(handle, name);
  291. return (NULL == *symbol) ? -1 : 0;
  292. XML_POP_WARNINGS
  293. }
  294. #endif /* _WIN32 */
  295. #endif /* LIBXML_MODULES_ENABLED */