/* * ***** 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 , Sun Microsystems Laboratories * Kai Engert * * 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 ***** */ /* * This file is meant to be included by other .c files. * This file takes a "parameter", the scope which includes this * code shall declare this variable: * const char *NameOfThisSharedLib; * * NameOfThisSharedLib: * 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. */ #ifdef XP_UNIX #include #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); PORT_Free(fullName); } } return dlh; } /* * We use PR_GetLibraryFilePathname to get the pathname of the loaded * shared lib that contains this function, and then do a PR_LoadLibrary * with an absolute pathname for the softoken shared library. */ static PRLibrary * loader_LoadLibrary(const char *nameToLoad) { PRLibrary *lib = NULL; char* fullPath = NULL; PRLibSpec libSpec; /* Get the pathname for nameOfAlreadyLoadedLib, i.e. /usr/lib/libnss3.so * PR_GetLibraryFilePathname works with either the base library name or a * function pointer, depending on the platform. We can't query an exported * symbol such as NSC_GetFunctionList, because on some platforms we can't * find symbols in loaded implicit dependencies. * But we can just get the address of this function ! */ fullPath = PR_GetLibraryFilePathname(NameOfThisSharedLib, (PRFuncPtr)&loader_LoadLibrary); if (fullPath) { lib = loader_LoadLibInReferenceDir(fullPath, nameToLoad); #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, nameToLoad); } } #endif PR_Free(fullPath); } if (!lib) { #ifdef DEBUG_LOADER PR_fprintf(PR_STDOUT, "\nAttempting to load %s\n", nameToLoad); #endif libSpec.type = PR_LibSpec_Pathname; libSpec.value.pathname = nameToLoad; lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL); } if (NULL == lib) { #ifdef DEBUG_LOADER PR_fprintf(PR_STDOUT, "\nLoading failed : %s.\n", nameToLoad); #endif } return lib; }