xmlmodule.c 10.3 KB
Newer Older
1
/*
2
 * xmlmodule.c : basic API for dynamic module loading added 2.6.17
3 4 5 6
 *
 * See Copyright for the status of this software.
 *
 * joelwreed@comcast.net
7 8
 *
 * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
9 10 11 12 13 14 15 16 17 18 19 20 21 22
 */

#define IN_LIBXML
#include "libxml.h"

#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlerror.h>
#include <libxml/xmlmodule.h>
#include <libxml/globals.h>

#ifdef LIBXML_MODULES_ENABLED

struct _xmlModule {
23 24
    unsigned char *name;
    void *handle;
25 26
};

27 28
static void *xmlModulePlatformOpen(const char *name);
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 39 40 41 42 43 44 45 46
/**
 * xmlModuleErrMemory:
 * @extra:  extra information
 *
 * Handle an out of memory condition
 */
static void
xmlModuleErrMemory(xmlModulePtr module, const char *extra)
{
    const char *name = NULL;
47

48
    if (module != NULL) {
49
        name = (const char *) module->name;
50 51 52 53 54 55 56 57
    }

    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
                    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
                    name, NULL, 0, 0,
                    "Memory allocation failed : %s\n", extra);
}

58 59 60
/**
 * xmlModuleOpen:
 * @name: the module name
61
 * @options: a set of xmlModuleOption
62 63
 *
 * Opens a module/shared library given its name or path
64 65 66 67
 * NOTE: that due to portability issues, behaviour can only be
 * guaranteed with @name using ASCII. We canot guarantee that
 * an UTF-8 string would work, which is why name is a const char *
 * and not a const xmlChar * .
68
 * TODO: options are not yet implemented.
69 70 71 72
 *
 * Returns a handle for the module or NULL in case of error
 */
xmlModulePtr
73
xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED)
74
{
75
    xmlModulePtr module;
76

77 78 79 80 81
    module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
    if (module == NULL) {
        xmlModuleErrMemory(NULL, "creating module");
        return (NULL);
    }
82

83
    memset(module, 0, sizeof(xmlModule));
84

85
    module->handle = xmlModulePlatformOpen(name);
86

87 88 89 90 91
    if (module->handle == NULL) {
        xmlFree(module);
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
                        name, NULL, 0, 0, "failed to open %s\n", name);
92
        return(NULL);
93
    }
94

95 96
    module->name = xmlStrdup((const xmlChar *) name);
    return (module);
97 98
}

99 100 101 102
/**
 * xmlModuleSymbol:
 * @module: the module
 * @name: the name of the symbol
103
 * @symbol: the resulting symbol address
104 105
 *
 * Lookup for a symbol address in the given module
106 107 108 109
 * NOTE: that due to portability issues, behaviour can only be
 * guaranteed with @name using ASCII. We canot guarantee that
 * an UTF-8 string would work, which is why name is a const char *
 * and not a const xmlChar * .
110
 *
111
 * Returns 0 if the symbol was found, or -1 in case of error
112
 */
113 114
int
xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol)
115
{
116
    int rc = -1;
117

118
    if ((NULL == module) || (symbol == NULL) || (name == NULL)) {
119 120
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
121 122
                        NULL, NULL, 0, 0, "null parameter\n");
        return rc;
123
    }
124

125
    rc = xmlModulePlatformSymbol(module->handle, name, symbol);
126

127
    if (rc == -1) {
128 129
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
                        XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
130 131 132 133
                        name, NULL, 0, 0,
                        "failed to find symbol: %s\n",
			(name == NULL ? "NULL" : name));
        return rc;
134
    }
135

136
    return rc;
137 138
}

139 140 141 142 143 144 145 146 147 148 149 150
/**
 * xmlModuleClose:
 * @module: the module handle
 *
 * The close operations unload the associated module and free the
 * data associated to the module.
 *
 * Returns 0 in case of success, -1 in case of argument error and -2
 *         if the module could not be closed/unloaded.
 */
int
xmlModuleClose(xmlModulePtr module)
151
{
152
    int rc;
153

154 155
    if (NULL == module) {
        __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
156 157
                        XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0,
                        NULL, NULL, 0, 0, "null module pointer\n");
158 159
        return -1;
    }
160

161
    rc = xmlModulePlatformClose(module->handle);
162

163 164
    if (rc != 0) {
        __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 169 170 171 172
        return -2;
    }

    rc = xmlModuleFree(module);
    return (rc);
173 174
}

175 176 177 178 179 180 181 182 183 184 185 186
/**
 * xmlModuleFree:
 * @module: the module handle
 *
 * The free operations free the data associated to the module
 * but does not unload the associated shared library which may still
 * be in use.
 *
 * Returns 0 in case of success, -1 in case of argument error
 */
int
xmlModuleFree(xmlModulePtr module)
187
{
188 189
    if (NULL == module) {
        __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 193
        return -1;
    }
194

195 196
    xmlFree(module->name);
    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 207 208 209
#ifndef RTLD_GLOBAL            /* For Tru64 UNIX 4.0 */
#define RTLD_GLOBAL 0
#endif

210
/**
211
 * xmlModulePlatformOpen:
212 213
 * @name: path to the module
 *
214
 * returns a handle on success, and zero on error.
215
 */
216

217 218
static void *
xmlModulePlatformOpen(const char *name)
219
{
220
    return dlopen(name, RTLD_GLOBAL | RTLD_NOW);
221 222 223 224
}

/*
 * xmlModulePlatformClose:
225 226
 * @handle: handle to the module
 *
227
 * returns 0 on success, and non-zero on error.
228
 */
229

230 231
static int
xmlModulePlatformClose(void *handle)
232
{
233
    return dlclose(handle);
234 235 236 237
}

/*
 * xmlModulePlatformSymbol:
238 239
 * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
 * returns 0 on success and the loaded symbol in result, and -1 on error.
240
 */
241

242 243
static int
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
244
{
245 246 247 248 249
    *symbol = dlsym(handle, name);
    if (dlerror() != NULL) {
	return -1;
    }
    return 0;
250 251
}

252
#else /* ! HAVE_DLOPEN */
253

254
#ifdef HAVE_SHLLOAD             /* HAVE_SHLLOAD */
255 256 257
#ifdef HAVE_DL_H
#include <dl.h>
#endif
258 259 260
/*
 * xmlModulePlatformOpen:
 * returns a handle on success, and zero on error.
261
 */
262

263 264
static void *
xmlModulePlatformOpen(const char *name)
265
{
266
    return shl_load(name, BIND_IMMEDIATE, 0L);
267 268 269 270 271
}

/*
 * xmlModulePlatformClose:
 * returns 0 on success, and non-zero on error.
272
 */
273

274 275
static int
xmlModulePlatformClose(void *handle)
276
{
277
    return shl_unload(handle);
278 279 280 281
}

/*
 * xmlModulePlatformSymbol:
282 283
 * http://docs.hp.com/en/B2355-90683/shl_load.3X.html
 * returns 0 on success and the loaded symbol in result, and -1 on error.
284
 */
285

286 287
static int
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
288
{
289 290 291
    int rc;

    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 300 301 302 303 304 305

#ifdef _WIN32

#include <windows.h>

/*
 * xmlModulePlatformOpen:
 * returns a handle on success, and zero on error.
306
 */
307

308 309
static void *
xmlModulePlatformOpen(const char *name)
310
{
311
    return LoadLibraryA(name);
312 313 314 315 316
}

/*
 * xmlModulePlatformClose:
 * returns 0 on success, and non-zero on error.
317
 */
318

319 320
static int
xmlModulePlatformClose(void *handle)
321
{
322 323 324 325
    int rc;

    rc = FreeLibrary(handle);
    return (0 == rc);
326 327 328 329
}

/*
 * xmlModulePlatformSymbol:
330 331
 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp
 * returns 0 on success and the loaded symbol in result, and -1 on error.
332
 */
333

334 335
static int
xmlModulePlatformSymbol(void *handle, const char *name, void **symbol)
336
{
337 338 339 340
#ifdef _WIN32_WCE
    /*
     * GetProcAddressA seems only available on WinCE
     */
341
    *symbol = GetProcAddressA(handle, name);
342 343 344
#else
    *symbol = GetProcAddress(handle, name);
#endif
345
    return (NULL == *symbol) ? -1 : 0;
346 347 348 349 350 351 352 353 354 355 356 357
}

#endif /* _WIN32 */

#ifdef HAVE_BEOS

#include <kernel/image.h>

/*
 * xmlModulePlatformOpen:
 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
 * returns a handle on success, and zero on error.
358
 */
359

360 361
static void *
xmlModulePlatformOpen(const char *name)
362
{
363
    return (void *) load_add_on(name);
364 365 366 367 368 369
}

/*
 * xmlModulePlatformClose:
 * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
 * returns 0 on success, and non-zero on error.
370
 */
371

372 373
static int
xmlModulePlatformClose(void *handle)
374
{
375
    status_t rc;
376

377 378 379 380 381 382
    rc = unload_add_on((image_id) handle);

    if (rc == B_OK)
        return 0;
    else
        return -1;
383 384 385 386 387
}

/*
 * xmlModulePlatformSymbol:
 * 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 392
static int
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 402 403 404 405 406 407 408 409 410
}

#endif /* HAVE_BEOS */

#ifdef HAVE_OS2

#include <os2.h>

/*
 * xmlModulePlatformOpen:
 * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
 * returns a handle on success, and zero on error.
411
 */
412

413 414
static void *
xmlModulePlatformOpen(const char *name)
415
{
416
    char errbuf[256];
417 418
    void *handle;
    int rc;
419

420
    rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle);
421

422 423 424 425
    if (rc)
        return 0;
    else
        return (handle);
426 427 428 429 430 431
}

/*
 * xmlModulePlatformClose:
 * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
 * returns 0 on success, and non-zero on error.
432
 */
433

434 435
static int
xmlModulePlatformClose(void *handle)
436
{
437
    return DosFreeModule(handle);
438 439 440 441 442
}

/*
 * xmlModulePlatformSymbol:
 * 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 447
static int
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 457
}

#endif /* HAVE_OS2 */

458 459
#define bottom_xmlmodule
#include "elfgcchack.h"
460
#endif /* LIBXML_MODULES_ENABLED */