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
      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
     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
     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
     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
     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 *
     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
     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
     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 *
     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
     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
     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 *
     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
     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
     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 *
     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
     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
     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 *
     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
     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
     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 */