blob: e1c351a96596ff459e93b83c781a42ccad9b3ae7 [file] [log] [blame]
Daniel Veillardce1648b2005-01-04 15:10:22 +00001/*
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00002 * xmlmodule.c : basic API for dynamic module loading added 2.6.17
Daniel Veillardce1648b2005-01-04 15:10:22 +00003 *
4 * See Copyright for the status of this software.
5 *
6 * joelwreed@comcast.net
Daniel Veillardbe076e92005-01-04 20:18:14 +00007 *
8 * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
Daniel Veillardce1648b2005-01-04 15:10:22 +00009 */
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
22struct _xmlModule {
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000023 unsigned char *name;
24 void *handle;
Daniel Veillardce1648b2005-01-04 15:10:22 +000025};
26
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000027static void *xmlModulePlatformOpen(const char *name);
28static int xmlModulePlatformClose(void *handle);
Daniel Veillardbe076e92005-01-04 20:18:14 +000029static int xmlModulePlatformSymbol(void *handle, const char *name, void **result);
Daniel Veillardce1648b2005-01-04 15:10:22 +000030
31/************************************************************************
32 * *
33 * module memory error handler *
34 * *
35 ************************************************************************/
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000036
Daniel Veillardce1648b2005-01-04 15:10:22 +000037/**
38 * xmlModuleErrMemory:
39 * @extra: extra information
40 *
41 * Handle an out of memory condition
42 */
43static void
44xmlModuleErrMemory(xmlModulePtr module, const char *extra)
45{
46 const char *name = NULL;
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000047
Daniel Veillardce1648b2005-01-04 15:10:22 +000048 if (module != NULL) {
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000049 name = (const char *) module->name;
Daniel Veillardce1648b2005-01-04 15:10:22 +000050 }
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
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000058/**
59 * xmlModuleOpen:
60 * @name: the module name
61 *
62 * Opens a module/shared library given its name or path
63 *
64 * Returns a handle for the module or NULL in case of error
65 */
66xmlModulePtr
67xmlModuleOpen(const char *name)
Daniel Veillardce1648b2005-01-04 15:10:22 +000068{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000069 xmlModulePtr module;
Daniel Veillardce1648b2005-01-04 15:10:22 +000070
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000071 module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
72 if (module == NULL) {
73 xmlModuleErrMemory(NULL, "creating module");
74 return (NULL);
75 }
Daniel Veillardce1648b2005-01-04 15:10:22 +000076
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000077 memset(module, 0, sizeof(xmlModule));
Daniel Veillardce1648b2005-01-04 15:10:22 +000078
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000079 module->handle = xmlModulePlatformOpen(name);
Daniel Veillardce1648b2005-01-04 15:10:22 +000080
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000081 if (module->handle == NULL) {
82 xmlFree(module);
83 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
84 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
85 name, NULL, 0, 0, "failed to open %s\n", name);
86 return 0;
87 }
88
89 module->name = xmlStrdup((const xmlChar *) name);
90 return (module);
91}
92
93/**
94 * xmlModuleSymbol:
95 * @module: the module
96 * @name: the name of the symbol
Daniel Veillardbe076e92005-01-04 20:18:14 +000097 * @symbol: the resulting symbol address
Daniel Veillardf6b71bd2005-01-04 17:50:14 +000098 *
99 * Lookup for a symbol address in the given module
100 *
Daniel Veillardbe076e92005-01-04 20:18:14 +0000101 * Returns 0 if the symbol was found, or -1 in case of error
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000102 */
Daniel Veillardbe076e92005-01-04 20:18:14 +0000103int
104xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000105{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000106 int rc = -1;
107
108 if ((NULL == module) || (symbol == NULL)) {
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000109 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
110 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
Daniel Veillardbe076e92005-01-04 20:18:14 +0000111 NULL, NULL, 0, 0, "null parameter\n");
112 return rc;
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000113 }
114
Daniel Veillardbe076e92005-01-04 20:18:14 +0000115 rc = xmlModulePlatformSymbol(module->handle, name, symbol);
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000116
Daniel Veillardbe076e92005-01-04 20:18:14 +0000117 if (rc == -1) {
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000118 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
119 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
Daniel Veillardbe076e92005-01-04 20:18:14 +0000120 name, NULL, 0, 0,
121 "failed to find symbol: %s\n",
122 (name == NULL ? "NULL" : name));
123 return rc;
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000124 }
125
Daniel Veillardbe076e92005-01-04 20:18:14 +0000126 return rc;
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000127}
128
129/**
130 * xmlModuleClose:
131 * @module: the module handle
132 *
133 * The close operations unload the associated module and free the
134 * data associated to the module.
135 *
136 * Returns 0 in case of success, -1 in case of argument error and -2
137 * if the module could not be closed/unloaded.
138 */
139int
140xmlModuleClose(xmlModulePtr module)
141{
142 int rc;
143
144 if (NULL == module) {
145 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Daniel Veillardbe076e92005-01-04 20:18:14 +0000146 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
147 NULL, NULL, 0, 0, "null module pointer\n");
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000148 return -1;
149 }
150
151 rc = xmlModulePlatformClose(module->handle);
152
153 if (rc != 0) {
154 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Daniel Veillardbe076e92005-01-04 20:18:14 +0000155 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000156 (const char *) module->name, NULL, 0, 0,
Daniel Veillardbe076e92005-01-04 20:18:14 +0000157 "failed to close: %s\n", module->name);
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000158 return -2;
159 }
160
161 rc = xmlModuleFree(module);
162 return (rc);
163}
164
165/**
166 * xmlModuleFree:
167 * @module: the module handle
168 *
169 * The free operations free the data associated to the module
170 * but does not unload the associated shared library which may still
171 * be in use.
172 *
173 * Returns 0 in case of success, -1 in case of argument error
174 */
175int
176xmlModuleFree(xmlModulePtr module)
177{
178 if (NULL == module) {
179 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Daniel Veillardbe076e92005-01-04 20:18:14 +0000180 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
181 NULL, NULL, 0, 0, "null module pointer\n");
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000182 return -1;
183 }
184
185 xmlFree(module->name);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000186 xmlFree(module);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000187
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000188 return (0);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000189}
190
191#ifdef HAVE_DLOPEN
192
193#include <dlfcn.h>
194
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000195/**
Daniel Veillardce1648b2005-01-04 15:10:22 +0000196 * xmlModulePlatformOpen:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000197 * @name: path to the module
198 *
Daniel Veillardce1648b2005-01-04 15:10:22 +0000199 * returns a handle on success, and zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000200 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000201
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000202static void *
203xmlModulePlatformOpen(const char *name)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000204{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000205 return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000206}
207
208/*
209 * xmlModulePlatformClose:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000210 * @handle: handle to the module
211 *
Daniel Veillardce1648b2005-01-04 15:10:22 +0000212 * returns 0 on success, and non-zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000213 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000214
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000215static int
216xmlModulePlatformClose(void *handle)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000217{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000218 return dlclose(handle);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000219}
220
221/*
222 * xmlModulePlatformSymbol:
Daniel Veillardbe076e92005-01-04 20:18:14 +0000223 * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
224 * returns 0 on success and the loaded symbol in result, and -1 on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000225 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000226
Daniel Veillardbe076e92005-01-04 20:18:14 +0000227static int
228xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000229{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000230 *symbol = dlsym(handle, name);
231 if (dlerror() != NULL) {
232 return -1;
233 }
234 return 0;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000235}
236
237#endif /* HAVE_DLOPEN */
238
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000239#ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000240
241/*
242 * xmlModulePlatformOpen:
243 * returns a handle on success, and zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000244 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000245
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000246static void *
247xmlModulePlatformOpen(const char *name)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000248{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000249 return shl_load(name, BIND_IMMEDIATE, 0L);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000250}
251
252/*
253 * xmlModulePlatformClose:
254 * returns 0 on success, and non-zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000255 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000256
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000257static int
258xmlModulePlatformClose(void *handle)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000259{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000260 return shl_unload(handle);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000261}
262
263/*
264 * xmlModulePlatformSymbol:
Daniel Veillardbe076e92005-01-04 20:18:14 +0000265 * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
266 * returns 0 on success and the loaded symbol in result, and -1 on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000267 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000268
Daniel Veillardbe076e92005-01-04 20:18:14 +0000269static int
270xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000271{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000272 int rc;
273
274 errno = 0;
Daniel Veillardbe076e92005-01-04 20:18:14 +0000275 rc = shl_findsym(handle, name, TYPE_PROCEDURE, symbol);
276 if ((-1 == rc) && (0 == errno)) {
277 rc = shl_findsym(handle, name, TYPE_DATA, symbol);
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000278 }
Daniel Veillardbe076e92005-01-04 20:18:14 +0000279 return rc;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000280}
281
282#endif /* HAVE_SHLLOAD */
283
284#ifdef _WIN32
285
286#include <windows.h>
287
288/*
289 * xmlModulePlatformOpen:
290 * returns a handle on success, and zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000291 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000292
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000293static void *
294xmlModulePlatformOpen(const char *name)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000295{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000296 return LoadLibrary(name);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000297}
298
299/*
300 * xmlModulePlatformClose:
301 * returns 0 on success, and non-zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000302 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000303
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000304static int
305xmlModulePlatformClose(void *handle)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000306{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000307 int rc;
308
309 rc = FreeLibrary(handle);
310 return (0 == rc);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000311}
312
313/*
314 * xmlModulePlatformSymbol:
Daniel Veillardbe076e92005-01-04 20:18:14 +0000315 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
316 * returns 0 on success and the loaded symbol in result, and -1 on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000317 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000318
Daniel Veillardbe076e92005-01-04 20:18:14 +0000319static int
320xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000321{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000322 *symbol = GetProcAddress(handle, name);
323 return (NULL == *symbol) ? -1 : 0;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000324}
325
326#endif /* _WIN32 */
327
328#ifdef HAVE_BEOS
329
330#include <kernel/image.h>
331
332/*
333 * xmlModulePlatformOpen:
334 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
335 * returns a handle on success, and zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000336 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000337
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000338static void *
339xmlModulePlatformOpen(const char *name)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000340{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000341 return (void *) load_add_on(name);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000342}
343
344/*
345 * xmlModulePlatformClose:
346 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
347 * returns 0 on success, and non-zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000348 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000349
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000350static int
351xmlModulePlatformClose(void *handle)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000352{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000353 status_t rc;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000354
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000355 rc = unload_add_on((image_id) handle);
356
357 if (rc == B_OK)
358 return 0;
359 else
360 return -1;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000361}
362
363/*
364 * xmlModulePlatformSymbol:
365 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
Daniel Veillardbe076e92005-01-04 20:18:14 +0000366 * returns 0 on success and the loaded symbol in result, and -1 on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000367 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000368
Daniel Veillardbe076e92005-01-04 20:18:14 +0000369static int
370xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000371{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000372 status_t rc;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000373
Daniel Veillardbe076e92005-01-04 20:18:14 +0000374 rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000375
Daniel Veillardbe076e92005-01-04 20:18:14 +0000376 return (rc == B_OK) ? 0 : -1;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000377}
378
379#endif /* HAVE_BEOS */
380
381#ifdef HAVE_OS2
382
383#include <os2.h>
384
385/*
386 * xmlModulePlatformOpen:
387 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
388 * returns a handle on success, and zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000389 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000390
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000391static void *
392xmlModulePlatformOpen(const char *name)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000393{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000394 char errbuf[256];
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000395 void *handle;
396 int rc;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000397
Daniel Veillardbe076e92005-01-04 20:18:14 +0000398 rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000399
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000400 if (rc)
401 return 0;
402 else
403 return (handle);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000404}
405
406/*
407 * xmlModulePlatformClose:
408 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
409 * returns 0 on success, and non-zero on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000410 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000411
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000412static int
413xmlModulePlatformClose(void *handle)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000414{
Daniel Veillardbe076e92005-01-04 20:18:14 +0000415 return DosFreeModule(handle);
Daniel Veillardce1648b2005-01-04 15:10:22 +0000416}
417
418/*
419 * xmlModulePlatformSymbol:
420 * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
Daniel Veillardbe076e92005-01-04 20:18:14 +0000421 * returns 0 on success and the loaded symbol in result, and -1 on error.
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000422 */
Daniel Veillardce1648b2005-01-04 15:10:22 +0000423
Daniel Veillardbe076e92005-01-04 20:18:14 +0000424static int
425xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Daniel Veillardce1648b2005-01-04 15:10:22 +0000426{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000427 int rc;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000428
Daniel Veillardbe076e92005-01-04 20:18:14 +0000429 rc = DosQueryProcAddr(handle, 0, name, symbol);
Daniel Veillardf6b71bd2005-01-04 17:50:14 +0000430
Daniel Veillardbe076e92005-01-04 20:18:14 +0000431 return (rc == NO_ERROR) ? 0 : -1;
Daniel Veillardce1648b2005-01-04 15:10:22 +0000432}
433
434#endif /* HAVE_OS2 */
435
436#endif /* LIBXML_MODULES_ENABLED */