From: Nikodemus S. <de...@us...> - 2010-04-07 16:14:32
|
Update of /cvsroot/sbcl/sbcl/src/runtime In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv32461/src/runtime Modified Files: bsd-os.c darwin-os.c hpux-os.c linux-os.c os.h osf1-os.c runtime.c runtime.h save.c sunos-os.c win32-os.c Log Message: 1.0.37.54: more robust runtime executable path detection Patch by Josh Elsasser. * os_get_runtime_executable_path() extended with an argument to indicate if the returned path should be externally usable (which precludes paths such as /proc/curproc/file). * If os_get_runtime_executable_path() fails, use an argv[0] derived path instead. * Check build_id when saving executable cores to make sure we got the right runtime -- since using the argv[0] method can otherwise go wrong once in a blue moon. Fixes Launchpad #375549. Index: bsd-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/bsd-os.c,v retrieving revision 1.64 retrieving revision 1.65 diff -u -d -r1.64 -r1.65 --- bsd-os.c 4 Oct 2009 16:15:59 -0000 1.64 +++ bsd-os.c 7 Apr 2010 16:14:21 -0000 1.65 @@ -428,7 +428,7 @@ #endif char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { char path[PATH_MAX + 1]; @@ -456,20 +456,16 @@ } #elif defined(LISP_FEATURE_NETBSD) || defined(LISP_FEATURE_OPENBSD) char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { struct stat sb; - char *path = strdup("/proc/curproc/file"); - if (path && ((stat(path, &sb)) == 0)) - return path; - else { - fprintf(stderr, "Couldn't stat /proc/curproc/file; is /proc mounted?\n"); - return NULL; - } + if (!external && stat("/proc/curproc/file", &sb) == 0) + return copied_string("/proc/curproc/file"); + return NULL; } #else /* Not DARWIN or FREEBSD or NETBSD or OPENBSD */ char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { return NULL; } Index: darwin-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/darwin-os.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- darwin-os.c 31 Aug 2009 06:11:12 -0000 1.5 +++ darwin-os.c 7 Apr 2010 16:14:21 -0000 1.6 @@ -24,7 +24,7 @@ #include <errno.h> char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { char path[PATH_MAX + 1]; uint32_t size = sizeof(path); Index: hpux-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/hpux-os.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- hpux-os.c 16 Feb 2009 22:30:25 -0000 1.3 +++ hpux-os.c 7 Apr 2010 16:14:21 -0000 1.4 @@ -135,9 +135,9 @@ } char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { - return copied_string("NOPE"); + return NULL; } /* when inside call_into_lisp, we will first jump to the stub Index: linux-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/linux-os.c,v retrieving revision 1.82 retrieving revision 1.83 diff -u -d -r1.82 -r1.83 --- linux-os.c 1 May 2009 10:30:51 -0000 1.82 +++ linux-os.c 7 Apr 2010 16:14:21 -0000 1.83 @@ -450,7 +450,7 @@ } char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { char path[PATH_MAX + 1]; int size; Index: os.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/os.h,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- os.h 25 Jul 2007 21:37:31 -0000 1.15 +++ os.h 7 Apr 2010 16:14:22 -0000 1.16 @@ -173,8 +173,10 @@ int os_get_errno(void); /* Return an absolute path to the runtime executable, or NULL if this - * information is unavailable. If a non-null pathname is returned, it - * must be 'free'd. */ -extern char *os_get_runtime_executable_path(void); + * information is unavailable. Unless external_path is non-zero the + * returned path may only be valid for the current process, ie: + * something like /proc/curproc/file. If a non-null pathname is + * returned, it must be 'free'd. */ +extern char *os_get_runtime_executable_path(int external_path); #endif Index: osf1-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/osf1-os.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- osf1-os.c 16 Feb 2009 22:30:25 -0000 1.14 +++ osf1-os.c 7 Apr 2010 16:14:22 -0000 1.15 @@ -146,7 +146,7 @@ } char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { return NULL; } Index: runtime.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/runtime.c,v retrieving revision 1.81 retrieving revision 1.82 diff -u -d -r1.81 -r1.82 --- runtime.c 21 May 2009 16:22:55 -0000 1.81 +++ runtime.c 7 Apr 2010 16:14:22 -0000 1.82 @@ -127,6 +127,37 @@ return copied_string(filename); } } + +#ifndef LISP_FEATURE_WIN32 +char * +copied_realpath(const char *pathname) +{ + char *messy, *tidy; + size_t len; + + /* realpath() supposedly can't be counted on to always return + * an absolute path, so we prepend the cwd to relative paths */ + messy = NULL; + if (pathname[0] != '/') { + messy = successful_malloc(PATH_MAX + 1); + if (getcwd(messy, PATH_MAX + 1) == NULL) { + free(messy); + return NULL; + } + len = strlen(messy); + snprintf(messy + len, PATH_MAX + 1 - len, "/%s", pathname); + } + + tidy = successful_malloc(PATH_MAX + 1); + if (realpath((messy ? messy : pathname), tidy) == NULL) { + free(messy); + free(tidy); + return NULL; + } + + return tidy; +} +#endif /* LISP_FEATURE_WIN32 */ /* miscellaneous chattiness */ @@ -205,11 +236,58 @@ return core; } +/* Try to find the path to an executable from argv[0], this is only + * used when os_get_runtime_executable_path() returns NULL */ +#ifdef LISP_FEATURE_WIN32 +char * +search_for_executable(const char *argv0) +{ + return NULL; +} +#else /* LISP_FEATURE_WIN32 */ +char * +search_for_executable(const char *argv0) +{ + char *search, *start, *end, *buf; + + /* If argv[0] contains a slash then it's probably an absolute path + * or relative to the current directory, so check if it exists. */ + if (strchr(argv0, '/') != NULL && access(argv0, F_OK) == 0) + return copied_realpath(argv0); + + /* Bail on an absolute path which doesn't exist */ + if (argv0[0] == '/') + return NULL; + + /* Otherwise check if argv[0] exists relative to any directory in PATH */ + search = getenv("PATH"); + if (search == NULL) + return NULL; + search = copied_string(search); + buf = successful_malloc(PATH_MAX + 1); + for (start = search; (end = strchr(start, ':')) != NULL; start = end + 1) { + *end = '\0'; + snprintf(buf, PATH_MAX + 1, "%s/%s", start, argv0); + if (access(buf, F_OK) == 0) { + free(search); + search = copied_realpath(buf); + free(buf); + return search; + } + } + + free(search); + free(buf); + return NULL; +} +#endif /* LISP_FEATURE_WIN32 */ + char **posix_argv; char *core_string; struct runtime_options *runtime_options; +char *saved_runtime_path = NULL; int main(int argc, char *argv[], char *envp[]) @@ -241,15 +319,22 @@ runtime_options = NULL; + /* Save the argv[0] derived runtime path in case + * os_get_runtime_executable_path(1) isn't able to get an + * externally-usable path later on. */ + saved_runtime_path = search_for_executable(argv[0]); + /* Check early to see if this executable has an embedded core, * which also populates runtime_options if the core has runtime * options */ - runtime_path = os_get_runtime_executable_path(); - if (runtime_path) { - os_vm_offset_t offset = search_for_embedded_core(runtime_path); + runtime_path = os_get_runtime_executable_path(0); + if (runtime_path || saved_runtime_path) { + os_vm_offset_t offset = search_for_embedded_core( + runtime_path ? runtime_path : saved_runtime_path); if (offset != -1) { embedded_core_offset = offset; - core = runtime_path; + core = (runtime_path ? runtime_path : + copied_string(saved_runtime_path)); } else { free(runtime_path); } Index: runtime.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/runtime.h,v retrieving revision 1.35 retrieving revision 1.36 diff -u -d -r1.35 -r1.36 --- runtime.h 29 Jul 2009 15:15:31 -0000 1.35 +++ runtime.h 7 Apr 2010 16:14:22 -0000 1.36 @@ -272,4 +272,7 @@ size_t thread_control_stack_size; }; +/* saved runtime path computed from argv[0] */ +extern char *saved_runtime_path; + #endif /* _SBCL_RUNTIME_H_ */ Index: save.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/save.c,v retrieving revision 1.35 retrieving revision 1.36 diff -u -d -r1.35 -r1.36 --- save.c 11 Nov 2009 19:01:20 -0000 1.35 +++ save.c 7 Apr 2010 16:14:22 -0000 1.36 @@ -383,6 +383,25 @@ exit(0); } +/* Check if the build_id for the current runtime is present in a + * buffer. */ +int +check_runtime_build_id(void *buf, size_t size) +{ + size_t idlen; + char *pos; + + idlen = strlen(build_id) - 1; + while ((pos = memchr(buf, build_id[0], size)) != NULL) { + size -= (pos + 1) - (char *)buf; + buf = (pos + 1); + if (idlen <= size && memcmp(buf, build_id + 1, idlen) == 0) + return 1; + } + + return 0; +} + /* Slurp the executable portion of the runtime into a malloced buffer * and return it. Places the size in bytes of the runtime into * 'size_out'. Returns NULL if the runtime cannot be loaded from @@ -414,6 +433,12 @@ goto lose; } + if (!check_runtime_build_id(buf, size)) { + fprintf(stderr, "Failed to locate current build_id in runtime: %s\n", + runtime_path); + goto lose; + } + fclose(input); *size_out = size; return buf; @@ -460,15 +485,19 @@ char *runtime_path; if (prepend_runtime) { - runtime_path = os_get_runtime_executable_path(); + runtime_path = os_get_runtime_executable_path(0); - if (runtime_path == NULL) { + if (runtime_path == NULL && saved_runtime_path == NULL) { fprintf(stderr, "Unable to get default runtime path.\n"); return NULL; } - *runtime_bytes = load_runtime(runtime_path, runtime_size); - free(runtime_path); + if (runtime_path == NULL) + *runtime_bytes = load_runtime(saved_runtime_path, runtime_size); + else { + *runtime_bytes = load_runtime(runtime_path, runtime_size); + free(runtime_path); + } if (*runtime_bytes == NULL) return 0; Index: sunos-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/sunos-os.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- sunos-os.c 22 Mar 2009 22:34:58 -0000 1.28 +++ sunos-os.c 7 Apr 2010 16:14:22 -0000 1.29 @@ -234,13 +234,11 @@ } char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { - int ret; char path[] = "/proc/self/object/a.out"; - ret = access(path, R_OK); - if (ret == -1) + if (external || access(path, R_OK) == -1) return NULL; return copied_string(path); Index: win32-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/win32-os.c,v retrieving revision 1.38 retrieving revision 1.39 diff -u -d -r1.38 -r1.39 --- win32-os.c 1 Mar 2010 16:32:56 -0000 1.38 +++ win32-os.c 7 Apr 2010 16:14:23 -0000 1.39 @@ -582,7 +582,7 @@ } char * -os_get_runtime_executable_path() +os_get_runtime_executable_path(int external) { char path[MAX_PATH + 1]; DWORD bufsize = sizeof(path); |