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