1 /* libxml2 - Library for parsing XML documents
2 * Copyright (C) 2006-2019 Free Software Foundation, Inc.
3 *
4 * This file is not part of the GNU gettext program, but is used with
5 * GNU gettext.
6 *
7 * The original copyright notice is as follows:
8 */
9
10 /*
11 * Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this software and associated documentation files (the "Software"), to deal
15 * in the Software without restriction, including without limitation the rights
16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 * copies of the Software, and to permit persons to whom the Software is fur-
18 * nished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
25 * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 * THE SOFTWARE.
30 *
31 * joelwreed@comcast.net
32 *
33 * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
34 */
35
36 /*
37 * xmlmodule.c : basic API for dynamic module loading added 2.6.17
38 */
39
40 /* In order RTLD_GLOBAL and RTLD_NOW to be defined on zOS */
41 #if defined(__MVS__)
42 #define _UNIX03_SOURCE
43 #endif
44
45 #define IN_LIBXML
46 #include "libxml.h"
47
48 #include <string.h>
49 #include <libxml/xmlmemory.h>
50 #include <libxml/xmlerror.h>
51 #include <libxml/xmlmodule.h>
52 #include <libxml/globals.h>
53
54 #ifdef LIBXML_MODULES_ENABLED
55
56 struct _xmlModule {
57 unsigned char *name;
58 void *handle;
59 };
60
61 static void *xmlModulePlatformOpen(const char *name);
62 static int xmlModulePlatformClose(void *handle);
63 static int xmlModulePlatformSymbol(void *handle, const char *name, void **result);
64
65 /************************************************************************
66 * *
67 * module memory error handler *
68 * *
69 ************************************************************************/
70
71 /**
72 * xmlModuleErrMemory:
73 * @extra: extra information
74 *
75 * Handle an out of memory condition
76 */
77 static void
xmlModuleErrMemory(xmlModulePtr module,const char * extra)78 xmlModuleErrMemory(xmlModulePtr module, const char *extra)
79 {
80 const char *name = NULL;
81
82 if (module != NULL) {
83 name = (const char *) module->name;
84 }
85
86 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
87 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
88 name, NULL, 0, 0,
89 "Memory allocation failed : %s\n", extra);
90 }
91
92 /**
93 * xmlModuleOpen:
94 * @name: the module name
95 * @options: a set of xmlModuleOption
96 *
97 * Opens a module/shared library given its name or path
98 * NOTE: that due to portability issues, behaviour can only be
99 * guaranteed with @name using ASCII. We canot guarantee that
100 * an UTF-8 string would work, which is why name is a const char *
101 * and not a const xmlChar * .
102 * TODO: options are not yet implemented.
103 *
104 * Returns a handle for the module or NULL in case of error
105 */
106 xmlModulePtr
xmlModuleOpen(const char * name,int options ATTRIBUTE_UNUSED)107 xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
108 {
109 xmlModulePtr module;
110
111 module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
112 if (module == NULL) {
113 xmlModuleErrMemory(NULL, "creating module");
114 return (NULL);
115 }
116
117 memset(module, 0, sizeof(xmlModule));
118
119 module->handle = xmlModulePlatformOpen(name);
120
121 if (module->handle == NULL) {
122 xmlFree(module);
123 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
124 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
125 name, NULL, 0, 0, "failed to open %s\n", name);
126 return(NULL);
127 }
128
129 module->name = xmlStrdup((const xmlChar *) name);
130 return (module);
131 }
132
133 /**
134 * xmlModuleSymbol:
135 * @module: the module
136 * @name: the name of the symbol
137 * @symbol: the resulting symbol address
138 *
139 * Lookup for a symbol address in the given module
140 * NOTE: that due to portability issues, behaviour can only be
141 * guaranteed with @name using ASCII. We canot guarantee that
142 * an UTF-8 string would work, which is why name is a const char *
143 * and not a const xmlChar * .
144 *
145 * Returns 0 if the symbol was found, or -1 in case of error
146 */
147 int
xmlModuleSymbol(xmlModulePtr module,const char * name,void ** symbol)148 xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
149 {
150 int rc = -1;
151
152 if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
153 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
154 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
155 NULL, NULL, 0, 0, "null parameter\n");
156 return rc;
157 }
158
159 rc = xmlModulePlatformSymbol(module->handle, name, symbol);
160
161 if (rc == -1) {
162 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
163 XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
164 name, NULL, 0, 0,
165 "failed to find symbol: %s\n",
166 (name == NULL ? "NULL" : name));
167 return rc;
168 }
169
170 return rc;
171 }
172
173 /**
174 * xmlModuleClose:
175 * @module: the module handle
176 *
177 * The close operations unload the associated module and free the
178 * data associated to the module.
179 *
180 * Returns 0 in case of success, -1 in case of argument error and -2
181 * if the module could not be closed/unloaded.
182 */
183 int
xmlModuleClose(xmlModulePtr module)184 xmlModuleClose(xmlModulePtr module)
185 {
186 int rc;
187
188 if (NULL == module) {
189 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
190 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
191 NULL, NULL, 0, 0, "null module pointer\n");
192 return -1;
193 }
194
195 rc = xmlModulePlatformClose(module->handle);
196
197 if (rc != 0) {
198 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
199 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
200 (const char *) module->name, NULL, 0, 0,
201 "failed to close: %s\n", module->name);
202 return -2;
203 }
204
205 rc = xmlModuleFree(module);
206 return (rc);
207 }
208
209 /**
210 * xmlModuleFree:
211 * @module: the module handle
212 *
213 * The free operations free the data associated to the module
214 * but does not unload the associated shared library which may still
215 * be in use.
216 *
217 * Returns 0 in case of success, -1 in case of argument error
218 */
219 int
xmlModuleFree(xmlModulePtr module)220 xmlModuleFree(xmlModulePtr module)
221 {
222 if (NULL == module) {
223 __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
224 XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
225 NULL, NULL, 0, 0, "null module pointer\n");
226 return -1;
227 }
228
229 xmlFree(module->name);
230 xmlFree(module);
231
232 return (0);
233 }
234
235 #if defined(HAVE_DLOPEN) && !defined(_WIN32)
236 #ifdef HAVE_DLFCN_H
237 #include <dlfcn.h>
238 #endif
239
240 #ifndef RTLD_GLOBAL /* For Tru64 UNIX 4.0 */
241 #define RTLD_GLOBAL 0
242 #endif
243
244 /**
245 * xmlModulePlatformOpen:
246 * @name: path to the module
247 *
248 * returns a handle on success, and zero on error.
249 */
250
251 static void *
xmlModulePlatformOpen(const char * name)252 xmlModulePlatformOpen(const char *name)
253 {
254 return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
255 }
256
257 /*
258 * xmlModulePlatformClose:
259 * @handle: handle to the module
260 *
261 * returns 0 on success, and non-zero on error.
262 */
263
264 static int
xmlModulePlatformClose(void * handle)265 xmlModulePlatformClose(void *handle)
266 {
267 return dlclose(handle);
268 }
269
270 /*
271 * xmlModulePlatformSymbol:
272 * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
273 * returns 0 on success and the loaded symbol in result, and -1 on error.
274 */
275
276 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)277 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
278 {
279 *symbol = dlsym(handle, name);
280 if (dlerror() != NULL) {
281 return -1;
282 }
283 return 0;
284 }
285
286 #else /* ! HAVE_DLOPEN */
287
288 #ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */
289 #ifdef HAVE_DL_H
290 #include <dl.h>
291 #endif
292 /*
293 * xmlModulePlatformOpen:
294 * returns a handle on success, and zero on error.
295 */
296
297 static void *
xmlModulePlatformOpen(const char * name)298 xmlModulePlatformOpen(const char *name)
299 {
300 return shl_load(name, BIND_IMMEDIATE, 0L);
301 }
302
303 /*
304 * xmlModulePlatformClose:
305 * returns 0 on success, and non-zero on error.
306 */
307
308 static int
xmlModulePlatformClose(void * handle)309 xmlModulePlatformClose(void *handle)
310 {
311 return shl_unload(handle);
312 }
313
314 /*
315 * xmlModulePlatformSymbol:
316 * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
317 * returns 0 on success and the loaded symbol in result, and -1 on error.
318 */
319
320 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)321 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
322 {
323 int rc;
324
325 errno = 0;
326 rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol);
327 return rc;
328 }
329
330 #endif /* HAVE_SHLLOAD */
331 #endif /* ! HAVE_DLOPEN */
332
333 #if defined(_WIN32) && !defined(__CYGWIN__)
334
335 #define WIN32_LEAN_AND_MEAN
336 #include <windows.h>
337
338 /*
339 * xmlModulePlatformOpen:
340 * returns a handle on success, and zero on error.
341 */
342
343 static void *
xmlModulePlatformOpen(const char * name)344 xmlModulePlatformOpen(const char *name)
345 {
346 return LoadLibraryA(name);
347 }
348
349 /*
350 * xmlModulePlatformClose:
351 * returns 0 on success, and non-zero on error.
352 */
353
354 static int
xmlModulePlatformClose(void * handle)355 xmlModulePlatformClose(void *handle)
356 {
357 int rc;
358
359 rc = FreeLibrary(handle);
360 return (0 == rc);
361 }
362
363 /*
364 * xmlModulePlatformSymbol:
365 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
366 * returns 0 on success and the loaded symbol in result, and -1 on error.
367 */
368
369 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)370 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
371 {
372 XML_IGNORE_PEDANTIC_WARNINGS
373 #ifdef _WIN32_WCE
374 /*
375 * GetProcAddressA seems only available on WinCE
376 */
377 *symbol = GetProcAddressA(handle, name);
378 #else
379 *symbol = GetProcAddress(handle, name);
380 #endif
381 return (NULL == *symbol) ? -1 : 0;
382 XML_POP_WARNINGS
383 }
384
385 #endif /* _WIN32 */
386
387 #ifdef HAVE_BEOS
388
389 #include <kernel/image.h>
390
391 /*
392 * xmlModulePlatformOpen:
393 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
394 * returns a handle on success, and zero on error.
395 */
396
397 static void *
xmlModulePlatformOpen(const char * name)398 xmlModulePlatformOpen(const char *name)
399 {
400 return (void *) load_add_on(name);
401 }
402
403 /*
404 * xmlModulePlatformClose:
405 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
406 * returns 0 on success, and non-zero on error.
407 */
408
409 static int
xmlModulePlatformClose(void * handle)410 xmlModulePlatformClose(void *handle)
411 {
412 status_t rc;
413
414 rc = unload_add_on((image_id) handle);
415
416 if (rc == B_OK)
417 return 0;
418 else
419 return -1;
420 }
421
422 /*
423 * xmlModulePlatformSymbol:
424 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
425 * returns 0 on success and the loaded symbol in result, and -1 on error.
426 */
427
428 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)429 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
430 {
431 status_t rc;
432
433 rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
434
435 return (rc == B_OK) ? 0 : -1;
436 }
437
438 #endif /* HAVE_BEOS */
439
440 #ifdef HAVE_OS2
441
442 #include <os2.h>
443
444 /*
445 * xmlModulePlatformOpen:
446 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
447 * returns a handle on success, and zero on error.
448 */
449
450 static void *
xmlModulePlatformOpen(const char * name)451 xmlModulePlatformOpen(const char *name)
452 {
453 char errbuf[256];
454 void *handle;
455 int rc;
456
457 rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
458
459 if (rc)
460 return 0;
461 else
462 return (handle);
463 }
464
465 /*
466 * xmlModulePlatformClose:
467 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
468 * returns 0 on success, and non-zero on error.
469 */
470
471 static int
xmlModulePlatformClose(void * handle)472 xmlModulePlatformClose(void *handle)
473 {
474 return DosFreeModule(handle);
475 }
476
477 /*
478 * xmlModulePlatformSymbol:
479 * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
480 * returns 0 on success and the loaded symbol in result, and -1 on error.
481 */
482
483 static int
xmlModulePlatformSymbol(void * handle,const char * name,void ** symbol)484 xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
485 {
486 int rc;
487
488 rc = DosQueryProcAddr(handle, 0, name, symbol);
489
490 return (rc == NO_ERROR) ? 0 : -1;
491 }
492
493 #endif /* HAVE_OS2 */
494
495 #define bottom_xmlmodule
496 #include "elfgcchack.h"
497 #endif /* LIBXML_MODULES_ENABLED */
498