diff options
author | Paul Querna <pquerna@apache.org> | 2009-03-24 10:32:34 +0000 |
---|---|---|
committer | Paul Querna <pquerna@apache.org> | 2009-03-24 10:32:34 +0000 |
commit | dfd4f72bed0d7ac95c8ee1a27a6aa652bd766e52 (patch) | |
tree | 69804a4de7433f4755bd62c647dee518c48c673a /util-misc/apu_dso.c | |
parent | 97a7d58c22e482e25154e5e46c7dd91d6222a947 (diff) | |
download | apr-dfd4f72bed0d7ac95c8ee1a27a6aa652bd766e52.tar.gz |
Merge APR-Util trunk into APR.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@757704 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'util-misc/apu_dso.c')
-rw-r--r-- | util-misc/apu_dso.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/util-misc/apu_dso.c b/util-misc/apu_dso.c new file mode 100644 index 000000000..383c5157a --- /dev/null +++ b/util-misc/apu_dso.c @@ -0,0 +1,199 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +#include <ctype.h> +#include <stdio.h> + +#include "apu_config.h" +#include "apu.h" + +#include "apr_pools.h" +#include "apr_tables.h" +#include "apr_dso.h" +#include "apr_strings.h" +#include "apr_hash.h" +#include "apr_file_io.h" +#include "apr_env.h" + +#include "apu_internal.h" +#include "apu_version.h" + +#if APU_DSO_BUILD + +#if APR_HAS_THREADS +static apr_thread_mutex_t* mutex = NULL; +#endif +static apr_hash_t *dsos = NULL; + +#if APR_HAS_THREADS +apr_status_t apu_dso_mutex_lock() +{ + return apr_thread_mutex_lock(mutex); +} +apr_status_t apu_dso_mutex_unlock() +{ + return apr_thread_mutex_unlock(mutex); +} +#else +apr_status_t apu_dso_mutex_lock() { + return APR_SUCCESS; +} +apr_status_t apu_dso_mutex_unlock() { + return APR_SUCCESS; +} +#endif + +static apr_status_t apu_dso_term(void *ptr) +{ + /* set statics to NULL so init can work again */ + dsos = NULL; +#if APR_HAS_THREADS + mutex = NULL; +#endif + + /* Everything else we need is handled by cleanups registered + * when we created mutexes and loaded DSOs + */ + return APR_SUCCESS; +} + +apr_status_t apu_dso_init(apr_pool_t *pool) +{ + apr_status_t ret = APR_SUCCESS; + apr_pool_t *global; + apr_pool_t *parent; + + if (dsos != NULL) { + return APR_SUCCESS; + } + + /* Top level pool scope, need process-scope lifetime */ + for (parent = global = pool; parent; parent = apr_pool_parent_get(global)) + global = parent; + + dsos = apr_hash_make(global); + +#if APR_HAS_THREADS + ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, global); + /* This already registers a pool cleanup */ +#endif + + apr_pool_cleanup_register(global, NULL, apu_dso_term, + apr_pool_cleanup_null); + + return ret; +} + +apr_status_t apu_dso_load(apr_dso_handle_t **dlhandleptr, + apr_dso_handle_sym_t *dsoptr, + const char *module, + const char *modsym, + apr_pool_t *pool) +{ + apr_dso_handle_t *dlhandle = NULL; + char *pathlist; + char path[APR_PATH_MAX + 1]; + apr_array_header_t *paths; + apr_pool_t *global; + apr_status_t rv = APR_EDSOOPEN; + char *eos = NULL; + int i; + + *dsoptr = apr_hash_get(dsos, module, APR_HASH_KEY_STRING); + if (*dsoptr) { + return APR_EINIT; + } + + /* The driver DSO must have exactly the same lifetime as the + * drivers hash table; ignore the passed-in pool */ + global = apr_hash_pool_get(dsos); + + /* Retrieve our path search list or prepare for a single search */ + if ((apr_env_get(&pathlist, APR_DSOPATH, pool) != APR_SUCCESS) + || (apr_filepath_list_split(&paths, pathlist, pool) != APR_SUCCESS)) + paths = apr_array_make(pool, 1, sizeof(char*)); + +#if defined(APU_DSO_LIBDIR) + /* Always search our prefix path, but on some platforms such as + * win32 this may be left undefined + */ + (*((char **)apr_array_push(paths))) = APU_DSO_LIBDIR; +#endif + + for (i = 0; i < paths->nelts; ++i) + { +#if defined(WIN32) + /* Use win32 dso search semantics and attempt to + * load the relative lib on the first pass. + */ + if (!eos) { + eos = path; + --i; + } + else +#endif + { + eos = apr_cpystrn(path, ((char**)paths->elts)[i], sizeof(path)); + if ((eos > path) && (eos - path < sizeof(path) - 1)) + *(eos++) = '/'; + } + apr_cpystrn(eos, module, sizeof(path) - (eos - path)); + + rv = apr_dso_load(&dlhandle, path, global); + if (dlhandleptr) { + *dlhandleptr = dlhandle; + } + if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */ + break; + } +#if defined(APU_DSO_LIBDIR) + else if (i < paths->nelts - 1) { +#else + else { /* No APU_DSO_LIBDIR to skip */ +#endif + /* try with apr-util-APU_MAJOR_VERSION appended */ + eos = apr_cpystrn(eos, + "apr-util-" APU_STRINGIFY(APU_MAJOR_VERSION) "/", + sizeof(path) - (eos - path)); + + apr_cpystrn(eos, module, sizeof(path) - (eos - path)); + + rv = apr_dso_load(&dlhandle, path, global); + if (dlhandleptr) { + *dlhandleptr = dlhandle; + } + if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */ + break; + } + } + } + + if (rv != APR_SUCCESS) /* APR_ESYMNOTFOUND */ + return rv; + + rv = apr_dso_sym(dsoptr, dlhandle, modsym); + if (rv != APR_SUCCESS) { /* APR_ESYMNOTFOUND */ + apr_dso_unload(dlhandle); + } + else { + module = apr_pstrdup(global, module); + apr_hash_set(dsos, module, APR_HASH_KEY_STRING, *dsoptr); + } + return rv; +} + +#endif /* APU_DSO_BUILD */ + |