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