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