find_directory(): Add architecture support

* Move PathBuffer helper class out of find_paths.cpp into its own
  header.
* find_directory():
  - Make use of MemoryDeleter to simplify things.
  - Make use of PathBuffer for a simpler and more correct handling.
  - Make B_UTILITIES_DIRECTORY to B_APPS_DIRECTORY. /boot/utilities
    doesn't exist anyway.
  - Resolve the concerned constants to the architecture specific
    subdirectory, when called in a secondary architecture context, just
    like find_path*().
This commit is contained in:
Ingo Weinhold 2013-11-17 19:10:18 +01:00
parent 7fb0d6c269
commit 04c6cb37bb
4 changed files with 216 additions and 147 deletions

View File

@ -9,30 +9,32 @@ CCFLAGS += -include $(kernelLibHeader) ;
C++FLAGS += -include $(kernelLibHeader) ;
local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ;
local librootOSSources = [ FDirName $(librootSources) os ] ;
local posixSources = [ FDirName $(librootSources) posix ] ;
# kernel libroot os files
KernelMergeObject kernel_os_main.o :
local sources =
driver_settings.cpp
find_directory.cpp
fs_info.c
system_revision.c
wait_for_objects.cpp
;
SourceHdrs $(sources) : $(librootOSSources) ;
KernelMergeObject kernel_os_main.o : $(sources)
: $(TARGET_KERNEL_PIC_CCFLAGS)
;
SEARCH on [ FGristFiles
driver_settings.cpp
find_directory.cpp
fs_info.c
system_revision.c
wait_for_objects.cpp
] = [ FDirName $(HAIKU_TOP) src system libroot os ] ;
SEARCH on [ FGristFiles $(sources) ]
= [ FDirName $(HAIKU_TOP) src system libroot os ] ;
# kernel libroot posix files
local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ;
local posixSources = [ FDirName $(librootSources) posix ] ;
SEARCH_SOURCE += [ FDirName $(posixSources) ] ;
SEARCH_SOURCE += [ FDirName $(posixSources) locale ] ;
SEARCH_SOURCE += [ FDirName $(posixSources) stdio ] ;

View File

@ -0,0 +1,75 @@
/*
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PATH_BUFFER_H
#define PATH_BUFFER_H
#include <string.h>
#include <algorithm>
namespace {
struct PathBuffer {
PathBuffer()
:
fBuffer(NULL),
fSize(0),
fLength(0)
{
}
PathBuffer(char* buffer, size_t size, size_t length = 0)
{
SetTo(buffer, size, length);
}
void SetTo(char* buffer, size_t size, size_t length = 0)
{
fBuffer = buffer;
fSize = size;
fLength = length;
if (fLength < fSize)
fBuffer[fLength] = '\0';
}
bool Append(const char* toAppend, size_t length)
{
if (length > 0 && fLength + 1 < fSize) {
size_t toCopy = std::min(length, fSize - fLength - 1);
memcpy(fBuffer + fLength, toAppend, toCopy);
fBuffer[fLength + toCopy] = '\0';
}
fLength += length;
return fLength < fSize;
}
bool Append(const char* toAppend)
{
return Append(toAppend, strlen(toAppend));
}
bool Append(char c)
{
return Append(&c, 1);
}
size_t Length() const
{
return fLength;
}
private:
char* fBuffer;
size_t fSize;
size_t fLength;
};
}
#endif // PATH_BUFFER_H

View File

@ -1,7 +1,8 @@
/*
* Copyright 2004, François Revol.
* Copyright 2007-2010, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de.
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
*
* Distributed under the terms of the MIT license.
*/
@ -26,11 +27,18 @@
#include <stdlib.h>
#include <unistd.h>
#include <architecture_private.h>
#include <errno_private.h>
#include <find_directory_private.h>
#include <stdlib_private.h>
#include <symbol_versioning.h>
#include <user_group.h>
#include <AutoDeleter.h>
#include "PathBuffer.h"
/* use pwents to find home */
#define USE_PWENTS
@ -77,23 +85,23 @@ enum {
static const char *kSystemDirectories[] = {
SYSTEM, // B_SYSTEM_DIRECTORY
SYSTEM, // B_BEOS_SYSTEM_DIRECTORY
SYSTEM "/add-ons",
SYSTEM "/add-ons$a",
SYSTEM "/boot",
SYSTEM "/data/fonts",
SYSTEM "/lib",
SYSTEM "/lib$a",
SYSTEM "/servers",
SYSTEM "/apps",
SYSTEM "/bin",
SYSTEM "/bin$a",
SYSTEM "/settings/etc",
SYSTEM "/documentation",
SYSTEM "/preferences",
SYSTEM "/add-ons/Translators",
SYSTEM "/add-ons/media",
SYSTEM "/add-ons$a/Translators",
SYSTEM "/add-ons$a/media",
SYSTEM "/data/sounds",
SYSTEM "/data",
SYSTEM "/develop",
SYSTEM "/packages",
SYSTEM "/develop/headers",
SYSTEM "/develop/headers$a",
};
/* Common directories, shared among users */
@ -101,12 +109,12 @@ static const char *kSystemDirectories[] = {
static const char *kCommonDirectories[] = {
COMMON, // B_COMMON_DIRECTORY
COMMON, // B_COMMON_SYSTEM_DIRECTORY
COMMON "/add-ons",
COMMON "/add-ons$a",
COMMON "/boot",
COMMON "/data/fonts",
COMMON "/lib",
COMMON "/lib$a",
COMMON "/servers",
COMMON "/bin",
COMMON "/bin$a",
SYSTEM "/settings/etc", // B_SYSTEM_ETC_DIRECTORY
COMMON "/documentation",
SYSTEM "/settings", // B_SYSTEM_SETTINGS_DIRECTORY
@ -115,24 +123,24 @@ static const char *kCommonDirectories[] = {
SYSTEM "/var/spool", // B_SYSTEM_SPOOL_DIRECTORY
SYSTEM "/cache/tmp", // B_SYSTEM_TEMP_DIRECTORY
SYSTEM "/var", // B_SYSTEM_VAR_DIRECTORY
COMMON "/add-ons/Translators",
COMMON "/add-ons/media",
COMMON "/add-ons$a/Translators",
COMMON "/add-ons$a/media",
COMMON "/data/sounds",
COMMON "/data",
SYSTEM "/cache", // B_SYSTEM_CACHE_DIRECTORY
COMMON "/packages",
COMMON "/develop/headers",
COMMON "/develop/headers$a",
SYSTEM NON_PACKAGED,
SYSTEM NON_PACKAGED "/add-ons",
SYSTEM NON_PACKAGED "/add-ons/Translators",
SYSTEM NON_PACKAGED "/add-ons/media",
SYSTEM NON_PACKAGED "/bin",
SYSTEM NON_PACKAGED "/add-ons$a",
SYSTEM NON_PACKAGED "/add-ons$a/Translators",
SYSTEM NON_PACKAGED "/add-ons$a/media",
SYSTEM NON_PACKAGED "/bin$a",
SYSTEM NON_PACKAGED "/data",
SYSTEM NON_PACKAGED "/data/fonts",
SYSTEM NON_PACKAGED "/data/sounds",
SYSTEM NON_PACKAGED "/documentation",
SYSTEM NON_PACKAGED "/lib",
SYSTEM NON_PACKAGED "/develop/headers",
SYSTEM NON_PACKAGED "/lib$a",
SYSTEM NON_PACKAGED "/develop/headers$a",
SYSTEM NON_PACKAGED "/develop",
};
@ -144,37 +152,37 @@ static const char *kCommonDirectories[] = {
static const char *kUserDirectories[] = {
HOME, // B_USER_DIRECTORY
HOME CONFIG, // B_USER_CONFIG_DIRECTORY
HOME CONFIG "/add-ons",
HOME CONFIG "/add-ons$a",
HOME CONFIG "/boot",
HOME CONFIG "/data/fonts",
HOME CONFIG "/lib",
HOME CONFIG "/lib$a",
HOME CONFIG "/settings",
HOME CONFIG "/settings/deskbar/menu",
HOME CONFIG "/settings/printers",
HOME CONFIG "/add-ons/Translators",
HOME CONFIG "/add-ons/media",
HOME CONFIG "/add-ons$a/Translators",
HOME CONFIG "/add-ons$a/media",
HOME CONFIG "/data/sounds",
HOME CONFIG "/data",
HOME CONFIG "/cache",
HOME CONFIG "/packages",
HOME CONFIG "/develop/headers",
HOME CONFIG "/develop/headers$a",
HOME CONFIG NON_PACKAGED,
HOME CONFIG NON_PACKAGED "/add-ons",
HOME CONFIG NON_PACKAGED "/add-ons/Translators",
HOME CONFIG NON_PACKAGED "/add-ons/media",
HOME CONFIG NON_PACKAGED "/bin",
HOME CONFIG NON_PACKAGED "/add-ons$a",
HOME CONFIG NON_PACKAGED "/add-ons$a/Translators",
HOME CONFIG NON_PACKAGED "/add-ons$a/media",
HOME CONFIG NON_PACKAGED "/bin$a",
HOME CONFIG NON_PACKAGED "/data",
HOME CONFIG NON_PACKAGED "/data/fonts",
HOME CONFIG NON_PACKAGED "/data/sounds",
HOME CONFIG NON_PACKAGED "/documentation",
HOME CONFIG NON_PACKAGED "/lib",
HOME CONFIG NON_PACKAGED "/develop/headers",
HOME CONFIG NON_PACKAGED "/lib$a",
HOME CONFIG NON_PACKAGED "/develop/headers$a",
HOME CONFIG NON_PACKAGED "/develop",
HOME CONFIG "/develop",
HOME CONFIG "/documentation",
HOME CONFIG "/servers",
HOME CONFIG "/apps",
HOME CONFIG "/bin",
HOME CONFIG "/bin$a",
HOME CONFIG "/preferences",
HOME CONFIG "/settings/etc",
HOME CONFIG "/var/log",
@ -217,23 +225,59 @@ create_path(const char *path, mode_t mode)
}
static size_t
get_user_home_path(char* buffer, size_t bufferSize)
{
const char* home = NULL;
#ifndef _KERNEL_MODE
#ifdef USE_PWENTS
struct passwd pwBuffer;
char pwStringBuffer[MAX_PASSWD_BUFFER_SIZE];
struct passwd* pw;
if (getpwuid_r(geteuid(), &pwBuffer, pwStringBuffer,
sizeof(pwStringBuffer), &pw) == 0
&& pw != NULL) {
home = pw->pw_dir;
}
#endif // USE_PWENTS
if (home == NULL) {
/* use env var */
ssize_t result = __getenv_reentrant("HOME", buffer, bufferSize);
if (result >= 0)
return result;
}
#endif // !_KERNEL_MODE
if (home == NULL)
home = kUserDirectory;
return strlcpy(buffer, home, bufferSize);
}
// #pragma mark -
status_t
__find_directory(directory_which which, dev_t device, bool createIt,
char *returnedPath, int32 pathLength)
char *returnedPath, int32 _pathLength)
{
if (_pathLength <= 0)
return E2BIG;
size_t pathLength = _pathLength;
status_t err = B_OK;
dev_t bootDevice = -1;
struct fs_info fsInfo;
struct stat st;
char *buffer = NULL;
const char *home = NULL;
const char *templatePath = NULL;
/* as with the R5 version, no on-stack buffer */
buffer = (char *)malloc(pathLength);
char *buffer = (char*)malloc(pathLength);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
memset(buffer, 0, pathLength);
/* fiddle with non-boot volume for items that need it */
@ -243,10 +287,8 @@ __find_directory(directory_which which, dev_t device, bool createIt,
bootDevice = dev_for_path("/boot");
if (device <= 0)
device = bootDevice;
if (fs_stat_dev(device, &fsInfo) < B_OK) {
free(buffer);
if (fs_stat_dev(device, &fsInfo) != B_OK)
return ENODEV;
}
if (device != bootDevice) {
#ifdef _KERNEL_MODE
err = _user_entry_ref_to_path(device, fsInfo.root, /*"."*/
@ -255,6 +297,8 @@ __find_directory(directory_which which, dev_t device, bool createIt,
err = _kern_entry_ref_to_path(device, fsInfo.root, /*"."*/
NULL, buffer, pathLength);
#endif
if (err != B_OK)
return err;
} else {
/* use the user id to find the home folder */
/* done later */
@ -269,11 +313,6 @@ __find_directory(directory_which which, dev_t device, bool createIt,
break;
}
if (err < B_OK) {
free(buffer);
return err;
}
switch ((int)which) {
/* Per volume directories */
case B_DESKTOP_DIRECTORY:
@ -394,71 +433,69 @@ __find_directory(directory_which which, dev_t device, bool createIt,
/* Global directories */
case B_APPS_DIRECTORY:
case B_UTILITIES_DIRECTORY:
templatePath = SYSTEM "/apps";
break;
case B_PREFERENCES_DIRECTORY:
templatePath = SYSTEM "/preferences";
break;
case B_UTILITIES_DIRECTORY:
templatePath = "utilities";
break;
case B_PACKAGE_LINKS_DIRECTORY:
templatePath = "packages";
break;
default:
free(buffer);
return EINVAL;
}
err = B_OK;
if (templatePath) {
if (!strncmp(templatePath, "$h", 2)) {
if (bootDevice > -1 && device != bootDevice) {
int l = pathLength - strlen(buffer);
if (l > 5)
strncat(buffer, "/home", 5);
} else {
if (templatePath == NULL)
return ENOENT;
PathBuffer pathBuffer(buffer, pathLength, strlen(buffer));
// resolve "$h" placeholder to the user's home directory
if (!strncmp(templatePath, "$h", 2)) {
if (bootDevice > -1 && device != bootDevice) {
pathBuffer.Append("/home");
} else {
size_t length = get_user_home_path(buffer, pathLength);
if (length >= pathLength)
return E2BIG;
pathBuffer.SetTo(buffer, pathLength, length);
}
templatePath += 2;
} else if (templatePath[0] != '\0')
pathBuffer.Append('/');
// resolve "$a" placeholder to the architecture subdirectory, if not
// primary
if (char* dollar = strchr(templatePath, '$')) {
if (dollar[1] == 'a') {
pathBuffer.Append(templatePath, dollar - templatePath);
#ifndef _KERNEL_MODE
#ifdef USE_PWENTS
struct passwd pwBuffer;
char pwStringBuffer[MAX_PASSWD_BUFFER_SIZE];
struct passwd *pw;
if (getpwuid_r(geteuid(), &pwBuffer, pwStringBuffer,
sizeof(pwStringBuffer), &pw) == 0
&& pw != NULL) {
home = pw->pw_dir;
}
#endif // USE_PWENTS
if (!home) {
/* use env var */
home = getenv("HOME");
}
#endif // !_KERNEL_MODE
if (!home)
home = kUserDirectory;
strncpy(buffer, home, pathLength);
const char* architecture = __get_architecture();
if (strcmp(architecture, __get_primary_architecture()) != 0) {
pathBuffer.Append('/');
pathBuffer.Append(architecture);
}
templatePath += 2;
} else
strlcat(buffer, "/", pathLength);
#endif
templatePath = dollar + 2;
}
}
if (!err && strlen(buffer) + 2 + strlen(templatePath)
< (uint32)pathLength) {
strcat(buffer, templatePath);
} else
err = err ? err : E2BIG;
} else
err = err ? err : ENOENT;
// append (remainder of) template path
pathBuffer.Append(templatePath);
if (!err && createIt && stat(buffer, &st) < 0)
if (pathBuffer.Length() >= pathLength)
return E2BIG;
if (createIt && stat(buffer, &st) < 0) {
err = create_path(buffer, 0755);
if (!err)
strlcpy(returnedPath, buffer, pathLength);
if (err != B_OK)
return err;
}
free(buffer);
return err;
strlcpy(returnedPath, buffer, pathLength);
return B_OK;
}

View File

@ -19,6 +19,8 @@
#include <AutoDeleter.h>
#include <syscalls.h>
#include "PathBuffer.h"
static const char* const kInstallationLocations[] = {
"/boot/home/config/non-packaged",
@ -43,53 +45,6 @@ static size_t kArchitectureSpecificBaseDirectoryCount =
/ 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