Now supports symbolic links correctly, and no longer loads the same shared

library twice.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17929 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-06-27 00:07:42 +00:00
parent 0cd3c003d1
commit fe7f3a2f1d
3 changed files with 70 additions and 36 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2005, Axel Dörfler, [email protected]. * Copyright 2003-2006, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * Copyright 2002, Manuel J. Petit. All rights reserved.
@@ -29,7 +29,7 @@ typedef struct elf_region_t {
typedef struct image_t { typedef struct image_t {
// image identification // image identification
char path[B_OS_NAME_LENGTH]; char path[B_PATH_NAME_LENGTH];
char name[B_OS_NAME_LENGTH]; char name[B_OS_NAME_LENGTH];
image_id id; image_id id;
image_type type; image_type type;
+25 -17
View File
@@ -178,21 +178,15 @@ static image_t *
find_image_in_queue(image_queue_t *queue, const char *name, bool isPath, find_image_in_queue(image_queue_t *queue, const char *name, bool isPath,
uint32 typeMask) uint32 typeMask)
{ {
image_t *iter; image_t *image;
if (isPath) { for (image = queue->head; image; image = image->next) {
for (iter = queue->head; iter; iter = iter->next) { const char *imageName = isPath ? image->path : image->name;
if (strncmp(iter->path, name, sizeof(iter->path)) == 0 int length = isPath ? sizeof(image->path) : sizeof(image->name);
&& typeMask & IMAGE_TYPE_TO_MASK(iter->type)) {
return iter; if (!strncmp(imageName, name, length)
} && (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) {
} return image;
} else {
for (iter = queue->head; iter; iter = iter->next) {
if (strncmp(iter->name, name, sizeof(iter->path)) == 0
&& typeMask & IMAGE_TYPE_TO_MASK(iter->type)) {
return iter;
}
} }
} }
@@ -207,8 +201,7 @@ find_image(char const *name, uint32 typeMask)
image_t *image; image_t *image;
image = find_image_in_queue(&sLoadedImages, name, isPath, typeMask); image = find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
if (image == NULL)
if (!image)
image = find_image_in_queue(&sLoadingImages, name, isPath, typeMask); image = find_image_in_queue(&sLoadingImages, name, isPath, typeMask);
return image; return image;
@@ -891,7 +884,10 @@ load_container(char const *name, image_type type, const char *rpath, image_t **_
// If the path is not absolute, we prepend the CWD to make it one. // If the path is not absolute, we prepend the CWD to make it one.
if (path[0] != '/') { if (path[0] != '/') {
char relativePath[PATH_MAX]; char relativePath[PATH_MAX];
strcpy(relativePath, path); if (!strncmp(path, "./", 2))
strcpy(relativePath, path + 2);
else
strcpy(relativePath, path);
// get the CWD // get the CWD
status = _kern_getcwd(path, sizeof(path)); status = _kern_getcwd(path, sizeof(path));
@@ -909,6 +905,18 @@ load_container(char const *name, image_type type, const char *rpath, image_t **_
} }
} }
// Test again if this image has been registered already - this time,
// we can check the full path, not just its name as noted.
// You could end up loading an image twice with symbolic links, else.
if (type != B_ADD_ON_IMAGE) {
found = find_image(path, APP_OR_LIBRARY_TYPE);
if (found) {
atomic_add(&found->ref_count, 1);
*_image = found;
return B_OK;
}
}
length = _kern_read(fd, 0, &eheader, sizeof(eheader)); length = _kern_read(fd, 0, &eheader, sizeof(eheader));
if (length != sizeof(eheader)) { if (length != sizeof(eheader)) {
status = B_NOT_AN_EXECUTABLE; status = B_NOT_AN_EXECUTABLE;
+43 -17
View File
@@ -78,16 +78,18 @@ search_path_for_type(image_type type)
static int static int
try_open_executable(const char *dir, int dirLen, const char *name, char *path, try_open_executable(const char *dir, int dirLength, const char *name, char *path,
int pathLen) size_t pathLength)
{ {
int nameLen = strlen(name); size_t nameLength = strlen(name);
struct stat stat;
status_t status;
// construct the path // construct the path
if (dirLen > 0) { if (dirLength > 0) {
char *buffer = path; char *buffer = path;
if (dirLen >= 2 && strncmp(dir, "%A", 2) == 0) { if (dirLength >= 2 && strncmp(dir, "%A", 2) == 0) {
// Replace %A with current app folder path (of course, // Replace %A with current app folder path (of course,
// this must be the first part of the path) // this must be the first part of the path)
// ToDo: Maybe using first image info is better suited than // ToDo: Maybe using first image info is better suited than
@@ -98,39 +100,63 @@ try_open_executable(const char *dir, int dirLen, const char *name, char *path,
// copy what's left (when the application name is removed) // copy what's left (when the application name is removed)
if (lastSlash != NULL) { if (lastSlash != NULL) {
strlcpy(buffer, gProgramArgs->program_path, strlcpy(buffer, gProgramArgs->program_path,
min(pathLen, lastSlash + 1 - gProgramArgs->program_path)); min((int)pathLength, lastSlash + 1 - gProgramArgs->program_path));
} else } else
strlcpy(buffer, ".", pathLen); strlcpy(buffer, ".", pathLength);
bytesCopied = strlen(buffer); bytesCopied = strlen(buffer);
buffer += bytesCopied; buffer += bytesCopied;
pathLen -= bytesCopied; pathLength -= bytesCopied;
dir += 2; dir += 2;
dirLen -= 2; dirLength -= 2;
} }
if (dirLen + 1 + nameLen >= pathLen) if (dirLength + 1 + nameLength >= pathLength)
return B_NAME_TOO_LONG; return B_NAME_TOO_LONG;
memcpy(buffer, dir, dirLen); memcpy(buffer, dir, dirLength);
buffer[dirLen] = '/'; buffer[dirLength] = '/';
strcpy(buffer + dirLen + 1, name); strcpy(buffer + dirLength + 1, name);
} else { } else {
if (nameLen >= pathLen) if (nameLength >= pathLength)
return B_NAME_TOO_LONG; return B_NAME_TOO_LONG;
strcpy(path + dirLen + 1, name); strcpy(path + dirLength + 1, name);
} }
TRACE(("runtime_loader: try_open_container(): %s\n", path)); TRACE(("runtime_loader: try_open_container(): %s\n", path));
// Test if the target is a symbolic link, and correct the path in this case
status = _kern_read_stat(-1, path, false, &stat, sizeof(struct stat));
if (status < B_OK)
return status;
if (S_ISLNK(stat.st_mode)) {
char buffer[PATH_MAX];
size_t length = PATH_MAX;
char *lastSlash;
// it's a link, indeed
status = _kern_read_link(-1, path, buffer, &length);
if (status < B_OK)
return status;
lastSlash = strrchr(path, '/');
if (buffer[0] != '/' && lastSlash != NULL) {
// relative path
strlcpy(lastSlash + 1, buffer, lastSlash + 1 - path + pathLength);
} else
strlcpy(path, buffer, pathLength);
}
return _kern_open(-1, path, O_RDONLY, 0); return _kern_open(-1, path, O_RDONLY, 0);
} }
static int static int
search_executable_in_path_list(const char *name, const char *pathList, search_executable_in_path_list(const char *name, const char *pathList,
int pathListLen, char *pathBuffer, int pathBufferLen) int pathListLen, char *pathBuffer, size_t pathBufferLength)
{ {
const char *pathListEnd = pathList + pathListLen; const char *pathListEnd = pathList + pathListLen;
status_t status = B_ENTRY_NOT_FOUND; status_t status = B_ENTRY_NOT_FOUND;
@@ -147,7 +173,7 @@ search_executable_in_path_list(const char *name, const char *pathList,
pathEnd++; pathEnd++;
fd = try_open_executable(pathList, pathEnd - pathList, name, pathBuffer, fd = try_open_executable(pathList, pathEnd - pathList, name, pathBuffer,
pathBufferLen); pathBufferLength);
if (fd >= 0) { if (fd >= 0) {
// see if it's a dir // see if it's a dir
struct stat stat; struct stat stat;