PageRenderTime 22ms CodeModel.GetById 13ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  1/*
  2 * ***** BEGIN LICENSE BLOCK *****
  3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4 *
  5 * The contents of this file are subject to the Mozilla Public License Version
  6 * 1.1 (the "License"); you may not use this file except in compliance with
  7 * the License. You may obtain a copy of the License at
  8 * http://www.mozilla.org/MPL/
  9 *
 10 * Software distributed under the License is distributed on an "AS IS" basis,
 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 12 * for the specific language governing rights and limitations under the
 13 * License.
 14 *
 15 * The Original Code is the Netscape security libraries.
 16 *
 17 * The Initial Developer of the Original Code is
 18 * Netscape Communications Corporation.
 19 * Portions created by the Initial Developer are Copyright (C) 2000
 20 * the Initial Developer. All Rights Reserved.
 21 *
 22 * Contributor(s):
 23 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
 24 *   Kai Engert <kengert@redhat.com>
 25 *
 26 * Alternatively, the contents of this file may be used under the terms of
 27 * either the GNU General Public License Version 2 or later (the "GPL"), or
 28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 29 * in which case the provisions of the GPL or the LGPL are applicable instead
 30 * of those above. If you wish to allow use of your version of this file only
 31 * under the terms of either the GPL or the LGPL, and not to allow others to
 32 * use your version of this file under the terms of the MPL, indicate your
 33 * decision by deleting the provisions above and replace them with the notice
 34 * and other provisions required by the GPL or the LGPL. If you do not delete
 35 * the provisions above, a recipient may use your version of this file under
 36 * the terms of any one of the MPL, the GPL or the LGPL.
 37 *
 38 * ***** END LICENSE BLOCK ***** */
 39
 40#include "secport.h"
 41#include "nspr.h"
 42
 43#ifdef XP_UNIX
 44#include <unistd.h>
 45#define BL_MAXSYMLINKS 20
 46
 47/*
 48 * If 'link' is a symbolic link, this function follows the symbolic links
 49 * and returns the pathname of the ultimate source of the symbolic links.
 50 * If 'link' is not a symbolic link, this function returns NULL.
 51 * The caller should call PR_Free to free the string returned by this
 52 * function.
 53 */
 54static char* loader_GetOriginalPathname(const char* link)
 55{
 56    char* resolved = NULL;
 57    char* input = NULL;
 58    PRUint32 iterations = 0;
 59    PRInt32 len = 0, retlen = 0;
 60    if (!link) {
 61        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
 62        return NULL;
 63    }
 64    len = PR_MAX(1024, strlen(link) + 1);
 65    resolved = PR_Malloc(len);
 66    input = PR_Malloc(len);
 67    if (!resolved || !input) {
 68        if (resolved) {
 69            PR_Free(resolved);
 70        }
 71        if (input) {
 72            PR_Free(input);
 73        }
 74        return NULL;
 75    }
 76    strcpy(input, link);
 77    while ( (iterations++ < BL_MAXSYMLINKS) &&
 78            ( (retlen = readlink(input, resolved, len - 1)) > 0) ) {
 79        char* tmp = input;
 80        resolved[retlen] = '\0'; /* NULL termination */
 81        input = resolved;
 82        resolved = tmp;
 83    }
 84    PR_Free(resolved);
 85    if (iterations == 1 && retlen < 0) {
 86        PR_Free(input);
 87        input = NULL;
 88    }
 89    return input;
 90}
 91#endif /* XP_UNIX */
 92
 93/*
 94 * Load the library with the file name 'name' residing in the same
 95 * directory as the reference library, whose pathname is 'referencePath'.
 96 */
 97static PRLibrary *
 98loader_LoadLibInReferenceDir(const char *referencePath, const char *name)
 99{
100    PRLibrary *dlh = NULL;
101    char *fullName = NULL;
102    char* c;
103    PRLibSpec libSpec;
104
105    /* Remove the trailing filename from referencePath and add the new one */
106    c = strrchr(referencePath, PR_GetDirectorySeparator());
107    if (c) {
108        size_t referencePathSize = 1 + c - referencePath;
109        fullName = (char*) PORT_Alloc(strlen(name) + referencePathSize + 1);
110        if (fullName) {
111            memcpy(fullName, referencePath, referencePathSize);
112            strcpy(fullName + referencePathSize, name); 
113#ifdef DEBUG_LOADER
114            PR_fprintf(PR_STDOUT, "\nAttempting to load fully-qualified %s\n", 
115                       fullName);
116#endif
117            libSpec.type = PR_LibSpec_Pathname;
118            libSpec.value.pathname = fullName;
119            dlh = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL
120#ifdef PR_LD_ALT_SEARCH_PATH
121            /* allow library's dependencies to be found in the same directory
122             * on Windows even if PATH is not set. Requires NSPR 4.8.1 . */
123                                          | PR_LD_ALT_SEARCH_PATH 
124#endif
125                                          );
126            PORT_Free(fullName);
127        }
128    }
129    return dlh;
130}
131
132/*
133 * Load a shared library called "newShLibName" in the same directory as
134 * a shared library that is already loaded, called existingShLibName.
135 * A pointer to a static function in that shared library,
136 * staticShLibFunc, is required.
137 *
138 * existingShLibName:
139 *   The file name of the shared library that shall be used as the 
140 *   "reference library". The loader will attempt to load the requested
141 *   library from the same directory as the reference library.
142 *
143 * staticShLibFunc:
144 *   Pointer to a static function in the "reference library".
145 *
146 * newShLibName:
147 *   The simple file name of the new shared library to be loaded.
148 *
149 * We use PR_GetLibraryFilePathname to get the pathname of the loaded 
150 * shared lib that contains this function, and then do a
151 * PR_LoadLibraryWithFlags with an absolute pathname for the shared
152 * library to be loaded.
153 *
154 * On Windows, the "alternate search path" strategy is employed, if available.
155 * On Unix, if existingShLibName is a symbolic link, and no link exists for the
156 * new library, the original link will be resolved, and the new library loaded
157 * from the resolved location.
158 *
159 * If the new shared library is not found in the same location as the reference
160 * library, it will then be loaded from the normal system library path.
161 *
162 */
163
164PRLibrary *
165PORT_LoadLibraryFromOrigin(const char* existingShLibName,
166                 PRFuncPtr staticShLibFunc,
167                 const char *newShLibName)
168{
169    PRLibrary *lib = NULL;
170    char* fullPath = NULL;
171    PRLibSpec libSpec;
172
173    /* Get the pathname for existingShLibName, e.g. /usr/lib/libnss3.so
174     * PR_GetLibraryFilePathname works with either the base library name or a
175     * function pointer, depending on the platform.
176     * We require the address of a function in the "reference library",
177     * provided by the caller. To avoid getting the address of the stub/thunk
178     * of an exported function by accident, use the address of a static
179     * function rather than an exported function.
180     */
181    fullPath = PR_GetLibraryFilePathname(existingShLibName,
182                                         staticShLibFunc);
183
184    if (fullPath) {
185        lib = loader_LoadLibInReferenceDir(fullPath, newShLibName);
186#ifdef XP_UNIX
187        if (!lib) {
188            /*
189             * If fullPath is a symbolic link, resolve the symbolic
190             * link and try again.
191             */
192            char* originalfullPath = loader_GetOriginalPathname(fullPath);
193            if (originalfullPath) {
194                PR_Free(fullPath);
195                fullPath = originalfullPath;
196                lib = loader_LoadLibInReferenceDir(fullPath, newShLibName);
197            }
198        }
199#endif
200        PR_Free(fullPath);
201    }
202    if (!lib) {
203#ifdef DEBUG_LOADER
204        PR_fprintf(PR_STDOUT, "\nAttempting to load %s\n", newShLibName);
205#endif
206        libSpec.type = PR_LibSpec_Pathname;
207        libSpec.value.pathname = newShLibName;
208        lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
209    }
210    if (NULL == lib) {
211#ifdef DEBUG_LOADER
212        PR_fprintf(PR_STDOUT, "\nLoading failed : %s.\n", newShLibName);
213#endif
214    }
215    return lib;
216}
217