• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "private/error.h"
26 
27 #ifdef LIBXML_MODULES_ENABLED
28 
29 struct _xmlModule {
30     unsigned char *name;
31     void *handle;
32 };
33 
34 static void *xmlModulePlatformOpen(const char *name);
35 static int xmlModulePlatformClose(void *handle);
36 static int xmlModulePlatformSymbol(void *handle, const char *name, void **result);
37 
38 /************************************************************************
39  *									*
40  *		module memory error handler				*
41  *									*
42  ************************************************************************/
43 
44 /**
45  * xmlModuleErrMemory:
46  * @extra:  extra information
47  *
48  * Handle an out of memory condition
49  */
50 static void
xmlModuleErrMemory(xmlModulePtr module,const char * extra)51 xmlModuleErrMemory(xmlModulePtr module, const char *extra)
52 {
53     const char *name = NULL;
54 
55     if (module != NULL) {
56         name = (const char *) module->name;
57     }
58 
59     __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
60                     XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
61                     name, NULL, 0, 0,
62                     "Memory allocation failed : %s\n", extra);
63 }
64 
65 /**
66  * xmlModuleOpen:
67  * @name: the module name
68  * @options: a set of xmlModuleOption
69  *
70  * Opens a module/shared library given its name or path
71  * NOTE: that due to portability issues, behaviour can only be
72  * guaranteed with @name using ASCII. We cannot guarantee that
73  * an UTF-8 string would work, which is why name is a const char *
74  * and not a const xmlChar * .
75  * TODO: options are not yet implemented.
76  *
77  * Returns a handle for the module or NULL in case of error
78  */
79 xmlModulePtr
xmlModuleOpen(const char * name,int options ATTRIBUTE_UNUSED)80 xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
81 {
82     xmlModulePtr module;
83 
84     module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
85     if (module == NULL) {
86         xmlModuleErrMemory(NULL, "creating module");
87         return (NULL);
88     }
89 
90     memset(module, 0, sizeof(xmlModule));
91 
92     module->handle = xmlModulePlatformOpen(name);
93 
94     if (module->handle == NULL) {
95         xmlFree(module);
96         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
97                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
98                         name, NULL, 0, 0, "failed to open %s\n", name);
99         return(NULL);
100     }
101 
102     module->name = xmlStrdup((const xmlChar *) name);
103     return (module);
104 }
105 
106 /**
107  * xmlModuleSymbol:
108  * @module: the module
109  * @name: the name of the symbol
110  * @symbol: the resulting symbol address
111  *
112  * Lookup for a symbol address in the given module
113  * NOTE: that due to portability issues, behaviour can only be
114  * guaranteed with @name using ASCII. We cannot guarantee that
115  * an UTF-8 string would work, which is why name is a const char *
116  * and not a const xmlChar * .
117  *
118  * Returns 0 if the symbol was found, or -1 in case of error
119  */
120 int
xmlModuleSymbol(xmlModulePtr module,const char * name,void ** symbol)121 xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
122 {
123     int rc = -1;
124 
125     if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
126         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
127                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
128                         NULL, NULL, 0, 0, "null parameter\n");
129         return rc;
130     }
131 
132     rc = xmlModulePlatformSymbol(module->handle, name, symbol);
133 
134     if (rc == -1) {
135         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
136                         XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
137                         name, NULL, 0, 0,
138                         "failed to find symbol: %s\n",
139 			(name == NULL ? "NULL" : name));
140         return rc;
141     }
142 
143     return rc;
144 }
145 
146 /**
147  * xmlModuleClose:
148  * @module: the module handle
149  *
150  * The close operations unload the associated module and free the
151  * data associated to the module.
152  *
153  * Returns 0 in case of success, -1 in case of argument error and -2
154  *         if the module could not be closed/unloaded.
155  */
156 int
xmlModuleClose(xmlModulePtr module)157 xmlModuleClose(xmlModulePtr module)
158 {
159     int rc;
160 
161     if (NULL == module) {
162         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
163                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
164                         NULL, NULL, 0, 0, "null module pointer\n");
165         return -1;
166     }
167 
168     rc = xmlModulePlatformClose(module->handle);
169 
170     if (rc != 0) {
171         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
172                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
173                         (const char *) module->name, NULL, 0, 0,
174                         "failed to close: %s\n", module->name);
175         return -2;
176     }
177 
178     rc = xmlModuleFree(module);
179     return (rc);
180 }
181 
182 /**
183  * xmlModuleFree:
184  * @module: the module handle
185  *
186  * The free operations free the data associated to the module
187  * but does not unload the associated shared library which may still
188  * be in use.
189  *
190  * Returns 0 in case of success, -1 in case of argument error
191  */
192 int
xmlModuleFree(xmlModulePtr module)193 xmlModuleFree(xmlModulePtr module)
194 {
195     if (NULL == module) {
196         __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
197                         XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
198                         NULL, NULL, 0, 0, "null module pointer\n");
199         return -1;
200     }
201 
202     xmlFree(module->name);
203     xmlFree(module);
204 
205     return (0);
206 }
207 
208 #if defined(HAVE_DLOPEN) && !defined(_WIN32)
209 #ifdef HAVE_DLFCN_H
210 #include <dlfcn.h>
211 #endif
212 
213 #ifndef RTLD_GLOBAL            /* For Tru64 UNIX 4.0 */
214 #define RTLD_GLOBAL 0
215 #endif
216 
217 /**
218  * xmlModulePlatformOpen:
219  * @name: path to the module
220  *
221  * returns a handle on success, and zero on error.
222  */
223 
224 static void *
xmlModulePlatformOpen(const char * name)225 xmlModulePlatformOpen(const char *name)
226 {
227     return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
228 }
229 
230 /*
231  * xmlModulePlatformClose:
232  * @handle: handle to the module
233  *
234  * returns 0 on success, and non-zero on error.
235  */
236 
237 static int
xmlModulePlatformClose(void * handle)238 xmlModulePlatformClose(void *handle)
239 {
240     return dlclose(handle);
241 }
242 
243 /*
244  * xmlModulePlatformSymbol:
245  * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
246  * returns 0 on success and the loaded symbol in result, and -1 on error.
247  */
248 
249 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)250 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
251 {
252     *symbol = dlsym(handle, name);
253     if (dlerror() != NULL) {
254 	return -1;
255     }
256     return 0;
257 }
258 
259 #else /* ! HAVE_DLOPEN */
260 
261 #ifdef HAVE_SHLLOAD             /* HAVE_SHLLOAD */
262 #ifdef HAVE_DL_H
263 #include <dl.h>
264 #endif
265 /*
266  * xmlModulePlatformOpen:
267  * returns a handle on success, and zero on error.
268  */
269 
270 static void *
xmlModulePlatformOpen(const char * name)271 xmlModulePlatformOpen(const char *name)
272 {
273     return shl_load(name, BIND_IMMEDIATE, 0L);
274 }
275 
276 /*
277  * xmlModulePlatformClose:
278  * returns 0 on success, and non-zero on error.
279  */
280 
281 static int
xmlModulePlatformClose(void * handle)282 xmlModulePlatformClose(void *handle)
283 {
284     return shl_unload(handle);
285 }
286 
287 /*
288  * xmlModulePlatformSymbol:
289  * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
290  * returns 0 on success and the loaded symbol in result, and -1 on error.
291  */
292 
293 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)294 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
295 {
296     int rc;
297 
298     errno = 0;
299     rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol);
300     return rc;
301 }
302 
303 #endif /* HAVE_SHLLOAD */
304 #endif /* ! HAVE_DLOPEN */
305 
306 #if defined(_WIN32)
307 
308 #define WIN32_LEAN_AND_MEAN
309 #include <windows.h>
310 
311 /*
312  * xmlModulePlatformOpen:
313  * returns a handle on success, and zero on error.
314  */
315 
316 static void *
xmlModulePlatformOpen(const char * name)317 xmlModulePlatformOpen(const char *name)
318 {
319     return LoadLibraryA(name);
320 }
321 
322 /*
323  * xmlModulePlatformClose:
324  * returns 0 on success, and non-zero on error.
325  */
326 
327 static int
xmlModulePlatformClose(void * handle)328 xmlModulePlatformClose(void *handle)
329 {
330     int rc;
331 
332     rc = FreeLibrary(handle);
333     return (0 == rc);
334 }
335 
336 /*
337  * xmlModulePlatformSymbol:
338  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
339  * returns 0 on success and the loaded symbol in result, and -1 on error.
340  */
341 
342 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)343 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
344 {
345 XML_IGNORE_FPTR_CAST_WARNINGS
346     *symbol = GetProcAddress(handle, name);
347     return (NULL == *symbol) ? -1 : 0;
348 XML_POP_WARNINGS
349 }
350 
351 #endif /* _WIN32 */
352 
353 #endif /* LIBXML_MODULES_ENABLED */
354