Blame xmlmodule.c

Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlmodule.c : basic API for dynamic module loading added 2.6.17
Packit Service a31ea6
 *
Packit Service a31ea6
 * See Copyright for the status of this software.
Packit Service a31ea6
 *
Packit Service a31ea6
 * joelwreed@comcast.net
Packit Service a31ea6
 *
Packit Service a31ea6
 * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
/* In order RTLD_GLOBAL and RTLD_NOW to be defined on zOS */
Packit Service a31ea6
#if defined(__MVS__)
Packit Service a31ea6
#define _UNIX03_SOURCE
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
#define IN_LIBXML
Packit Service a31ea6
#include "libxml.h"
Packit Service a31ea6
Packit Service a31ea6
#include <string.h>
Packit Service a31ea6
#include <libxml/xmlmemory.h>
Packit Service a31ea6
#include <libxml/xmlerror.h>
Packit Service a31ea6
#include <libxml/xmlmodule.h>
Packit Service a31ea6
#include <libxml/globals.h>
Packit Service a31ea6
Packit Service a31ea6
#ifdef LIBXML_MODULES_ENABLED
Packit Service a31ea6
Packit Service a31ea6
struct _xmlModule {
Packit Service a31ea6
    unsigned char *name;
Packit Service a31ea6
    void *handle;
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
static void *xmlModulePlatformOpen(const char *name);
Packit Service a31ea6
static int xmlModulePlatformClose(void *handle);
Packit Service a31ea6
static int xmlModulePlatformSymbol(void *handle, const char *name, void **result);
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *		module memory error handler				*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlModuleErrMemory:
Packit Service a31ea6
 * @extra:  extra information
Packit Service a31ea6
 *
Packit Service a31ea6
 * Handle an out of memory condition
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlModuleErrMemory(xmlModulePtr module, const char *extra)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *name = NULL;
Packit Service a31ea6
Packit Service a31ea6
    if (module != NULL) {
Packit Service a31ea6
        name = (const char *) module->name;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Packit Service a31ea6
                    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
Packit Service a31ea6
                    name, NULL, 0, 0,
Packit Service a31ea6
                    "Memory allocation failed : %s\n", extra);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlModuleOpen:
Packit Service a31ea6
 * @name: the module name
Packit Service a31ea6
 * @options: a set of xmlModuleOption
Packit Service a31ea6
 *
Packit Service a31ea6
 * Opens a module/shared library given its name or path
Packit Service a31ea6
 * NOTE: that due to portability issues, behaviour can only be
Packit Service a31ea6
 * guaranteed with @name using ASCII. We canot guarantee that
Packit Service a31ea6
 * an UTF-8 string would work, which is why name is a const char *
Packit Service a31ea6
 * and not a const xmlChar * .
Packit Service a31ea6
 * TODO: options are not yet implemented.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a handle for the module or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlModulePtr
Packit Service a31ea6
xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlModulePtr module;
Packit Service a31ea6
Packit Service a31ea6
    module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
Packit Service a31ea6
    if (module == NULL) {
Packit Service a31ea6
        xmlModuleErrMemory(NULL, "creating module");
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    memset(module, 0, sizeof(xmlModule));
Packit Service a31ea6
Packit Service a31ea6
    module->handle = xmlModulePlatformOpen(name);
Packit Service a31ea6
Packit Service a31ea6
    if (module->handle == NULL) {
Packit Service a31ea6
        xmlFree(module);
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Packit Service a31ea6
                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
Packit Service a31ea6
                        name, NULL, 0, 0, "failed to open %s\n", name);
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    module->name = xmlStrdup((const xmlChar *) name);
Packit Service a31ea6
    return (module);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlModuleSymbol:
Packit Service a31ea6
 * @module: the module
Packit Service a31ea6
 * @name: the name of the symbol
Packit Service a31ea6
 * @symbol: the resulting symbol address
Packit Service a31ea6
 *
Packit Service a31ea6
 * Lookup for a symbol address in the given module
Packit Service a31ea6
 * NOTE: that due to portability issues, behaviour can only be
Packit Service a31ea6
 * guaranteed with @name using ASCII. We canot guarantee that
Packit Service a31ea6
 * an UTF-8 string would work, which is why name is a const char *
Packit Service a31ea6
 * and not a const xmlChar * .
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 if the symbol was found, or -1 in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
Packit Service a31ea6
{
Packit Service a31ea6
    int rc = -1;
Packit Service a31ea6
Packit Service a31ea6
    if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Packit Service a31ea6
                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
Packit Service a31ea6
                        NULL, NULL, 0, 0, "null parameter\n");
Packit Service a31ea6
        return rc;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    rc = xmlModulePlatformSymbol(module->handle, name, symbol);
Packit Service a31ea6
Packit Service a31ea6
    if (rc == -1) {
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Packit Service a31ea6
                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
Packit Service a31ea6
                        name, NULL, 0, 0,
Packit Service a31ea6
                        "failed to find symbol: %s\n",
Packit Service a31ea6
			(name == NULL ? "NULL" : name));
Packit Service a31ea6
        return rc;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    return rc;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlModuleClose:
Packit Service a31ea6
 * @module: the module handle
Packit Service a31ea6
 *
Packit Service a31ea6
 * The close operations unload the associated module and free the
Packit Service a31ea6
 * data associated to the module.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 in case of success, -1 in case of argument error and -2
Packit Service a31ea6
 *         if the module could not be closed/unloaded.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlModuleClose(xmlModulePtr module)
Packit Service a31ea6
{
Packit Service a31ea6
    int rc;
Packit Service a31ea6
Packit Service a31ea6
    if (NULL == module) {
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Packit Service a31ea6
                        XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
Packit Service a31ea6
                        NULL, NULL, 0, 0, "null module pointer\n");
Packit Service a31ea6
        return -1;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    rc = xmlModulePlatformClose(module->handle);
Packit Service a31ea6
Packit Service a31ea6
    if (rc != 0) {
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Packit Service a31ea6
                        XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
Packit Service a31ea6
                        (const char *) module->name, NULL, 0, 0,
Packit Service a31ea6
                        "failed to close: %s\n", module->name);
Packit Service a31ea6
        return -2;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    rc = xmlModuleFree(module);
Packit Service a31ea6
    return (rc);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlModuleFree:
Packit Service a31ea6
 * @module: the module handle
Packit Service a31ea6
 *
Packit Service a31ea6
 * The free operations free the data associated to the module
Packit Service a31ea6
 * but does not unload the associated shared library which may still
Packit Service a31ea6
 * be in use.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 in case of success, -1 in case of argument error
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlModuleFree(xmlModulePtr module)
Packit Service a31ea6
{
Packit Service a31ea6
    if (NULL == module) {
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
Packit Service a31ea6
                        XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL,
Packit Service a31ea6
                        NULL, NULL, 0, 0, "null module pointer\n");
Packit Service a31ea6
        return -1;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    xmlFree(module->name);
Packit Service a31ea6
    xmlFree(module);
Packit Service a31ea6
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#if defined(HAVE_DLOPEN) && !defined(_WIN32)
Packit Service a31ea6
#ifdef HAVE_DLFCN_H
Packit Service a31ea6
#include <dlfcn.h>
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
#ifndef RTLD_GLOBAL            /* For Tru64 UNIX 4.0 */
Packit Service a31ea6
#define RTLD_GLOBAL 0
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlModulePlatformOpen:
Packit Service a31ea6
 * @name: path to the module
Packit Service a31ea6
 *
Packit Service a31ea6
 * returns a handle on success, and zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static void *
Packit Service a31ea6
xmlModulePlatformOpen(const char *name)
Packit Service a31ea6
{
Packit Service a31ea6
    return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformClose:
Packit Service a31ea6
 * @handle: handle to the module
Packit Service a31ea6
 *
Packit Service a31ea6
 * returns 0 on success, and non-zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformClose(void *handle)
Packit Service a31ea6
{
Packit Service a31ea6
    return dlclose(handle);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformSymbol:
Packit Service a31ea6
 * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
Packit Service a31ea6
 * returns 0 on success and the loaded symbol in result, and -1 on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Packit Service a31ea6
{
Packit Service a31ea6
    *symbol = dlsym(handle, name);
Packit Service a31ea6
    if (dlerror() != NULL) {
Packit Service a31ea6
	return -1;
Packit Service a31ea6
    }
Packit Service a31ea6
    return 0;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#else /* ! HAVE_DLOPEN */
Packit Service a31ea6
Packit Service a31ea6
#ifdef HAVE_SHLLOAD             /* HAVE_SHLLOAD */
Packit Service a31ea6
#ifdef HAVE_DL_H
Packit Service a31ea6
#include <dl.h>
Packit Service a31ea6
#endif
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformOpen:
Packit Service a31ea6
 * returns a handle on success, and zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static void *
Packit Service a31ea6
xmlModulePlatformOpen(const char *name)
Packit Service a31ea6
{
Packit Service a31ea6
    return shl_load(name, BIND_IMMEDIATE, 0L);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformClose:
Packit Service a31ea6
 * returns 0 on success, and non-zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformClose(void *handle)
Packit Service a31ea6
{
Packit Service a31ea6
    return shl_unload(handle);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformSymbol:
Packit Service a31ea6
 * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
Packit Service a31ea6
 * returns 0 on success and the loaded symbol in result, and -1 on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Packit Service a31ea6
{
Packit Service a31ea6
    int rc;
Packit Service a31ea6
Packit Service a31ea6
    errno = 0;
Packit Service a31ea6
    rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol);
Packit Service a31ea6
    return rc;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#endif /* HAVE_SHLLOAD */
Packit Service a31ea6
#endif /* ! HAVE_DLOPEN */
Packit Service a31ea6
Packit Service a31ea6
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit Service a31ea6
Packit Service a31ea6
#define WIN32_LEAN_AND_MEAN
Packit Service a31ea6
#include <windows.h>
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformOpen:
Packit Service a31ea6
 * returns a handle on success, and zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static void *
Packit Service a31ea6
xmlModulePlatformOpen(const char *name)
Packit Service a31ea6
{
Packit Service a31ea6
    return LoadLibraryA(name);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformClose:
Packit Service a31ea6
 * returns 0 on success, and non-zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformClose(void *handle)
Packit Service a31ea6
{
Packit Service a31ea6
    int rc;
Packit Service a31ea6
Packit Service a31ea6
    rc = FreeLibrary(handle);
Packit Service a31ea6
    return (0 == rc);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformSymbol:
Packit Service a31ea6
 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
Packit Service a31ea6
 * returns 0 on success and the loaded symbol in result, and -1 on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Packit Service a31ea6
{
Packit Service a31ea6
#ifdef _WIN32_WCE
Packit Service a31ea6
    /*
Packit Service a31ea6
     * GetProcAddressA seems only available on WinCE
Packit Service a31ea6
     */
Packit Service a31ea6
    *symbol = GetProcAddressA(handle, name);
Packit Service a31ea6
#else
Packit Service a31ea6
    *symbol = GetProcAddress(handle, name);
Packit Service a31ea6
#endif
Packit Service a31ea6
    return (NULL == *symbol) ? -1 : 0;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#endif /* _WIN32 */
Packit Service a31ea6
Packit Service a31ea6
#ifdef HAVE_BEOS
Packit Service a31ea6
Packit Service a31ea6
#include <kernel/image.h>
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformOpen:
Packit Service a31ea6
 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
Packit Service a31ea6
 * returns a handle on success, and zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static void *
Packit Service a31ea6
xmlModulePlatformOpen(const char *name)
Packit Service a31ea6
{
Packit Service a31ea6
    return (void *) load_add_on(name);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformClose:
Packit Service a31ea6
 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
Packit Service a31ea6
 * returns 0 on success, and non-zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformClose(void *handle)
Packit Service a31ea6
{
Packit Service a31ea6
    status_t rc;
Packit Service a31ea6
Packit Service a31ea6
    rc = unload_add_on((image_id) handle);
Packit Service a31ea6
Packit Service a31ea6
    if (rc == B_OK)
Packit Service a31ea6
        return 0;
Packit Service a31ea6
    else
Packit Service a31ea6
        return -1;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformSymbol:
Packit Service a31ea6
 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
Packit Service a31ea6
 * returns 0 on success and the loaded symbol in result, and -1 on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Packit Service a31ea6
{
Packit Service a31ea6
    status_t rc;
Packit Service a31ea6
Packit Service a31ea6
    rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol);
Packit Service a31ea6
Packit Service a31ea6
    return (rc == B_OK) ? 0 : -1;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#endif /* HAVE_BEOS */
Packit Service a31ea6
Packit Service a31ea6
#ifdef HAVE_OS2
Packit Service a31ea6
Packit Service a31ea6
#include <os2.h>
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformOpen:
Packit Service a31ea6
 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
Packit Service a31ea6
 * returns a handle on success, and zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static void *
Packit Service a31ea6
xmlModulePlatformOpen(const char *name)
Packit Service a31ea6
{
Packit Service a31ea6
    char errbuf[256];
Packit Service a31ea6
    void *handle;
Packit Service a31ea6
    int rc;
Packit Service a31ea6
Packit Service a31ea6
    rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
Packit Service a31ea6
Packit Service a31ea6
    if (rc)
Packit Service a31ea6
        return 0;
Packit Service a31ea6
    else
Packit Service a31ea6
        return (handle);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformClose:
Packit Service a31ea6
 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
Packit Service a31ea6
 * returns 0 on success, and non-zero on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformClose(void *handle)
Packit Service a31ea6
{
Packit Service a31ea6
    return DosFreeModule(handle);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlModulePlatformSymbol:
Packit Service a31ea6
 * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
Packit Service a31ea6
 * returns 0 on success and the loaded symbol in result, and -1 on error.
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
static int
Packit Service a31ea6
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
Packit Service a31ea6
{
Packit Service a31ea6
    int rc;
Packit Service a31ea6
Packit Service a31ea6
    rc = DosQueryProcAddr(handle, 0, name, symbol);
Packit Service a31ea6
Packit Service a31ea6
    return (rc == NO_ERROR) ? 0 : -1;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#endif /* HAVE_OS2 */
Packit Service a31ea6
Packit Service a31ea6
#define bottom_xmlmodule
Packit Service a31ea6
#include "elfgcchack.h"
Packit Service a31ea6
#endif /* LIBXML_MODULES_ENABLED */