1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter#include <ctype.h> 18251876Speter#include <stdio.h> 19251876Speter 20251876Speter#include "apu_config.h" 21251876Speter#include "apu.h" 22251876Speter 23251876Speter#include "apr_pools.h" 24251876Speter#include "apr_tables.h" 25251876Speter#include "apr_dso.h" 26251876Speter#include "apr_strings.h" 27251876Speter#include "apr_hash.h" 28251876Speter#include "apr_file_io.h" 29251876Speter#include "apr_env.h" 30251876Speter#include "apr_atomic.h" 31251876Speter 32251876Speter#include "apu_internal.h" 33251876Speter#include "apu_version.h" 34251876Speter 35251876Speter#if APU_DSO_BUILD 36251876Speter 37251876Speter#if APR_HAS_THREADS 38251876Speterstatic apr_thread_mutex_t* mutex = NULL; 39251876Speter#endif 40251876Speterstatic apr_hash_t *dsos = NULL; 41251876Speterstatic apr_uint32_t initialised = 0, in_init = 1; 42251876Speter 43251876Speter#if APR_HAS_THREADS 44251876Speterapr_status_t apu_dso_mutex_lock() 45251876Speter{ 46251876Speter return apr_thread_mutex_lock(mutex); 47251876Speter} 48251876Speterapr_status_t apu_dso_mutex_unlock() 49251876Speter{ 50251876Speter return apr_thread_mutex_unlock(mutex); 51251876Speter} 52251876Speter#else 53251876Speterapr_status_t apu_dso_mutex_lock() { 54251876Speter return APR_SUCCESS; 55251876Speter} 56251876Speterapr_status_t apu_dso_mutex_unlock() { 57251876Speter return APR_SUCCESS; 58251876Speter} 59251876Speter#endif 60251876Speter 61251876Speterstatic apr_status_t apu_dso_term(void *ptr) 62251876Speter{ 63251876Speter /* set statics to NULL so init can work again */ 64251876Speter dsos = NULL; 65251876Speter#if APR_HAS_THREADS 66251876Speter mutex = NULL; 67251876Speter#endif 68251876Speter 69251876Speter /* Everything else we need is handled by cleanups registered 70251876Speter * when we created mutexes and loaded DSOs 71251876Speter */ 72251876Speter return APR_SUCCESS; 73251876Speter} 74251876Speter 75251876Speterapr_status_t apu_dso_init(apr_pool_t *pool) 76251876Speter{ 77251876Speter apr_status_t ret = APR_SUCCESS; 78251876Speter apr_pool_t *parent; 79251876Speter 80251876Speter if (apr_atomic_inc32(&initialised)) { 81251876Speter apr_atomic_set32(&initialised, 1); /* prevent wrap-around */ 82251876Speter 83251876Speter while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */ 84251876Speter ; 85251876Speter 86251876Speter return APR_SUCCESS; 87251876Speter } 88251876Speter 89251876Speter /* Top level pool scope, need process-scope lifetime */ 90262253Speter for (parent = apr_pool_parent_get(pool); 91262253Speter parent && parent != pool; 92262253Speter parent = apr_pool_parent_get(pool)) 93262253Speter pool = parent; 94251876Speter 95262253Speter dsos = apr_hash_make(pool); 96251876Speter 97251876Speter#if APR_HAS_THREADS 98262253Speter ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool); 99251876Speter /* This already registers a pool cleanup */ 100251876Speter#endif 101251876Speter 102262253Speter apr_pool_cleanup_register(pool, NULL, apu_dso_term, 103251876Speter apr_pool_cleanup_null); 104251876Speter 105251876Speter apr_atomic_dec32(&in_init); 106251876Speter 107251876Speter return ret; 108251876Speter} 109251876Speter 110251876Speterapr_status_t apu_dso_load(apr_dso_handle_t **dlhandleptr, 111251876Speter apr_dso_handle_sym_t *dsoptr, 112251876Speter const char *module, 113251876Speter const char *modsym, 114251876Speter apr_pool_t *pool) 115251876Speter{ 116251876Speter apr_dso_handle_t *dlhandle = NULL; 117251876Speter char *pathlist; 118251876Speter char path[APR_PATH_MAX + 1]; 119251876Speter apr_array_header_t *paths; 120251876Speter apr_pool_t *global; 121251876Speter apr_status_t rv = APR_EDSOOPEN; 122251876Speter char *eos = NULL; 123251876Speter int i; 124251876Speter 125251876Speter *dsoptr = apr_hash_get(dsos, module, APR_HASH_KEY_STRING); 126251876Speter if (*dsoptr) { 127251876Speter return APR_EINIT; 128251876Speter } 129251876Speter 130251876Speter /* The driver DSO must have exactly the same lifetime as the 131251876Speter * drivers hash table; ignore the passed-in pool */ 132251876Speter global = apr_hash_pool_get(dsos); 133251876Speter 134251876Speter /* Retrieve our path search list or prepare for a single search */ 135251876Speter if ((apr_env_get(&pathlist, APR_DSOPATH, pool) != APR_SUCCESS) 136251876Speter || (apr_filepath_list_split(&paths, pathlist, pool) != APR_SUCCESS)) 137251876Speter paths = apr_array_make(pool, 1, sizeof(char*)); 138251876Speter 139251876Speter#if defined(APU_DSO_LIBDIR) 140251876Speter /* Always search our prefix path, but on some platforms such as 141251876Speter * win32 this may be left undefined 142251876Speter */ 143251876Speter (*((char **)apr_array_push(paths))) = APU_DSO_LIBDIR; 144251876Speter#endif 145251876Speter 146251876Speter for (i = 0; i < paths->nelts; ++i) 147251876Speter { 148251876Speter#if defined(WIN32) 149251876Speter /* Use win32 dso search semantics and attempt to 150251876Speter * load the relative lib on the first pass. 151251876Speter */ 152251876Speter if (!eos) { 153251876Speter eos = path; 154251876Speter --i; 155251876Speter } 156251876Speter else 157251876Speter#endif 158251876Speter { 159251876Speter eos = apr_cpystrn(path, ((char**)paths->elts)[i], sizeof(path)); 160251876Speter if ((eos > path) && (eos - path < sizeof(path) - 1)) 161251876Speter *(eos++) = '/'; 162251876Speter } 163251876Speter apr_cpystrn(eos, module, sizeof(path) - (eos - path)); 164251876Speter 165251876Speter rv = apr_dso_load(&dlhandle, path, global); 166251876Speter if (dlhandleptr) { 167251876Speter *dlhandleptr = dlhandle; 168251876Speter } 169251876Speter if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */ 170251876Speter break; 171251876Speter } 172251876Speter#if defined(APU_DSO_LIBDIR) 173251876Speter else if (i < paths->nelts - 1) { 174251876Speter#else 175251876Speter else { /* No APU_DSO_LIBDIR to skip */ 176251876Speter#endif 177251876Speter /* try with apr-util-APU_MAJOR_VERSION appended */ 178251876Speter eos = apr_cpystrn(eos, 179251876Speter "apr-util-" APU_STRINGIFY(APU_MAJOR_VERSION) "/", 180251876Speter sizeof(path) - (eos - path)); 181251876Speter 182251876Speter apr_cpystrn(eos, module, sizeof(path) - (eos - path)); 183251876Speter 184251876Speter rv = apr_dso_load(&dlhandle, path, global); 185251876Speter if (dlhandleptr) { 186251876Speter *dlhandleptr = dlhandle; 187251876Speter } 188251876Speter if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */ 189251876Speter break; 190251876Speter } 191251876Speter } 192251876Speter } 193251876Speter 194251876Speter if (rv != APR_SUCCESS) /* APR_ESYMNOTFOUND */ 195251876Speter return rv; 196251876Speter 197251876Speter rv = apr_dso_sym(dsoptr, dlhandle, modsym); 198251876Speter if (rv != APR_SUCCESS) { /* APR_ESYMNOTFOUND */ 199251876Speter apr_dso_unload(dlhandle); 200251876Speter } 201251876Speter else { 202251876Speter module = apr_pstrdup(global, module); 203251876Speter apr_hash_set(dsos, module, APR_HASH_KEY_STRING, *dsoptr); 204251876Speter } 205251876Speter return rv; 206251876Speter} 207251876Speter 208251876Speter#endif /* APU_DSO_BUILD */ 209251876Speter 210