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
xmlModuleErrMemory(xmlModulePtr module,const char * extra)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
xmlModuleOpen(const char * name,int options ATTRIBUTE_UNUSED)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
xmlModuleSymbol(xmlModulePtr module,const char * name,void ** symbol)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
xmlModuleClose(xmlModulePtr module)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
xmlModuleFree(xmlModulePtr module)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 *
xmlModulePlatformOpen(const char * name)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
xmlModulePlatformClose(void * handle)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
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)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 *
xmlModulePlatformOpen(const char * name)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
xmlModulePlatformClose(void * handle)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
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)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 *
xmlModulePlatformOpen(const char * name)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
xmlModulePlatformClose(void * handle)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
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)341 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
342 {
343 XML_IGNORE_PEDANTIC_WARNINGS
344 #ifdef _WIN32_WCE
345 /*
346 * GetProcAddressA seems only available on WinCE
347 */
348 *symbol = GetProcAddressA(handle, name);
349 #else
350 *symbol = GetProcAddress(handle, name);
351 #endif
352 return (NULL == *symbol) ? -1 : 0;
353 XML_POP_WARNINGS
354 }
355
356 #endif /* _WIN32 */
357
358 #ifdef HAVE_BEOS
359
360 #include <kernel/image.h>
361
362 /*
363 * xmlModulePlatformOpen:
364 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
365 * returns a handle on success, and zero on error.
366 */
367
368 static void *
xmlModulePlatformOpen(const char * name)369 xmlModulePlatformOpen(const char *name)
370 {
371 return (void *) load_add_on(name);
372 }
373
374 /*
375 * xmlModulePlatformClose:
376 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
377 * returns 0 on success, and non-zero on error.
378 */
379
380 static int
xmlModulePlatformClose(void * handle)381 xmlModulePlatformClose(void *handle)
382 {
383 status_t rc;
384
385 rc = unload_add_on((image_id) handle);
386
387 if (rc == B_OK)
388 return 0;
389 else
390 return -1;
391 }
392
393 /*
394 * xmlModulePlatformSymbol:
395 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
396 * returns 0 on success and the loaded symbol in result, and -1 on error.
397 */
398
399 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)400 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
401 {
402 status_t rc;
403
404 rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
405
406 return (rc == B_OK) ? 0 : -1;
407 }
408
409 #endif /* HAVE_BEOS */
410
411 #ifdef HAVE_OS2
412
413 #include <os2.h>
414
415 /*
416 * xmlModulePlatformOpen:
417 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
418 * returns a handle on success, and zero on error.
419 */
420
421 static void *
xmlModulePlatformOpen(const char * name)422 xmlModulePlatformOpen(const char *name)
423 {
424 char errbuf[256];
425 void *handle;
426 int rc;
427
428 rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
429
430 if (rc)
431 return 0;
432 else
433 return (handle);
434 }
435
436 /*
437 * xmlModulePlatformClose:
438 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
439 * returns 0 on success, and non-zero on error.
440 */
441
442 static int
xmlModulePlatformClose(void * handle)443 xmlModulePlatformClose(void *handle)
444 {
445 return DosFreeModule(handle);
446 }
447
448 /*
449 * xmlModulePlatformSymbol:
450 * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
451 * returns 0 on success and the loaded symbol in result, and -1 on error.
452 */
453
454 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)455 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
456 {
457 int rc;
458
459 rc = DosQueryProcAddr(handle, 0, name, symbol);
460
461 return (rc == NO_ERROR) ? 0 : -1;
462 }
463
464 #endif /* HAVE_OS2 */
465
466 #define bottom_xmlmodule
467 #include "elfgcchack.h"
468 #endif /* LIBXML_MODULES_ENABLED */
469