Add get_*architecture() API, extend find_path*() API
* Add get_architecture(), get_primary_architecture(), get_secondary_architectures(), guess_architecture_for_path() to get the caller's architecture, the primary architecture, all secondary architectures, or the architecture associated with a specified path respectively. * Rename the find_path*() functions to find_path*_etc() and add an optional architecture parameter. Add simplified find_path*() functions. * BPathFinder: Add FindPath[s]() versions with an architecture parameter.
This commit is contained in:
@@ -170,16 +170,26 @@ extern "C" {
|
|||||||
status_t find_directory(directory_which which, dev_t volume, bool createIt,
|
status_t find_directory(directory_which which, dev_t volume, bool createIt,
|
||||||
char* pathString, int32 length);
|
char* pathString, int32 length);
|
||||||
|
|
||||||
status_t find_path(const void* codePointer, const char* dependency,
|
status_t find_path(const void* codePointer, path_base_directory baseDirectory,
|
||||||
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
const char* subPath, char* pathBuffer, size_t bufferSize);
|
||||||
char* pathBuffer, size_t bufferSize);
|
|
||||||
|
|
||||||
status_t find_path_for_path(const char* path, const char* dependency,
|
status_t find_path_etc(const void* codePointer, const char* dependency,
|
||||||
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
const char* architecture, path_base_directory baseDirectory,
|
||||||
char* pathBuffer, size_t bufferSize);
|
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize);
|
||||||
|
|
||||||
|
status_t find_path_for_path(const char* path, path_base_directory baseDirectory,
|
||||||
|
const char* subPath, char* pathBuffer, size_t bufferSize);
|
||||||
|
|
||||||
|
status_t find_path_for_path_etc(const char* path, const char* dependency,
|
||||||
|
const char* architecture, path_base_directory baseDirectory,
|
||||||
|
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize);
|
||||||
|
|
||||||
status_t find_paths(path_base_directory baseDirectory, const char* subPath,
|
status_t find_paths(path_base_directory baseDirectory, const char* subPath,
|
||||||
uint32 flags, char*** _paths, size_t* _pathCount);
|
char*** _paths, size_t* _pathCount);
|
||||||
|
|
||||||
|
status_t find_paths_etc(const char* architecture,
|
||||||
|
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
||||||
|
char*** _paths, size_t* _pathCount);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ public:
|
|||||||
status_t SetTo(const entry_ref& ref,
|
status_t SetTo(const entry_ref& ref,
|
||||||
const char* dependency = NULL);
|
const char* dependency = NULL);
|
||||||
|
|
||||||
|
status_t FindPath(const char* architecture,
|
||||||
|
path_base_directory baseDirectory,
|
||||||
|
const char* subPath, uint32 flags,
|
||||||
|
BPath& path);
|
||||||
status_t FindPath(path_base_directory baseDirectory,
|
status_t FindPath(path_base_directory baseDirectory,
|
||||||
const char* subPath, uint32 flags,
|
const char* subPath, uint32 flags,
|
||||||
BPath& path);
|
BPath& path);
|
||||||
@@ -39,6 +43,10 @@ public:
|
|||||||
status_t FindPath(path_base_directory baseDirectory,
|
status_t FindPath(path_base_directory baseDirectory,
|
||||||
BPath& path);
|
BPath& path);
|
||||||
|
|
||||||
|
static status_t FindPaths(const char* architecture,
|
||||||
|
path_base_directory baseDirectory,
|
||||||
|
const char* subPath, uint32 flags,
|
||||||
|
BStringList& paths);
|
||||||
static status_t FindPaths(path_base_directory baseDirectory,
|
static status_t FindPaths(path_base_directory baseDirectory,
|
||||||
const char* subPath, uint32 flags,
|
const char* subPath, uint32 flags,
|
||||||
BStringList& paths);
|
BStringList& paths);
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _SUPPORT_ARCHITECTURE_H
|
||||||
|
#define _SUPPORT_ARCHITECTURE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
const char* get_architecture();
|
||||||
|
const char* get_primary_architecture();
|
||||||
|
size_t get_secondary_architectures(const char** architectures,
|
||||||
|
size_t count);
|
||||||
|
const char* guess_architecture_for_path(const char* path);
|
||||||
|
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _SUPPORT_ARCHITECTURE_H */
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _SYSTEM_ARCHITECTURE_PRIVATE_H
|
||||||
|
#define _SYSTEM_ARCHITECTURE_PRIVATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Architecture.h>
|
||||||
|
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
const char* __get_architecture();
|
||||||
|
const char* __get_primary_architecture();
|
||||||
|
size_t __get_secondary_architectures(const char** architectures,
|
||||||
|
size_t count);
|
||||||
|
const char* __guess_architecture_for_path(const char* path);
|
||||||
|
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _SYSTEM_ARCHITECTURE_PRIVATE_H */
|
||||||
@@ -17,16 +17,31 @@ __BEGIN_DECLS
|
|||||||
status_t __find_directory(directory_which which, dev_t device, bool createIt,
|
status_t __find_directory(directory_which which, dev_t device, bool createIt,
|
||||||
char *returnedPath, int32 pathLength);
|
char *returnedPath, int32 pathLength);
|
||||||
|
|
||||||
status_t __find_path(const void* codePointer, const char* dependency,
|
status_t __find_path(const void* codePointer, path_base_directory baseDirectory,
|
||||||
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
const char* subPath, char* pathBuffer, size_t bufferSize);
|
||||||
char* pathBuffer, size_t bufferSize);
|
|
||||||
|
|
||||||
status_t __find_path_for_path(const char* path, const char* dependency,
|
status_t __find_path_etc(const void* codePointer, const char* dependency,
|
||||||
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
const char* architecture, path_base_directory baseDirectory,
|
||||||
char* pathBuffer, size_t bufferSize);
|
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize);
|
||||||
|
|
||||||
|
status_t __find_path_for_path(const char* path,
|
||||||
|
path_base_directory baseDirectory, const char* subPath, char* pathBuffer,
|
||||||
|
size_t bufferSize);
|
||||||
|
|
||||||
|
status_t __find_path_for_path_etc(const char* path, const char* dependency,
|
||||||
|
const char* architecture, path_base_directory baseDirectory,
|
||||||
|
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize);
|
||||||
|
|
||||||
status_t __find_paths(path_base_directory baseDirectory, const char* subPath,
|
status_t __find_paths(path_base_directory baseDirectory, const char* subPath,
|
||||||
uint32 flags, char*** _paths, size_t* _pathCount);
|
char*** _paths, size_t* _pathCount);
|
||||||
|
|
||||||
|
status_t __find_paths_etc(const char* architecture,
|
||||||
|
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
||||||
|
char*** _paths, size_t* _pathCount);
|
||||||
|
|
||||||
|
const char* __guess_secondary_architecture_from_path(const char* path,
|
||||||
|
const char* const* secondaryArchitectures,
|
||||||
|
size_t secondaryArchitectureCount);
|
||||||
|
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|||||||
@@ -55,9 +55,11 @@ BPathFinder::SetTo(const entry_ref& ref, const char* dependency)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPathFinder::FindPath(path_base_directory baseDirectory, const char* subPath,
|
BPathFinder::FindPath(const char* architecture,
|
||||||
uint32 flags, BPath& path)
|
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
||||||
|
BPath& path)
|
||||||
{
|
{
|
||||||
path.Unset();
|
path.Unset();
|
||||||
|
|
||||||
@@ -71,11 +73,11 @@ BPathFinder::FindPath(path_base_directory baseDirectory, const char* subPath,
|
|||||||
status_t error;
|
status_t error;
|
||||||
|
|
||||||
if (!fPath.IsEmpty()) {
|
if (!fPath.IsEmpty()) {
|
||||||
error = find_path_for_path(fPath, dependency, baseDirectory, subPath,
|
error = find_path_for_path_etc(fPath, dependency, architecture,
|
||||||
flags, pathBuffer, sizeof(pathBuffer));
|
baseDirectory, subPath, flags, pathBuffer, sizeof(pathBuffer));
|
||||||
} else {
|
} else {
|
||||||
error = find_path(fCodePointer, dependency, baseDirectory, subPath,
|
error = find_path_etc(fCodePointer, dependency, architecture,
|
||||||
flags, pathBuffer, sizeof(pathBuffer));
|
baseDirectory, subPath, flags, pathBuffer, sizeof(pathBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -84,33 +86,41 @@ BPathFinder::FindPath(path_base_directory baseDirectory, const char* subPath,
|
|||||||
return path.SetTo(pathBuffer);
|
return path.SetTo(pathBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BPathFinder::FindPath(path_base_directory baseDirectory, const char* subPath,
|
||||||
|
uint32 flags, BPath& path)
|
||||||
|
{
|
||||||
|
return FindPath(NULL, baseDirectory, subPath, flags, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPathFinder::FindPath(path_base_directory baseDirectory, const char* subPath,
|
BPathFinder::FindPath(path_base_directory baseDirectory, const char* subPath,
|
||||||
BPath& path)
|
BPath& path)
|
||||||
{
|
{
|
||||||
return FindPath(baseDirectory, subPath, 0, path);
|
return FindPath(NULL, baseDirectory, subPath, 0, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BPathFinder::FindPath(path_base_directory baseDirectory, BPath& path)
|
BPathFinder::FindPath(path_base_directory baseDirectory, BPath& path)
|
||||||
{
|
{
|
||||||
return FindPath(baseDirectory, NULL, 0, path);
|
return FindPath(NULL, baseDirectory, NULL, 0, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
BPathFinder::FindPaths(path_base_directory baseDirectory, const char* subPath,
|
BPathFinder::FindPaths(const char* architecture,
|
||||||
uint32 flags, BStringList& paths)
|
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
||||||
|
BStringList& paths)
|
||||||
{
|
{
|
||||||
paths.MakeEmpty();
|
paths.MakeEmpty();
|
||||||
|
|
||||||
// get the paths
|
// get the paths
|
||||||
char** pathArray;
|
char** pathArray;
|
||||||
size_t pathCount;
|
size_t pathCount;
|
||||||
status_t error = find_paths(baseDirectory, subPath, flags, &pathArray,
|
status_t error = find_paths_etc(architecture, baseDirectory, subPath, flags,
|
||||||
&pathCount);
|
&pathArray, &pathCount);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -127,18 +137,26 @@ BPathFinder::FindPaths(path_base_directory baseDirectory, const char* subPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
BPathFinder::FindPaths(path_base_directory baseDirectory, const char* subPath,
|
||||||
|
uint32 flags, BStringList& paths)
|
||||||
|
{
|
||||||
|
return FindPaths(NULL, baseDirectory, subPath, 0, paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
BPathFinder::FindPaths(path_base_directory baseDirectory, const char* subPath,
|
BPathFinder::FindPaths(path_base_directory baseDirectory, const char* subPath,
|
||||||
BStringList& paths)
|
BStringList& paths)
|
||||||
{
|
{
|
||||||
return FindPaths(baseDirectory, subPath, 0, paths);
|
return FindPaths(NULL, baseDirectory, subPath, 0, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
BPathFinder::FindPaths(path_base_directory baseDirectory, BStringList& paths)
|
BPathFinder::FindPaths(path_base_directory baseDirectory, BStringList& paths)
|
||||||
{
|
{
|
||||||
return FindPaths(baseDirectory, NULL, 0, paths);
|
return FindPaths(NULL, baseDirectory, NULL, 0, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <architecture_private.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <directories.h>
|
||||||
|
#include <find_directory_private.h>
|
||||||
|
#include <runtime_loader.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char* const kArchitecture = B_HAIKU_ABI_NAME;
|
||||||
|
static const char* const kPrimaryArchitecture = __HAIKU_PRIMARY_PACKAGING_ARCH;
|
||||||
|
|
||||||
|
#ifdef __HAIKU_ARCH_X86
|
||||||
|
static const char* const kSiblingArchitectures[] = {"x86_gcc2", "x86"};
|
||||||
|
#else
|
||||||
|
static const char* const kSiblingArchitectures[] = {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const size_t kSiblingArchitectureCount
|
||||||
|
= sizeof(kSiblingArchitectures) / sizeof(const char*);
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
has_secondary_architecture(const char* architecture)
|
||||||
|
{
|
||||||
|
if (strcmp(architecture, kPrimaryArchitecture) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char path[B_PATH_NAME_LENGTH];
|
||||||
|
snprintf(path, sizeof(path), kSystemLibDirectory "/%s/libroot.so",
|
||||||
|
architecture);
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
return lstat(path, &st) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
__get_architecture()
|
||||||
|
{
|
||||||
|
return kArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
__get_primary_architecture()
|
||||||
|
{
|
||||||
|
return kPrimaryArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
__get_secondary_architectures(const char** architectures, size_t count)
|
||||||
|
{
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
// If this is an architecture that could be a primary or secondary
|
||||||
|
// architecture, check for which architectures a libroot.so is present.
|
||||||
|
if (kSiblingArchitectureCount > 0) {
|
||||||
|
for (size_t i = 0; i < kSiblingArchitectureCount; i++) {
|
||||||
|
const char* architecture = kSiblingArchitectures[i];
|
||||||
|
if (!has_secondary_architecture(architecture))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (index < count)
|
||||||
|
architectures[index] = architecture;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
__guess_architecture_for_path(const char* path)
|
||||||
|
{
|
||||||
|
if (kSiblingArchitectureCount == 0)
|
||||||
|
return kPrimaryArchitecture;
|
||||||
|
|
||||||
|
// ask the runtime loader
|
||||||
|
const char* architecture;
|
||||||
|
if (__gRuntimeLoader->get_executable_architecture(path, &architecture)
|
||||||
|
== B_OK) {
|
||||||
|
// verify that it is one of the sibling architectures
|
||||||
|
for (size_t i = 0; i < kSiblingArchitectureCount; i++) {
|
||||||
|
if (strcmp(architecture, kSiblingArchitectures[i]) == 0)
|
||||||
|
return kSiblingArchitectures[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guess from the given path
|
||||||
|
architecture = __guess_secondary_architecture_from_path(path,
|
||||||
|
kSiblingArchitectures, kSiblingArchitectureCount);
|
||||||
|
|
||||||
|
return architecture != NULL && has_secondary_architecture(architecture)
|
||||||
|
? architecture : kPrimaryArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
B_DEFINE_WEAK_ALIAS(__get_architecture, get_architecture);
|
||||||
|
B_DEFINE_WEAK_ALIAS(__get_primary_architecture, get_primary_architecture);
|
||||||
|
B_DEFINE_WEAK_ALIAS(__get_secondary_architectures, get_secondary_architectures);
|
||||||
|
B_DEFINE_WEAK_ALIAS(__guess_architecture_for_path, guess_architecture_for_path);
|
||||||
@@ -14,6 +14,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) locks ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) locks ] ;
|
||||||
|
|
||||||
MergeObject <$(architecture)>os_main.o :
|
MergeObject <$(architecture)>os_main.o :
|
||||||
|
Architecture.cpp
|
||||||
area.c
|
area.c
|
||||||
atomic.c
|
atomic.c
|
||||||
debug.c
|
debug.c
|
||||||
|
|||||||
@@ -11,8 +11,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <fs_attr.h>
|
#include <fs_attr.h>
|
||||||
|
|
||||||
|
#include <architecture_private.h>
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
|
||||||
@@ -28,7 +31,70 @@ static size_t kHomeInstallationLocationIndex = 1;
|
|||||||
static size_t kInstallationLocationCount
|
static size_t kInstallationLocationCount
|
||||||
= sizeof(kInstallationLocations) / sizeof(kInstallationLocations[0]);
|
= sizeof(kInstallationLocations) / sizeof(kInstallationLocations[0]);
|
||||||
|
|
||||||
|
static const path_base_directory kArchitectureSpecificBaseDirectories[] = {
|
||||||
|
B_FIND_PATH_ADD_ONS_DIRECTORY,
|
||||||
|
B_FIND_PATH_BIN_DIRECTORY,
|
||||||
|
B_FIND_PATH_DEVELOP_LIB_DIRECTORY,
|
||||||
|
B_FIND_PATH_HEADERS_DIRECTORY,
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t kArchitectureSpecificBaseDirectoryCount =
|
||||||
|
sizeof(kArchitectureSpecificBaseDirectories)
|
||||||
|
/ sizeof(kArchitectureSpecificBaseDirectories[0]);
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct PathBuffer {
|
||||||
|
PathBuffer(char* buffer, size_t size)
|
||||||
|
:
|
||||||
|
fBuffer(buffer),
|
||||||
|
fSize(size),
|
||||||
|
fLength(0)
|
||||||
|
{
|
||||||
|
if (fSize > 0)
|
||||||
|
fBuffer[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Append(const char* toAppend, size_t length)
|
||||||
|
{
|
||||||
|
if (fLength < fSize) {
|
||||||
|
size_t toCopy = std::min(length, fSize - fLength);
|
||||||
|
if (toCopy > 0) {
|
||||||
|
memcpy(fBuffer + fLength, toAppend, toCopy);
|
||||||
|
fBuffer[fLength + toCopy] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fLength += length;
|
||||||
|
return fLength < fSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Append(const char* toAppend)
|
||||||
|
{
|
||||||
|
return Append(toAppend, strlen(toAppend));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Length() const
|
||||||
|
{
|
||||||
|
return fLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* fBuffer;
|
||||||
|
size_t fSize;
|
||||||
|
size_t fLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! Returns the installation location relative path for the given base directory
|
||||||
|
constant and installation location index. A '%' in the returned path must be
|
||||||
|
replaced by "" for the primary architecture and by "/<arch>" for a secondary
|
||||||
|
architecture.
|
||||||
|
*/
|
||||||
static const char*
|
static const char*
|
||||||
get_relative_directory_path(size_t installationLocationIndex,
|
get_relative_directory_path(size_t installationLocationIndex,
|
||||||
path_base_directory baseDirectory)
|
path_base_directory baseDirectory)
|
||||||
@@ -37,11 +103,11 @@ get_relative_directory_path(size_t installationLocationIndex,
|
|||||||
case B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY:
|
case B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY:
|
||||||
return "";
|
return "";
|
||||||
case B_FIND_PATH_ADD_ONS_DIRECTORY:
|
case B_FIND_PATH_ADD_ONS_DIRECTORY:
|
||||||
return "/add-ons";
|
return "/add-ons%";
|
||||||
case B_FIND_PATH_APPS_DIRECTORY:
|
case B_FIND_PATH_APPS_DIRECTORY:
|
||||||
return "/apps";
|
return "/apps";
|
||||||
case B_FIND_PATH_BIN_DIRECTORY:
|
case B_FIND_PATH_BIN_DIRECTORY:
|
||||||
return "/bin";
|
return "/bin%";
|
||||||
case B_FIND_PATH_BOOT_DIRECTORY:
|
case B_FIND_PATH_BOOT_DIRECTORY:
|
||||||
return "/boot";
|
return "/boot";
|
||||||
case B_FIND_PATH_CACHE_DIRECTORY:
|
case B_FIND_PATH_CACHE_DIRECTORY:
|
||||||
@@ -51,7 +117,7 @@ get_relative_directory_path(size_t installationLocationIndex,
|
|||||||
case B_FIND_PATH_DEVELOP_DIRECTORY:
|
case B_FIND_PATH_DEVELOP_DIRECTORY:
|
||||||
return "/develop";
|
return "/develop";
|
||||||
case B_FIND_PATH_DEVELOP_LIB_DIRECTORY:
|
case B_FIND_PATH_DEVELOP_LIB_DIRECTORY:
|
||||||
return "/develop/lib";
|
return "/develop/lib%";
|
||||||
case B_FIND_PATH_DOCUMENTATION_DIRECTORY:
|
case B_FIND_PATH_DOCUMENTATION_DIRECTORY:
|
||||||
return "/documentation";
|
return "/documentation";
|
||||||
case B_FIND_PATH_ETC_DIRECTORY:
|
case B_FIND_PATH_ETC_DIRECTORY:
|
||||||
@@ -59,7 +125,7 @@ get_relative_directory_path(size_t installationLocationIndex,
|
|||||||
case B_FIND_PATH_FONTS_DIRECTORY:
|
case B_FIND_PATH_FONTS_DIRECTORY:
|
||||||
return "/data/fonts";
|
return "/data/fonts";
|
||||||
case B_FIND_PATH_HEADERS_DIRECTORY:
|
case B_FIND_PATH_HEADERS_DIRECTORY:
|
||||||
return "/develop/headers";
|
return "/develop/headers%";
|
||||||
case B_FIND_PATH_LIB_DIRECTORY:
|
case B_FIND_PATH_LIB_DIRECTORY:
|
||||||
return "/lib";
|
return "/lib";
|
||||||
case B_FIND_PATH_LOG_DIRECTORY:
|
case B_FIND_PATH_LOG_DIRECTORY:
|
||||||
@@ -80,7 +146,7 @@ get_relative_directory_path(size_t installationLocationIndex,
|
|||||||
case B_FIND_PATH_SPOOL_DIRECTORY:
|
case B_FIND_PATH_SPOOL_DIRECTORY:
|
||||||
return "/var/spool";
|
return "/var/spool";
|
||||||
case B_FIND_PATH_TRANSLATORS_DIRECTORY:
|
case B_FIND_PATH_TRANSLATORS_DIRECTORY:
|
||||||
return "/add-ons/Translators";
|
return "/add-ons%/Translators";
|
||||||
case B_FIND_PATH_VAR_DIRECTORY:
|
case B_FIND_PATH_VAR_DIRECTORY:
|
||||||
return "/var";
|
return "/var";
|
||||||
|
|
||||||
@@ -183,6 +249,73 @@ normalize_path(const char* path, char* buffer, size_t bufferSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
normalize_longest_existing_path_prefix(const char* path, char* buffer,
|
||||||
|
size_t bufferSize)
|
||||||
|
{
|
||||||
|
if (strlcpy(buffer, path, bufferSize) >= bufferSize)
|
||||||
|
return B_NAME_TOO_LONG;
|
||||||
|
|
||||||
|
// Until we have an existing path, chop off leaf components.
|
||||||
|
for (;;) {
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(buffer, &st) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Chop off the leaf, but fail, it it's "..", since then we'd actually
|
||||||
|
// construct a subpath.
|
||||||
|
char* lastSlash = strrchr(buffer, '/');
|
||||||
|
if (lastSlash == NULL || strcmp(lastSlash + 1, "..") == 0)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
*lastSlash = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize the existing prefix path
|
||||||
|
size_t prefixLength = strlen(buffer);
|
||||||
|
status_t error = normalize_path(buffer, buffer, bufferSize);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// Re-append the non-existent suffix. Remove duplicate slashes and "."
|
||||||
|
// components.
|
||||||
|
const char* bufferEnd = buffer + bufferSize;
|
||||||
|
char* end = buffer + strlen(buffer);
|
||||||
|
const char* remainder = path + prefixLength + 1;
|
||||||
|
while (*remainder != '\0') {
|
||||||
|
// find component start
|
||||||
|
if (*remainder == '/') {
|
||||||
|
remainder++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find component end
|
||||||
|
const char* componentEnd = strchr(remainder, '/');
|
||||||
|
if (componentEnd == NULL)
|
||||||
|
componentEnd = remainder + strlen(remainder);
|
||||||
|
|
||||||
|
// skip "." components
|
||||||
|
size_t componentLength = componentEnd - remainder;
|
||||||
|
if (componentLength == 1 && *remainder == '.') {
|
||||||
|
remainder++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the component
|
||||||
|
if (end + 1 + componentLength >= bufferEnd)
|
||||||
|
return B_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
|
*end++ = '/';
|
||||||
|
memcpy(end, remainder, componentLength);
|
||||||
|
end += componentLength;
|
||||||
|
remainder += componentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
*end = '\0';
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
get_installation_location(const char* path, size_t& _index)
|
get_installation_location(const char* path, size_t& _index)
|
||||||
{
|
{
|
||||||
@@ -238,21 +371,38 @@ normalize_dependency(const char* dependency, char* buffer, size_t bufferSize)
|
|||||||
|
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
process_path(const char* installationLocation, const char* relativePath,
|
process_path(const char* installationLocation, const char* architecture,
|
||||||
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize)
|
const char* relativePath, const char* subPath, uint32 flags,
|
||||||
|
char* pathBuffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
size_t totalLength;
|
// copy the installation location
|
||||||
|
PathBuffer buffer(pathBuffer, bufferSize);
|
||||||
|
buffer.Append(installationLocation);
|
||||||
|
|
||||||
|
// append the relative path, expanding the architecture placeholder
|
||||||
|
if (const char* placeholder = strchr(relativePath, '%')) {
|
||||||
|
buffer.Append(relativePath, placeholder - relativePath);
|
||||||
|
|
||||||
|
if (architecture != NULL) {
|
||||||
|
buffer.Append("/", 1);
|
||||||
|
buffer.Append(architecture);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.Append(placeholder + 1);
|
||||||
|
} else
|
||||||
|
buffer.Append(relativePath);
|
||||||
|
|
||||||
|
// append subpath, if given
|
||||||
if (subPath != NULL) {
|
if (subPath != NULL) {
|
||||||
totalLength = snprintf(pathBuffer, bufferSize, "%s%s/%s",
|
buffer.Append("/", 1);
|
||||||
installationLocation, relativePath, subPath);
|
buffer.Append(subPath);
|
||||||
} else {
|
|
||||||
totalLength = snprintf(pathBuffer, bufferSize, "%s%s",
|
|
||||||
installationLocation, relativePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t totalLength = buffer.Length();
|
||||||
if (totalLength >= bufferSize)
|
if (totalLength >= bufferSize)
|
||||||
return B_BUFFER_OVERFLOW;
|
return B_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
|
// handle the flags
|
||||||
char* path = pathBuffer;
|
char* path = pathBuffer;
|
||||||
|
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
@@ -283,9 +433,13 @@ process_path(const char* installationLocation, const char* relativePath,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
internal_path_for_path(char* referencePath, size_t referencePathSize,
|
internal_path_for_path(char* referencePath, size_t referencePathSize,
|
||||||
const char* dependency, path_base_directory baseDirectory,
|
const char* dependency, const char* architecture,
|
||||||
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize)
|
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
||||||
|
char* pathBuffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
|
if (strcmp(architecture, __get_primary_architecture()) == 0)
|
||||||
|
architecture = NULL;
|
||||||
|
|
||||||
// normalize
|
// normalize
|
||||||
status_t error = normalize_path(referencePath, referencePath,
|
status_t error = normalize_path(referencePath, referencePath,
|
||||||
referencePathSize);
|
referencePathSize);
|
||||||
@@ -359,8 +513,8 @@ internal_path_for_path(char* referencePath, size_t referencePathSize,
|
|||||||
if (relativePath == NULL)
|
if (relativePath == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
ssize_t pathSize = process_path(installationLocation, relativePath, subPath,
|
ssize_t pathSize = process_path(installationLocation, architecture,
|
||||||
flags, pathBuffer, bufferSize);
|
relativePath, subPath, flags, pathBuffer, bufferSize);
|
||||||
if (pathSize <= 0)
|
if (pathSize <= 0)
|
||||||
return pathSize == 0 ? B_ENTRY_NOT_FOUND : pathSize;
|
return pathSize == 0 ? B_ENTRY_NOT_FOUND : pathSize;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -371,9 +525,18 @@ internal_path_for_path(char* referencePath, size_t referencePathSize,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
__find_path(const void* codePointer, const char* dependency,
|
__find_path(const void* codePointer, path_base_directory baseDirectory,
|
||||||
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
const char* subPath, char* pathBuffer, size_t bufferSize)
|
||||||
char* pathBuffer, size_t bufferSize)
|
{
|
||||||
|
return __find_path_etc(codePointer, NULL, NULL, baseDirectory, subPath, 0,
|
||||||
|
pathBuffer, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
__find_path_etc(const void* codePointer, const char* dependency,
|
||||||
|
const char* architecture, path_base_directory baseDirectory,
|
||||||
|
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
if (pathBuffer == NULL)
|
if (pathBuffer == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -384,15 +547,28 @@ __find_path(const void* codePointer, const char* dependency,
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
if (architecture == NULL)
|
||||||
|
architecture = __get_architecture();
|
||||||
|
|
||||||
return internal_path_for_path(imageInfo.name, sizeof(imageInfo.name),
|
return internal_path_for_path(imageInfo.name, sizeof(imageInfo.name),
|
||||||
dependency, baseDirectory, subPath, flags, pathBuffer, bufferSize);
|
dependency, architecture, baseDirectory, subPath, flags, pathBuffer,
|
||||||
|
bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
__find_path_for_path(const char* path, const char* dependency,
|
__find_path_for_path(const char* path, path_base_directory baseDirectory,
|
||||||
path_base_directory baseDirectory, const char* subPath, uint32 flags,
|
const char* subPath, char* pathBuffer, size_t bufferSize)
|
||||||
char* pathBuffer, size_t bufferSize)
|
{
|
||||||
|
return __find_path_for_path_etc(path, NULL, NULL, baseDirectory, subPath, 0,
|
||||||
|
pathBuffer, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
__find_path_for_path_etc(const char* path, const char* dependency,
|
||||||
|
const char* architecture, path_base_directory baseDirectory,
|
||||||
|
const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
char referencePath[B_PATH_NAME_LENGTH];
|
char referencePath[B_PATH_NAME_LENGTH];
|
||||||
if (strlcpy(referencePath, path, sizeof(referencePath))
|
if (strlcpy(referencePath, path, sizeof(referencePath))
|
||||||
@@ -400,18 +576,42 @@ __find_path_for_path(const char* path, const char* dependency,
|
|||||||
return B_NAME_TOO_LONG;
|
return B_NAME_TOO_LONG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (architecture == NULL)
|
||||||
|
architecture = __guess_architecture_for_path(path);
|
||||||
|
|
||||||
return internal_path_for_path(referencePath, sizeof(referencePath),
|
return internal_path_for_path(referencePath, sizeof(referencePath),
|
||||||
dependency, baseDirectory, subPath, flags, pathBuffer, bufferSize);
|
dependency, architecture, baseDirectory, subPath, flags, pathBuffer,
|
||||||
|
bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
__find_paths(path_base_directory baseDirectory, const char* subPath,
|
__find_paths(path_base_directory baseDirectory, const char* subPath,
|
||||||
uint32 flags, char*** _paths, size_t* _pathCount)
|
char*** _paths, size_t* _pathCount)
|
||||||
|
{
|
||||||
|
return __find_paths_etc(NULL, baseDirectory, subPath, 0, _paths,
|
||||||
|
_pathCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
__find_paths_etc(const char* architecture, path_base_directory baseDirectory,
|
||||||
|
const char* subPath, uint32 flags, char*** _paths, size_t* _pathCount)
|
||||||
{
|
{
|
||||||
if (_paths == NULL || _pathCount == NULL)
|
if (_paths == NULL || _pathCount == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// Analyze architecture. If NULL, use the caller's architecture. If the
|
||||||
|
// effective architecture is the primary one, set architecture to NULL to
|
||||||
|
// indicate that we don't need to insert an architecture subdirectory
|
||||||
|
// component.
|
||||||
|
if (architecture == NULL)
|
||||||
|
architecture = __get_architecture();
|
||||||
|
if (strcmp(architecture, __get_primary_architecture()) == 0)
|
||||||
|
architecture = NULL;
|
||||||
|
size_t architectureSize = architecture != NULL
|
||||||
|
? strlen(architecture) + 1 : 0;
|
||||||
|
|
||||||
size_t subPathLength = subPath != NULL ? strlen(subPath) + 1 : 0;
|
size_t subPathLength = subPath != NULL ? strlen(subPath) + 1 : 0;
|
||||||
|
|
||||||
// Get the relative paths and compute the total size to allocate.
|
// Get the relative paths and compute the total size to allocate.
|
||||||
@@ -425,6 +625,8 @@ __find_paths(path_base_directory baseDirectory, const char* subPath,
|
|||||||
|
|
||||||
totalSize += strlen(kInstallationLocations[i])
|
totalSize += strlen(kInstallationLocations[i])
|
||||||
+ strlen(relativePaths[i]) + subPathLength + 1;
|
+ strlen(relativePaths[i]) + subPathLength + 1;
|
||||||
|
if (strchr(relativePaths[i], '%') != NULL)
|
||||||
|
totalSize += architectureSize - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate storage
|
// allocate storage
|
||||||
@@ -440,7 +642,7 @@ __find_paths(path_base_directory baseDirectory, const char* subPath,
|
|||||||
const char* pathBufferEnd = pathBuffer + totalSize;
|
const char* pathBufferEnd = pathBuffer + totalSize;
|
||||||
for (size_t i = 0; i < kInstallationLocationCount; i++) {
|
for (size_t i = 0; i < kInstallationLocationCount; i++) {
|
||||||
ssize_t pathSize = process_path(kInstallationLocations[i],
|
ssize_t pathSize = process_path(kInstallationLocations[i],
|
||||||
relativePaths[i], subPath, flags, pathBuffer,
|
architecture, relativePaths[i], subPath, flags, pathBuffer,
|
||||||
pathBufferEnd - pathBuffer);
|
pathBufferEnd - pathBuffer);
|
||||||
if (pathSize < 0)
|
if (pathSize < 0)
|
||||||
return pathSize;
|
return pathSize;
|
||||||
@@ -461,6 +663,65 @@ __find_paths(path_base_directory baseDirectory, const char* subPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
__guess_secondary_architecture_from_path(const char* path,
|
||||||
|
const char* const* secondaryArchitectures,
|
||||||
|
size_t secondaryArchitectureCount)
|
||||||
|
{
|
||||||
|
// Get the longest existing prefix path and normalize it.
|
||||||
|
char prefix[B_PATH_NAME_LENGTH];
|
||||||
|
if (normalize_longest_existing_path_prefix(path, prefix, sizeof(prefix))
|
||||||
|
!= B_OK) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get an installation location relative path
|
||||||
|
size_t installationLocationIndex;
|
||||||
|
const char* installationLocation = get_installation_location(prefix,
|
||||||
|
installationLocationIndex);
|
||||||
|
if (installationLocation == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
const char* relativePath = prefix + strlen(installationLocation);
|
||||||
|
if (relativePath[0] != '/')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Iterate through the known paths that would indicate a secondary
|
||||||
|
// architecture and try to match them with our given path.
|
||||||
|
for (size_t i = 0; i < kArchitectureSpecificBaseDirectoryCount; i++) {
|
||||||
|
const char* basePath = get_relative_directory_path(
|
||||||
|
installationLocationIndex, kArchitectureSpecificBaseDirectories[i]);
|
||||||
|
const char* placeholder = strchr(basePath, '%');
|
||||||
|
if (placeholder == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// match the part up to the architecture placeholder
|
||||||
|
size_t prefixLength = placeholder - basePath;
|
||||||
|
if (strncmp(relativePath, basePath, prefixLength) != 0
|
||||||
|
|| relativePath[prefixLength] != '/') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// match the architecture
|
||||||
|
const char* architecturePart = relativePath + prefixLength + 1;
|
||||||
|
for (size_t k = 0; k < secondaryArchitectureCount; k++) {
|
||||||
|
const char* architecture = secondaryArchitectures[k];
|
||||||
|
size_t architectureLength = strlen(architecture);
|
||||||
|
if (strncmp(architecturePart, architecture, architectureLength) == 0
|
||||||
|
&& (architecturePart[architectureLength] == '/'
|
||||||
|
|| architecturePart[architectureLength] == '\0')) {
|
||||||
|
return architecture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
B_DEFINE_WEAK_ALIAS(__find_path, find_path);
|
B_DEFINE_WEAK_ALIAS(__find_path, find_path);
|
||||||
|
B_DEFINE_WEAK_ALIAS(__find_path_etc, find_path_etc);
|
||||||
B_DEFINE_WEAK_ALIAS(__find_path_for_path, find_path_for_path);
|
B_DEFINE_WEAK_ALIAS(__find_path_for_path, find_path_for_path);
|
||||||
|
B_DEFINE_WEAK_ALIAS(__find_path_for_path_etc, find_path_for_path_etc);
|
||||||
B_DEFINE_WEAK_ALIAS(__find_paths, find_paths);
|
B_DEFINE_WEAK_ALIAS(__find_paths, find_paths);
|
||||||
|
B_DEFINE_WEAK_ALIAS(__find_paths_etc, find_paths_etc);
|
||||||
|
|||||||
Reference in New Issue
Block a user