X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=crypto%2Fdso%2Fdso_dlfcn.c;h=2d7534afac7d4b683e0f079cc2d9ce50fdde4880;hb=1642000707b91d26ae7bc238838786c4bb56cfc1;hp=681e9782ad14d822bb69d7856efd47d7cac994f0;hpb=b7b6c047ca5badf3d76187ad2640e5f088e96ecd;p=openssl.git diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c index 681e9782ad..2d7534afac 100644 --- a/crypto/dso/dso_dlfcn.c +++ b/crypto/dso/dso_dlfcn.c @@ -1,4 +1,4 @@ -/* dso_dlfcn.c */ +/* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ @@ -85,6 +85,8 @@ static int dlfcn_finish(DSO *dso); static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); #endif static char *dlfcn_name_converter(DSO *dso, const char *filename); +static char *dlfcn_merger(DSO *dso, const char *filespec1, + const char *filespec2); static DSO_METHOD dso_meth_dlfcn = { "OpenSSL 'dlfcn' shared library method", @@ -99,6 +101,7 @@ static DSO_METHOD dso_meth_dlfcn = { #endif NULL, /* ctrl */ dlfcn_name_converter, + dlfcn_merger, NULL, /* init */ NULL /* finish */ }; @@ -114,7 +117,7 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) * as we don't have autoconf yet, I'm implementing a hack that could * be hacked further relatively easily to deal with cases as we find * them. Initially this is to cope with OpenBSD. */ -#ifdef __OpenBSD__ +#if defined(__OpenBSD__) || defined(__NetBSD__) # ifdef DL_LAZY # define DLOPEN_FLAG DL_LAZY # else @@ -125,7 +128,11 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) # endif # endif #else -# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */ +# ifdef OPENSSL_SYS_SUNOS +# define DLOPEN_FLAG 1 +# else +# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */ +# endif #endif /* For this DSO_METHOD, our meth_data STACK will contain; @@ -137,17 +144,23 @@ static int dlfcn_load(DSO *dso) void *ptr = NULL; /* See applicable comments in dso_dl.c */ char *filename = DSO_convert_filename(dso, NULL); + int flags = DLOPEN_FLAG; if(filename == NULL) { DSOerr(DSO_F_DLFCN_LOAD,DSO_R_NO_FILENAME); goto err; } - ptr = dlopen(filename, DLOPEN_FLAG); + +#ifdef RTLD_GLOBAL + if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS) + flags |= RTLD_GLOBAL; +#endif + ptr = dlopen(filename, flags); if(ptr == NULL) { DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); - ERR_add_error_data(3, "filename(", filename, ")"); + ERR_add_error_data(4, "filename(", filename, "): ", dlerror()); goto err; } if(!sk_push(dso->meth_data, (char *)ptr)) @@ -215,7 +228,7 @@ static void *dlfcn_bind_var(DSO *dso, const char *symname) if(sym == NULL) { DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_SYM_FAILURE); - ERR_add_error_data(3, "symname(", symname, ")"); + ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); return(NULL); } return(sym); @@ -246,12 +259,79 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) if(sym == NULL) { DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE); - ERR_add_error_data(3, "symname(", symname, ")"); + ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); return(NULL); } return(sym); } +static char *dlfcn_merger(DSO *dso, const char *filespec1, + const char *filespec2) + { + char *merged; + + if(!filespec1 && !filespec2) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + /* If the first file specification is a rooted path, it rules. + same goes if the second file specification is missing. */ + if (!filespec2 || filespec1[0] == '/') + { + merged = OPENSSL_malloc(strlen(filespec1) + 1); + if(!merged) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec1); + } + /* If the first file specification is missing, the second one rules. */ + else if (!filespec1) + { + merged = OPENSSL_malloc(strlen(filespec2) + 1); + if(!merged) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec2); + } + else + /* This part isn't as trivial as it looks. It assumes that + the second file specification really is a directory, and + makes no checks whatsoever. Therefore, the result becomes + the concatenation of filespec2 followed by a slash followed + by filespec1. */ + { + int spec2len, len; + + spec2len = (filespec2 ? strlen(filespec2) : 0); + len = spec2len + (filespec1 ? strlen(filespec1) : 0); + + if(filespec2 && filespec2[spec2len - 1] == '/') + { + spec2len--; + len--; + } + merged = OPENSSL_malloc(len + 2); + if(!merged) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec2); + merged[spec2len] = '/'; + strcpy(&merged[spec2len + 1], filespec1); + } + return(merged); + } + static char *dlfcn_name_converter(DSO *dso, const char *filename) { char *translated;