(root)/
libxml2-2.12.3/
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  /* 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/xmlmodule.h>
      21  #include <libxml/xmlmemory.h>
      22  #include <libxml/xmlerror.h>
      23  #include <libxml/xmlstring.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
      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
      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
     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
     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
     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 *
     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
     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
     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 *
     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
     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
     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 *
     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
     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
     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 */