Comments?
This adds apr_dso_open(). Its intention is to only open a dynamic shared
library and to do so without any further process to automatically bind
global symbols, unlike apr_dso_load().
Jonathan
Index: include/apr_dso.h
===================================================================
--- include/apr_dso.h (revision 366515)
+++ include/apr_dso.h (working copy)
@@ -49,20 +49,43 @@
typedef void * apr_dso_handle_sym_t;
/**
- * Load a DSO library.
+ * Open a DSO library.
* @param res_handle Location to store new handle for the DSO.
* @param path Path to the DSO library
* @param ctx Pool to use.
- * @bug We aught to provide an alternative to RTLD_GLOBAL, which
- * is the only supported method of loading DSOs today.
+ * @bug not yet implemented on every supported OS
+ * @remark This implies apr_dso_open() does not let apr_dso_sym()
+ * to bind globally, and one either uses apr_dso_open()
+ * or apr_dso_load() to access a library by local or global
+ * namespace, respectively.
*/
+APR_DECLARE(apr_status_t) apr_dso_open(apr_dso_handle_t **res_handle,
+ const char *path, apr_pool_t *ctx);
+
+/**
+ * Open a DSO library and load symbols.
+ * @param res_handle Location to store new handle for the DSO.
+ * @param path Path to the DSO library
+ * @param ctx Pool to use.
+ * @remark This implies apr_dso_load() allows apr_dso_sym()
+ * to bind globally but unenforced, and one either uses
+ * apr_dso_open() or apr_dso_load() to access a library by
+ * local or global namespace, respectively.
+ */
APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle,
const char *path, apr_pool_t *ctx);
/**
- * Close a DSO library.
+ * Close a DSO library opened by apr_dso_open().
* @param handle handle to close.
+ * @bug not yet implemented on every supported OS
*/
+APR_DECLARE(apr_status_t) apr_dso_close(apr_dso_handle_t *handle);
+
+/**
+ * Close a DSO library opened by apr_dso_load().
+ * @param handle handle to close.
+ */
APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle);
/**
Index: dso/unix/dso_dlfcn.h
===================================================================
--- dso/unix/dso_dlfcn.h (revision 0)
+++ dso/unix/dso_dlfcn.h (revision 0)
@@ -0,0 +1,102 @@
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+ apr_dso_handle_t *dso = thedso;
+
+ if (dso->handle == NULL)
+ return APR_SUCCESS;
+
+ if (dlclose(dso->handle) != 0)
+ return APR_EINIT;
+ dso->handle = NULL;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t dlfcn_open(apr_dso_handle_t *res_handle,
+ const char *path, int flags)
+{
+#if defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\
+ (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) ||\
+ defined(__DragonFly__)
+ res_handle->handle = dlopen((char *)path, flags);
+
+#else
+#if defined(_AIX)
+ if (strchr(path + 1, '(') && path[strlen(path) - 1] == ')')
+ {
+ /* This special archive.a(dso.so) syntax is required for
+ * the way libtool likes to build shared libraries on AIX.
+ * dlopen() support for such a library requires that the
+ * RTLD_MEMBER flag be enabled.
+ */
+ flags |= RTLD_MEMBER;
+ }
+#endif /* _AIX */
+ res_handle->handle = dlopen(path, flags);
+#endif
+
+ if(res_handle->handle == NULL) {
+ res_handle->errormsg = dlerror();
+ return APR_EDSOOPEN;
+ }
+
+ apr_pool_cleanup_register(res_handle->pool, res_handle, dso_cleanup,
apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t dso_open(apr_dso_handle_t *res_handle,
+ const char *path)
+{
+ return dlfcn_open(res_handle, path, RTLD_LAZY | RTLD_LOCAL);
+}
+
+static apr_status_t dso_load(apr_dso_handle_t *res_handle,
+ const char *path)
+{
+ return dlfcn_open(res_handle, path, RTLD_NOW | RTLD_GLOBAL);
+}
+
+
+static apr_status_t dso_sym(apr_dso_handle_sym_t *ressym,
+ apr_dso_handle_t *handle,
+ const char *symname)
+{
+#if defined(DLSYM_NEEDS_UNDERSCORE)
+ void *retval;
+ char *symbol = (char*)malloc(sizeof(char)*(strlen(symname)+2));
+ sprintf(symbol, "_%s", symname);
+ retval = dlsym(handle->handle, symbol);
+ free(symbol);
+#elif defined(SEQUENT) || defined(SNI)
+ void *retval = dlsym(handle->handle, (char *)symname);
+#else
+ void *retval = dlsym(handle->handle, symname);
+#endif /* DLSYM_NEEDS_UNDERSCORE */
+
+ if (retval == NULL) {
+ handle->errormsg = dlerror();
+ return APR_ESYMNOTFOUND;
+ }
+
+ *ressym = retval;
+
+ return APR_SUCCESS;
+}
Index: dso/unix/dso_shl.h
===================================================================
--- dso/unix/dso_shl.h (revision 0)
+++ dso/unix/dso_shl.h (revision 0)
@@ -0,0 +1,75 @@
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+ apr_dso_handle_t *dso = thedso;
+
+ if (dso->handle == NULL)
+ return APR_SUCCESS;
+
+ shl_unload((shl_t)dso->handle);
+ dso->handle = NULL;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t dso_open(apr_dso_handle_t *res_handle,
+ const char *path)
+{
+ res_handle->handle = shl_load(path, BIND_DEFERRED, 0L);
+
+ if(res_handle->handle == NULL) {
+ res_handle->errormsg = strerror(errno);
+ return APR_EDSOOPEN;
+ }
+
+ apr_pool_cleanup_register(res_handle->pool, res_handle, dso_cleanup,
apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t apr_dso_load(apr_dso_handle_t *res_handle,
+ const char *path)
+{
+ res_hanlde->handle = shl_load(path, BIND_IMMEDIATE, 0L);
+
+ if(res_handle->handle == NULL) {
+ res_handle->errormsg = strerror(errno);
+ return APR_EDSOOPEN;
+ }
+
+ apr_pool_cleanup_register(res_handle->pool, res_handle, dso_cleanup,
apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t dso_sym(apr_dso_handle_sym_t *ressym,
+ apr_dso_handle_t *handle,
+ const char *symname)
+{
+ void *symaddr = NULL;
+ int status;
+
+ errno = 0;
+ status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_PROCEDURE,
&symaddr);
+ if (status == -1 && errno == 0) /* try TYPE_DATA instead */
+ status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_DATA,
&symaddr);
+ if (status == -1)
+ return APR_ESYMNOTFOUND;
+ *ressym = symaddr;
+ return APR_SUCCESS;
+}
Index: dso/unix/dso.c
===================================================================
--- dso/unix/dso.c (revision 366515)
+++ dso/unix/dso.c (working copy)
@@ -20,10 +20,6 @@
#if APR_HAS_DSO
-#if !defined(DSO_USE_DLFCN) && !defined(DSO_USE_SHL) && !defined(DSO_USE_DYLD)
-#error No DSO implementation specified.
-#endif
-
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif
@@ -34,8 +30,14 @@
#include <string.h> /* for strerror() on HP-UX */
#endif
-#if defined(DSO_USE_DYLD)
-#define DYLD_LIBRARY_HANDLE (void *)-1
+#if defined(DSO_USE_DLFCN)
+#include "dso_dlfcn.h"
+#elif defined(DSO_USE_SHL)
+#include "dso_shl.h"
+#elif defined(DSO_USE_DYLD)
+#include "dso_dyld.h"
+#else
+#error No DSO implementation specified.
#endif
APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
@@ -55,187 +57,39 @@
return APR_SUCCESS;
}
-static apr_status_t dso_cleanup(void *thedso)
+APR_DECLARE(apr_status_t) apr_dso_open(apr_dso_handle_t **res_handle,
+ const char *path, apr_pool_t *pool)
{
- apr_dso_handle_t *dso = thedso;
+ *res_handle = apr_pcalloc(pool, sizeof(**res_handle));
+ (*res_handle)->pool = pool ;
- if (dso->handle == NULL)
- return APR_SUCCESS;
-
-#if defined(DSO_USE_SHL)
- shl_unload((shl_t)dso->handle);
-#elif defined(DSO_USE_DYLD)
- if (dso->handle != DYLD_LIBRARY_HANDLE) {
- NSUnLinkModule(dso->handle, FALSE);
- }
-#elif defined(DSO_USE_DLFCN)
- if (dlclose(dso->handle) != 0)
- return APR_EINIT;
-#endif
- dso->handle = NULL;
-
- return APR_SUCCESS;
-}
-
+ return dso_open(*res_handle, path);
+}
+
APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle,
const char *path, apr_pool_t *pool)
{
-#if defined(DSO_USE_SHL)
- shl_t os_handle = shl_load(path, BIND_IMMEDIATE, 0L);
-
-#elif defined(DSO_USE_DYLD)
- NSObjectFileImage image;
- NSModule os_handle = NULL;
- NSObjectFileImageReturnCode dsoerr;
- const char* err_msg = NULL;
- dsoerr = NSCreateObjectFileImageFromFile(path, &image);
-
- if (dsoerr == NSObjectFileImageSuccess) {
-#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) &&
defined(NSLINKMODULE_OPTION_NONE)
- os_handle = NSLinkModule(image, path,
- NSLINKMODULE_OPTION_RETURN_ON_ERROR |
- NSLINKMODULE_OPTION_NONE);
- /* If something went wrong, get the errors... */
- if (!os_handle) {
- NSLinkEditErrors errors;
- int errorNumber;
- const char *fileName;
- NSLinkEditError(&errors, &errorNumber, &fileName, &err_msg);
- }
-#else
- os_handle = NSLinkModule(image, path, FALSE);
-#endif
- NSDestroyObjectFileImage(image);
- }
- else if ((dsoerr == NSObjectFileImageFormat ||
- dsoerr == NSObjectFileImageInappropriateFile) &&
- NSAddLibrary(path) == TRUE) {
- os_handle = (NSModule)DYLD_LIBRARY_HANDLE;
- }
- else {
- err_msg = "cannot create object file image or add library";
- }
-
-#elif defined(DSO_USE_DLFCN)
-#if defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\
- (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) ||\
- defined(__DragonFly__)
- void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL);
-
-#else
- int flags = RTLD_NOW | RTLD_GLOBAL;
- void *os_handle;
-#ifdef _AIX
- if (strchr(path + 1, '(') && path[strlen(path) - 1] == ')')
- {
- /* This special archive.a(dso.so) syntax is required for
- * the way libtool likes to build shared libraries on AIX.
- * dlopen() support for such a library requires that the
- * RTLD_MEMBER flag be enabled.
- */
- flags |= RTLD_MEMBER;
- }
-#endif
- os_handle = dlopen(path, flags);
-#endif
-#endif /* DSO_USE_x */
-
*res_handle = apr_pcalloc(pool, sizeof(**res_handle));
+ (*res_handle)->pool = pool ;
- if(os_handle == NULL) {
-#if defined(DSO_USE_SHL)
- (*res_handle)->errormsg = strerror(errno);
- return APR_EDSOOPEN;
-#elif defined(DSO_USE_DYLD)
- (*res_handle)->errormsg = (err_msg) ? err_msg : "link failed";
- return APR_EDSOOPEN;
-#elif defined(DSO_USE_DLFCN)
- (*res_handle)->errormsg = dlerror();
- return APR_EDSOOPEN;
-#endif
- }
-
- (*res_handle)->handle = (void*)os_handle;
- (*res_handle)->pool = pool;
- (*res_handle)->errormsg = NULL;
-
- apr_pool_cleanup_register(pool, *res_handle, dso_cleanup,
apr_pool_cleanup_null);
-
- return APR_SUCCESS;
-}
+ return dso_load(*res_handle, path);
+}
APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
{
return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
}
+APR_DECLARE(apr_status_t) apr_dso_close(apr_dso_handle_t *handle)
+{
+ return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
+}
+
APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym,
apr_dso_handle_t *handle,
const char *symname)
{
-#if defined(DSO_USE_SHL)
- void *symaddr = NULL;
- int status;
-
- errno = 0;
- status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_PROCEDURE,
&symaddr);
- if (status == -1 && errno == 0) /* try TYPE_DATA instead */
- status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_DATA,
&symaddr);
- if (status == -1)
- return APR_ESYMNOTFOUND;
- *ressym = symaddr;
- return APR_SUCCESS;
-
-#elif defined(DSO_USE_DYLD)
- void *retval = NULL;
- NSSymbol symbol;
- char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2));
- sprintf(symname2, "_%s", symname);
-#ifdef NSLINKMODULE_OPTION_PRIVATE
- if (handle->handle == DYLD_LIBRARY_HANDLE) {
- symbol = NSLookupAndBindSymbol(symname2);
- }
- else {
- symbol = NSLookupSymbolInModule((NSModule)handle->handle, symname2);
- }
-#else
- symbol = NSLookupAndBindSymbol(symname2);
-#endif
- free(symname2);
- if (symbol == NULL) {
- handle->errormsg = "undefined symbol";
- return APR_ESYMNOTFOUND;
- }
- retval = NSAddressOfSymbol(symbol);
- if (retval == NULL) {
- handle->errormsg = "cannot resolve symbol";
- return APR_ESYMNOTFOUND;
- }
- *ressym = retval;
- return APR_SUCCESS;
-#elif defined(DSO_USE_DLFCN)
-
-#if defined(DLSYM_NEEDS_UNDERSCORE)
- void *retval;
- char *symbol = (char*)malloc(sizeof(char)*(strlen(symname)+2));
- sprintf(symbol, "_%s", symname);
- retval = dlsym(handle->handle, symbol);
- free(symbol);
-#elif defined(SEQUENT) || defined(SNI)
- void *retval = dlsym(handle->handle, (char *)symname);
-#else
- void *retval = dlsym(handle->handle, symname);
-#endif /* DLSYM_NEEDS_UNDERSCORE */
-
- if (retval == NULL) {
- handle->errormsg = dlerror();
- return APR_ESYMNOTFOUND;
- }
-
- *ressym = retval;
-
- return APR_SUCCESS;
-#endif /* DSO_USE_x */
+ return dso_sym(ressym, handle, symname);
}
APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer,
Index: dso/unix/dso_dyld.h
===================================================================
--- dso/unix/dso_dyld.h (revision 0)
+++ dso/unix/dso_dyld.h (revision 0)
@@ -0,0 +1,152 @@
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DYLD_LIBRARY_HANDLE (void *)-1
+
+static apr_status_t dso_cleanup(void *thedso)
+{
+ apr_dso_handle_t *dso = thedso;
+
+ if (dso->handle == NULL)
+ return APR_SUCCESS;
+
+ if (dso->handle != DYLD_LIBRARY_HANDLE) {
+ NSUnLinkModule(dso->handle, FALSE);
+ }
+ dso->handle = NULL;
+
+ return APR_SUCCESS;
+}
+
+static const char * dyld_errmsg(void)
+{
+#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR)
+ NSLinkEditErrors errors;
+ int errorNumber;
+ const char *fileName;
+ const char *errmsg;
+ NSLinkEditError(&errors, &errorNumber, &fileName, &errmsg);
+ return errmsg;
+#else
+ return "error";
+#endif
+}
+
+static apr_status_t apr_dso_open(apr_dso_handle_t *res_handle,
+ const char *path)
+{
+#if defined(NSLINKMODULE_OPTION_PRIVATE)
+ NSObjectFileImage image;
+ NSObjectFileImageReturnCode dsoerr;
+
+ dsoerr = NSCreateObjectFileImageFromFile(path, &image);
+ if (dsoerr != NSObjectFileImageSuccess) {
+ res_handle->errormsg = "cannot create object file image";
+ return APR_EDSOOPEN;
+ }
+ res_handle->handle = NSLinkModule(image, path,
+#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR)
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR |
+#endif
+ NSLINKMODULE_OPTION_PRIVATE);
+ if (!res_handle->handle) {
+ res_handle->errormsg = dyld_errmsg();
+ NSDestroyObjectFileImage(image);
+ return APR_EDSOOPEN;
+ }
+ NSDestroyObjectFileImage(image);
+
+ apr_pool_cleanup_register(res_handle->pool, res_handle, dso_cleanup,
apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+#else
+ res_handle->errormsg = "private module unsupported in OS";
+ return APR_EDSOOPEN;
+#endif
+}
+
+
+static apr_status_t dso_load(apr_dso_handle_t *res_handle,
+ const char *path, apr_pool_t *pool)
+{
+ NSObjectFileImage image;
+ NSModule os_handle = NULL;
+ NSObjectFileImageReturnCode dsoerr;
+
+ dsoerr = NSCreateObjectFileImageFromFile(path, &image);
+ if (dsoerr == NSObjectFileImageSuccess) {
+ res_handle->handle = NSLinkModule(image, path,
+#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR)
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR |
+#endif
+#if defined(NSLINKMODULE_OPTION_NONE)
+ NSLINKMODULE_OPTION_NONE);
+#else
+ FALSE);
+#endif
+ if (!res_handle->handle) {
+ res_handle->errormsg = dyld_error();
+ NSDestroyObjectFileImage(image);
+ return APR_EDSOOPEN;
+ }
+ NSDestroyObjectFileImage(image);
+ }
+ else if ((dsoerr == NSObjectFileImageFormat ||
+ dsoerr == NSObjectFileImageInappropriateFile) &&
+ NSAddLibrary(path) == TRUE) {
+ res_handle->handle = (NSModule)DYLD_LIBRARY_HANDLE;
+ }
+ else {
+ res_handle->errormsg = "cannot create object file image";
+ return APR_EDSOOPEN;
+ }
+
+ apr_pool_cleanup_register(res_handle->pool, res_handle, dso_cleanup,
apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t dso_sym(apr_dso_handle_sym_t *ressym,
+ apr_dso_handle_t *handle,
+ const char *symname)
+{
+ void *retval = NULL;
+ NSSymbol symbol;
+ char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2));
+ sprintf(symname2, "_%s", symname);
+#ifdef NSLINKMODULE_OPTION_PRIVATE
+ if (handle->handle == DYLD_LIBRARY_HANDLE) {
+ symbol = NSLookupAndBindSymbol(symname2);
+ }
+ else {
+ symbol = NSLookupSymbolInModule((NSModule)handle->handle, symname2);
+ }
+#else
+ symbol = NSLookupAndBindSymbol(symname2);
+#endif
+ free(symname2);
+ if (symbol == NULL) {
+ handle->errormsg = "undefined symbol";
+ return APR_ESYMNOTFOUND;
+ }
+ retval = NSAddressOfSymbol(symbol);
+ if (retval == NULL) {
+ handle->errormsg = "cannot resolve symbol";
+ return APR_ESYMNOTFOUND;
+ }
+ *ressym = retval;
+ return APR_SUCCESS;
+}