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:
@@ -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.
|
||||
*
|
||||
* Copyright 2002, Manuel J. Petit. All rights reserved.
|
||||
@@ -29,7 +29,7 @@ typedef struct elf_region_t {
|
||||
|
||||
typedef struct image_t {
|
||||
// image identification
|
||||
char path[B_OS_NAME_LENGTH];
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
char name[B_OS_NAME_LENGTH];
|
||||
image_id id;
|
||||
image_type type;
|
||||
|
||||
@@ -178,21 +178,15 @@ static image_t *
|
||||
find_image_in_queue(image_queue_t *queue, const char *name, bool isPath,
|
||||
uint32 typeMask)
|
||||
{
|
||||
image_t *iter;
|
||||
image_t *image;
|
||||
|
||||
if (isPath) {
|
||||
for (iter = queue->head; iter; iter = iter->next) {
|
||||
if (strncmp(iter->path, name, sizeof(iter->path)) == 0
|
||||
&& typeMask & IMAGE_TYPE_TO_MASK(iter->type)) {
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
for (image = queue->head; image; image = image->next) {
|
||||
const char *imageName = isPath ? image->path : image->name;
|
||||
int length = isPath ? sizeof(image->path) : sizeof(image->name);
|
||||
|
||||
if (!strncmp(imageName, name, length)
|
||||
&& (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,8 +201,7 @@ find_image(char const *name, uint32 typeMask)
|
||||
image_t *image;
|
||||
|
||||
image = find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
|
||||
|
||||
if (!image)
|
||||
if (image == NULL)
|
||||
image = find_image_in_queue(&sLoadingImages, name, isPath, typeMask);
|
||||
|
||||
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 (path[0] != '/') {
|
||||
char relativePath[PATH_MAX];
|
||||
strcpy(relativePath, path);
|
||||
if (!strncmp(path, "./", 2))
|
||||
strcpy(relativePath, path + 2);
|
||||
else
|
||||
strcpy(relativePath, path);
|
||||
|
||||
// get the CWD
|
||||
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));
|
||||
if (length != sizeof(eheader)) {
|
||||
status = B_NOT_AN_EXECUTABLE;
|
||||
|
||||
@@ -78,16 +78,18 @@ search_path_for_type(image_type type)
|
||||
|
||||
|
||||
static int
|
||||
try_open_executable(const char *dir, int dirLen, const char *name, char *path,
|
||||
int pathLen)
|
||||
try_open_executable(const char *dir, int dirLength, const char *name, char *path,
|
||||
size_t pathLength)
|
||||
{
|
||||
int nameLen = strlen(name);
|
||||
size_t nameLength = strlen(name);
|
||||
struct stat stat;
|
||||
status_t status;
|
||||
|
||||
// construct the path
|
||||
if (dirLen > 0) {
|
||||
if (dirLength > 0) {
|
||||
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,
|
||||
// this must be the first part of the path)
|
||||
// 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)
|
||||
if (lastSlash != NULL) {
|
||||
strlcpy(buffer, gProgramArgs->program_path,
|
||||
min(pathLen, lastSlash + 1 - gProgramArgs->program_path));
|
||||
min((int)pathLength, lastSlash + 1 - gProgramArgs->program_path));
|
||||
} else
|
||||
strlcpy(buffer, ".", pathLen);
|
||||
strlcpy(buffer, ".", pathLength);
|
||||
|
||||
bytesCopied = strlen(buffer);
|
||||
buffer += bytesCopied;
|
||||
pathLen -= bytesCopied;
|
||||
pathLength -= bytesCopied;
|
||||
dir += 2;
|
||||
dirLen -= 2;
|
||||
dirLength -= 2;
|
||||
}
|
||||
|
||||
if (dirLen + 1 + nameLen >= pathLen)
|
||||
if (dirLength + 1 + nameLength >= pathLength)
|
||||
return B_NAME_TOO_LONG;
|
||||
|
||||
memcpy(buffer, dir, dirLen);
|
||||
buffer[dirLen] = '/';
|
||||
strcpy(buffer + dirLen + 1, name);
|
||||
memcpy(buffer, dir, dirLength);
|
||||
buffer[dirLength] = '/';
|
||||
strcpy(buffer + dirLength + 1, name);
|
||||
} else {
|
||||
if (nameLen >= pathLen)
|
||||
if (nameLength >= pathLength)
|
||||
return B_NAME_TOO_LONG;
|
||||
|
||||
strcpy(path + dirLen + 1, name);
|
||||
strcpy(path + dirLength + 1, name);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
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;
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
@@ -147,7 +173,7 @@ search_executable_in_path_list(const char *name, const char *pathList,
|
||||
pathEnd++;
|
||||
|
||||
fd = try_open_executable(pathList, pathEnd - pathList, name, pathBuffer,
|
||||
pathBufferLen);
|
||||
pathBufferLength);
|
||||
if (fd >= 0) {
|
||||
// see if it's a dir
|
||||
struct stat stat;
|
||||
|
||||
Reference in New Issue
Block a user