/security/nss/lib/util/secload.c
http://github.com/zpao/v8monkey · C · 217 lines · 112 code · 10 blank · 95 comment · 17 complexity · 26aea1d8141283e947a42e24ed65eb33 MD5 · raw file
- /*
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (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.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
- * Kai Engert <kengert@redhat.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
- #include "secport.h"
- #include "nspr.h"
- #ifdef XP_UNIX
- #include <unistd.h>
- #define BL_MAXSYMLINKS 20
- /*
- * If 'link' is a symbolic link, this function follows the symbolic links
- * and returns the pathname of the ultimate source of the symbolic links.
- * If 'link' is not a symbolic link, this function returns NULL.
- * The caller should call PR_Free to free the string returned by this
- * function.
- */
- static char* loader_GetOriginalPathname(const char* link)
- {
- char* resolved = NULL;
- char* input = NULL;
- PRUint32 iterations = 0;
- PRInt32 len = 0, retlen = 0;
- if (!link) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- return NULL;
- }
- len = PR_MAX(1024, strlen(link) + 1);
- resolved = PR_Malloc(len);
- input = PR_Malloc(len);
- if (!resolved || !input) {
- if (resolved) {
- PR_Free(resolved);
- }
- if (input) {
- PR_Free(input);
- }
- return NULL;
- }
- strcpy(input, link);
- while ( (iterations++ < BL_MAXSYMLINKS) &&
- ( (retlen = readlink(input, resolved, len - 1)) > 0) ) {
- char* tmp = input;
- resolved[retlen] = '\0'; /* NULL termination */
- input = resolved;
- resolved = tmp;
- }
- PR_Free(resolved);
- if (iterations == 1 && retlen < 0) {
- PR_Free(input);
- input = NULL;
- }
- return input;
- }
- #endif /* XP_UNIX */
- /*
- * Load the library with the file name 'name' residing in the same
- * directory as the reference library, whose pathname is 'referencePath'.
- */
- static PRLibrary *
- loader_LoadLibInReferenceDir(const char *referencePath, const char *name)
- {
- PRLibrary *dlh = NULL;
- char *fullName = NULL;
- char* c;
- PRLibSpec libSpec;
- /* Remove the trailing filename from referencePath and add the new one */
- c = strrchr(referencePath, PR_GetDirectorySeparator());
- if (c) {
- size_t referencePathSize = 1 + c - referencePath;
- fullName = (char*) PORT_Alloc(strlen(name) + referencePathSize + 1);
- if (fullName) {
- memcpy(fullName, referencePath, referencePathSize);
- strcpy(fullName + referencePathSize, name);
- #ifdef DEBUG_LOADER
- PR_fprintf(PR_STDOUT, "\nAttempting to load fully-qualified %s\n",
- fullName);
- #endif
- libSpec.type = PR_LibSpec_Pathname;
- libSpec.value.pathname = fullName;
- dlh = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL
- #ifdef PR_LD_ALT_SEARCH_PATH
- /* allow library's dependencies to be found in the same directory
- * on Windows even if PATH is not set. Requires NSPR 4.8.1 . */
- | PR_LD_ALT_SEARCH_PATH
- #endif
- );
- PORT_Free(fullName);
- }
- }
- return dlh;
- }
- /*
- * Load a shared library called "newShLibName" in the same directory as
- * a shared library that is already loaded, called existingShLibName.
- * A pointer to a static function in that shared library,
- * staticShLibFunc, is required.
- *
- * existingShLibName:
- * The file name of the shared library that shall be used as the
- * "reference library". The loader will attempt to load the requested
- * library from the same directory as the reference library.
- *
- * staticShLibFunc:
- * Pointer to a static function in the "reference library".
- *
- * newShLibName:
- * The simple file name of the new shared library to be loaded.
- *
- * We use PR_GetLibraryFilePathname to get the pathname of the loaded
- * shared lib that contains this function, and then do a
- * PR_LoadLibraryWithFlags with an absolute pathname for the shared
- * library to be loaded.
- *
- * On Windows, the "alternate search path" strategy is employed, if available.
- * On Unix, if existingShLibName is a symbolic link, and no link exists for the
- * new library, the original link will be resolved, and the new library loaded
- * from the resolved location.
- *
- * If the new shared library is not found in the same location as the reference
- * library, it will then be loaded from the normal system library path.
- *
- */
- PRLibrary *
- PORT_LoadLibraryFromOrigin(const char* existingShLibName,
- PRFuncPtr staticShLibFunc,
- const char *newShLibName)
- {
- PRLibrary *lib = NULL;
- char* fullPath = NULL;
- PRLibSpec libSpec;
- /* Get the pathname for existingShLibName, e.g. /usr/lib/libnss3.so
- * PR_GetLibraryFilePathname works with either the base library name or a
- * function pointer, depending on the platform.
- * We require the address of a function in the "reference library",
- * provided by the caller. To avoid getting the address of the stub/thunk
- * of an exported function by accident, use the address of a static
- * function rather than an exported function.
- */
- fullPath = PR_GetLibraryFilePathname(existingShLibName,
- staticShLibFunc);
- if (fullPath) {
- lib = loader_LoadLibInReferenceDir(fullPath, newShLibName);
- #ifdef XP_UNIX
- if (!lib) {
- /*
- * If fullPath is a symbolic link, resolve the symbolic
- * link and try again.
- */
- char* originalfullPath = loader_GetOriginalPathname(fullPath);
- if (originalfullPath) {
- PR_Free(fullPath);
- fullPath = originalfullPath;
- lib = loader_LoadLibInReferenceDir(fullPath, newShLibName);
- }
- }
- #endif
- PR_Free(fullPath);
- }
- if (!lib) {
- #ifdef DEBUG_LOADER
- PR_fprintf(PR_STDOUT, "\nAttempting to load %s\n", newShLibName);
- #endif
- libSpec.type = PR_LibSpec_Pathname;
- libSpec.value.pathname = newShLibName;
- lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
- }
- if (NULL == lib) {
- #ifdef DEBUG_LOADER
- PR_fprintf(PR_STDOUT, "\nLoading failed : %s.\n", newShLibName);
- #endif
- }
- return lib;
- }