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