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.
|
* 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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user