From 12a5e9a4a272ed7be3e7acd74d3817367efefee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 17 Feb 2008 16:38:07 +0000 Subject: [PATCH] bonefish+axeld: The runtime loader did not correctly resolve %A correctly with the actual normalized program path. IOW it would not work correctly with symlinks to applications that had their own lib directory. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23986 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/runtime_loader/elf.cpp | 19 +++++++-- src/system/runtime_loader/runtime_loader.c | 39 ++++++++++--------- .../runtime_loader/runtime_loader_private.h | 5 ++- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index bba4cd4dd6..cdc5738c30 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -263,8 +263,21 @@ find_loaded_image_by_id(image_id id) } +static const char * +get_program_path() +{ + for (image_t *image = sLoadedImages.head; image; image = image->next) { + if (image->type == B_APP_IMAGE) + return image->path; + } + + return NULL; +} + + static status_t -parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, int32 *_sheaderSize) +parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, + int32 *_sheaderSize) { if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) return B_NOT_AN_EXECUTABLE; @@ -990,7 +1003,7 @@ load_container(char const *name, image_type type, const char *rpath, image_t **_ strlcpy(path, name, sizeof(path)); // Try to load explicit image path first - fd = open_executable(path, type, rpath); + fd = open_executable(path, type, rpath, get_program_path()); if (fd < 0) { FATAL("cannot open file %s\n", path); KTRACE("rld: load_container(\"%s\"): failed to open file", name); diff --git a/src/system/runtime_loader/runtime_loader.c b/src/system/runtime_loader/runtime_loader.c index 90524c3024..3b8a75890e 100644 --- a/src/system/runtime_loader/runtime_loader.c +++ b/src/system/runtime_loader/runtime_loader.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -82,8 +82,8 @@ search_path_for_type(image_type type) static int -try_open_executable(const char *dir, int dirLength, const char *name, char *path, - size_t pathLength) +try_open_executable(const char *dir, int dirLength, const char *name, + const char *programPath, char *path, size_t pathLength) { size_t nameLength = strlen(name); struct stat stat; @@ -93,18 +93,19 @@ try_open_executable(const char *dir, int dirLength, const char *name, char *path if (dirLength > 0) { char *buffer = path; + if (programPath == NULL) + programPath = gProgramArgs->program_path; + if (dirLength >= 2 && strncmp(dir, "%A", 2) == 0) { // Replace %A with current app folder path (of course, // this must be the first part of the path) - // ToDo: Maybe using first image info is better suited than - // gProgamArgs->program_path here? - char *lastSlash = strrchr(gProgramArgs->program_path, '/'); + char *lastSlash = strrchr(programPath, '/'); int bytesCopied; // copy what's left (when the application name is removed) if (lastSlash != NULL) { - strlcpy(buffer, gProgramArgs->program_path, - min((int)pathLength, lastSlash + 1 - gProgramArgs->program_path)); + strlcpy(buffer, programPath, + min((int)pathLength, lastSlash + 1 - programPath)); } else strlcpy(buffer, ".", pathLength); @@ -160,7 +161,8 @@ try_open_executable(const char *dir, int dirLength, const char *name, char *path static int search_executable_in_path_list(const char *name, const char *pathList, - int pathListLen, char *pathBuffer, size_t pathBufferLength) + int pathListLen, const char *programPath, char *pathBuffer, + size_t pathBufferLength) { const char *pathListEnd = pathList + pathListLen; status_t status = B_ENTRY_NOT_FOUND; @@ -176,8 +178,8 @@ search_executable_in_path_list(const char *name, const char *pathList, while (pathEnd < pathListEnd && *pathEnd != ':') pathEnd++; - fd = try_open_executable(pathList, pathEnd - pathList, name, pathBuffer, - pathBufferLength); + fd = try_open_executable(pathList, pathEnd - pathList, name, + programPath, pathBuffer, pathBufferLength); if (fd >= 0) { // see if it's a dir struct stat stat; @@ -199,7 +201,8 @@ search_executable_in_path_list(const char *name, const char *pathList, int -open_executable(char *name, image_type type, const char *rpath) +open_executable(char *name, image_type type, const char *rpath, + const char *programPath) { const char *paths; char buffer[PATH_MAX]; @@ -214,7 +217,7 @@ open_executable(char *name, image_type type, const char *rpath) // Even though ELF specs don't say this, we give shared libraries // another chance and look them up in the usual search paths - at // least that seems to be what BeOS does, and since it doesn't hurt... - paths = strrchr(name, '/'); + paths = strrchr(name, '/') + 1; memmove(name, paths, strlen(paths) + 1); } @@ -229,11 +232,11 @@ open_executable(char *name, image_type type, const char *rpath) // If there is no ';', we set only secondList to simplify things. if (firstList) { fd = search_executable_in_path_list(name, firstList, - semicolon - firstList, buffer, sizeof(buffer)); + semicolon - firstList, programPath, buffer, sizeof(buffer)); } if (fd < 0) { fd = search_executable_in_path_list(name, secondList, - strlen(secondList), buffer, sizeof(buffer)); + strlen(secondList), programPath, buffer, sizeof(buffer)); } } @@ -242,13 +245,13 @@ open_executable(char *name, image_type type, const char *rpath) paths = search_path_for_type(type); if (paths) { fd = search_executable_in_path_list(name, paths, strlen(paths), - buffer, sizeof(buffer)); + programPath, buffer, sizeof(buffer)); } } if (fd >= 0) { // we found it, copy path! - TRACE(("runtime_loader: open_container(%s): found at %s\n", name, buffer)); + TRACE(("runtime_loader: open_executable(%s): found at %s\n", name, buffer)); strlcpy(name, buffer, PATH_MAX); } @@ -278,7 +281,7 @@ test_executable(const char *name, uid_t user, gid_t group, char *invoker) strlcpy(path, name, sizeof(path)); - fd = open_executable(path, B_APP_IMAGE, NULL); + fd = open_executable(path, B_APP_IMAGE, NULL, NULL); if (fd < B_OK) return fd; diff --git a/src/system/runtime_loader/runtime_loader_private.h b/src/system/runtime_loader/runtime_loader_private.h index 530c685a07..1e2185a24e 100644 --- a/src/system/runtime_loader/runtime_loader_private.h +++ b/src/system/runtime_loader/runtime_loader_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -23,7 +23,8 @@ extern "C" { #endif int runtime_loader(void *arg); -int open_executable(char *name, image_type type, const char *rpath); +int open_executable(char *name, image_type type, const char *rpath, + const char *programPath); status_t test_executable(const char *path, uid_t user, gid_t group, char *starter);