• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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