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) ; 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 # kernel libroot os files
KernelMergeObject kernel_os_main.o : local sources =
driver_settings.cpp driver_settings.cpp
find_directory.cpp find_directory.cpp
fs_info.c fs_info.c
system_revision.c system_revision.c
wait_for_objects.cpp wait_for_objects.cpp
;
SourceHdrs $(sources) : $(librootOSSources) ;
KernelMergeObject kernel_os_main.o : $(sources)
: $(TARGET_KERNEL_PIC_CCFLAGS) : $(TARGET_KERNEL_PIC_CCFLAGS)
; ;
SEARCH on [ FGristFiles SEARCH on [ FGristFiles $(sources) ]
driver_settings.cpp = [ FDirName $(HAIKU_TOP) src system libroot os ] ;
find_directory.cpp
fs_info.c
system_revision.c
wait_for_objects.cpp
] = [ FDirName $(HAIKU_TOP) src system libroot os ] ;
# kernel libroot posix files # 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) ] ;
SEARCH_SOURCE += [ FDirName $(posixSources) locale ] ; SEARCH_SOURCE += [ FDirName $(posixSources) locale ] ;
SEARCH_SOURCE += [ FDirName $(posixSources) stdio ] ; 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 2004, François Revol.
* Copyright 2007-2010, Axel Dörfler, axeld@pinc-software.de. * 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. * Distributed under the terms of the MIT license.
*/ */
@ -26,11 +27,18 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <architecture_private.h>
#include <errno_private.h> #include <errno_private.h>
#include <find_directory_private.h> #include <find_directory_private.h>
#include <stdlib_private.h>
#include <symbol_versioning.h> #include <symbol_versioning.h>
#include <user_group.h> #include <user_group.h>
#include <AutoDeleter.h>
#include "PathBuffer.h"
/* use pwents to find home */ /* use pwents to find home */
#define USE_PWENTS #define USE_PWENTS
@ -77,23 +85,23 @@ enum {
static const char *kSystemDirectories[] = { static const char *kSystemDirectories[] = {
SYSTEM, // B_SYSTEM_DIRECTORY SYSTEM, // B_SYSTEM_DIRECTORY
SYSTEM, // B_BEOS_SYSTEM_DIRECTORY SYSTEM, // B_BEOS_SYSTEM_DIRECTORY
SYSTEM "/add-ons", SYSTEM "/add-ons$a",
SYSTEM "/boot", SYSTEM "/boot",
SYSTEM "/data/fonts", SYSTEM "/data/fonts",
SYSTEM "/lib", SYSTEM "/lib$a",
SYSTEM "/servers", SYSTEM "/servers",
SYSTEM "/apps", SYSTEM "/apps",
SYSTEM "/bin", SYSTEM "/bin$a",
SYSTEM "/settings/etc", SYSTEM "/settings/etc",
SYSTEM "/documentation", SYSTEM "/documentation",
SYSTEM "/preferences", SYSTEM "/preferences",
SYSTEM "/add-ons/Translators", SYSTEM "/add-ons$a/Translators",
SYSTEM "/add-ons/media", SYSTEM "/add-ons$a/media",
SYSTEM "/data/sounds", SYSTEM "/data/sounds",
SYSTEM "/data", SYSTEM "/data",
SYSTEM "/develop", SYSTEM "/develop",
SYSTEM "/packages", SYSTEM "/packages",
SYSTEM "/develop/headers", SYSTEM "/develop/headers$a",
}; };
/* Common directories, shared among users */ /* Common directories, shared among users */
@ -101,12 +109,12 @@ static const char *kSystemDirectories[] = {
static const char *kCommonDirectories[] = { static const char *kCommonDirectories[] = {
COMMON, // B_COMMON_DIRECTORY COMMON, // B_COMMON_DIRECTORY
COMMON, // B_COMMON_SYSTEM_DIRECTORY COMMON, // B_COMMON_SYSTEM_DIRECTORY
COMMON "/add-ons", COMMON "/add-ons$a",
COMMON "/boot", COMMON "/boot",
COMMON "/data/fonts", COMMON "/data/fonts",
COMMON "/lib", COMMON "/lib$a",
COMMON "/servers", COMMON "/servers",
COMMON "/bin", COMMON "/bin$a",
SYSTEM "/settings/etc", // B_SYSTEM_ETC_DIRECTORY SYSTEM "/settings/etc", // B_SYSTEM_ETC_DIRECTORY
COMMON "/documentation", COMMON "/documentation",
SYSTEM "/settings", // B_SYSTEM_SETTINGS_DIRECTORY SYSTEM "/settings", // B_SYSTEM_SETTINGS_DIRECTORY
@ -115,24 +123,24 @@ static const char *kCommonDirectories[] = {
SYSTEM "/var/spool", // B_SYSTEM_SPOOL_DIRECTORY SYSTEM "/var/spool", // B_SYSTEM_SPOOL_DIRECTORY
SYSTEM "/cache/tmp", // B_SYSTEM_TEMP_DIRECTORY SYSTEM "/cache/tmp", // B_SYSTEM_TEMP_DIRECTORY
SYSTEM "/var", // B_SYSTEM_VAR_DIRECTORY SYSTEM "/var", // B_SYSTEM_VAR_DIRECTORY
COMMON "/add-ons/Translators", COMMON "/add-ons$a/Translators",
COMMON "/add-ons/media", COMMON "/add-ons$a/media",
COMMON "/data/sounds", COMMON "/data/sounds",
COMMON "/data", COMMON "/data",
SYSTEM "/cache", // B_SYSTEM_CACHE_DIRECTORY SYSTEM "/cache", // B_SYSTEM_CACHE_DIRECTORY
COMMON "/packages", COMMON "/packages",
COMMON "/develop/headers", COMMON "/develop/headers$a",
SYSTEM NON_PACKAGED, SYSTEM NON_PACKAGED,
SYSTEM NON_PACKAGED "/add-ons", SYSTEM NON_PACKAGED "/add-ons$a",
SYSTEM NON_PACKAGED "/add-ons/Translators", SYSTEM NON_PACKAGED "/add-ons$a/Translators",
SYSTEM NON_PACKAGED "/add-ons/media", SYSTEM NON_PACKAGED "/add-ons$a/media",
SYSTEM NON_PACKAGED "/bin", SYSTEM NON_PACKAGED "/bin$a",
SYSTEM NON_PACKAGED "/data", SYSTEM NON_PACKAGED "/data",
SYSTEM NON_PACKAGED "/data/fonts", SYSTEM NON_PACKAGED "/data/fonts",
SYSTEM NON_PACKAGED "/data/sounds", SYSTEM NON_PACKAGED "/data/sounds",
SYSTEM NON_PACKAGED "/documentation", SYSTEM NON_PACKAGED "/documentation",
SYSTEM NON_PACKAGED "/lib", SYSTEM NON_PACKAGED "/lib$a",
SYSTEM NON_PACKAGED "/develop/headers", SYSTEM NON_PACKAGED "/develop/headers$a",
SYSTEM NON_PACKAGED "/develop", SYSTEM NON_PACKAGED "/develop",
}; };
@ -144,37 +152,37 @@ static const char *kCommonDirectories[] = {
static const char *kUserDirectories[] = { static const char *kUserDirectories[] = {
HOME, // B_USER_DIRECTORY HOME, // B_USER_DIRECTORY
HOME CONFIG, // B_USER_CONFIG_DIRECTORY HOME CONFIG, // B_USER_CONFIG_DIRECTORY
HOME CONFIG "/add-ons", HOME CONFIG "/add-ons$a",
HOME CONFIG "/boot", HOME CONFIG "/boot",
HOME CONFIG "/data/fonts", HOME CONFIG "/data/fonts",
HOME CONFIG "/lib", HOME CONFIG "/lib$a",
HOME CONFIG "/settings", HOME CONFIG "/settings",
HOME CONFIG "/settings/deskbar/menu", HOME CONFIG "/settings/deskbar/menu",
HOME CONFIG "/settings/printers", HOME CONFIG "/settings/printers",
HOME CONFIG "/add-ons/Translators", HOME CONFIG "/add-ons$a/Translators",
HOME CONFIG "/add-ons/media", HOME CONFIG "/add-ons$a/media",
HOME CONFIG "/data/sounds", HOME CONFIG "/data/sounds",
HOME CONFIG "/data", HOME CONFIG "/data",
HOME CONFIG "/cache", HOME CONFIG "/cache",
HOME CONFIG "/packages", HOME CONFIG "/packages",
HOME CONFIG "/develop/headers", HOME CONFIG "/develop/headers$a",
HOME CONFIG NON_PACKAGED, HOME CONFIG NON_PACKAGED,
HOME CONFIG NON_PACKAGED "/add-ons", HOME CONFIG NON_PACKAGED "/add-ons$a",
HOME CONFIG NON_PACKAGED "/add-ons/Translators", HOME CONFIG NON_PACKAGED "/add-ons$a/Translators",
HOME CONFIG NON_PACKAGED "/add-ons/media", HOME CONFIG NON_PACKAGED "/add-ons$a/media",
HOME CONFIG NON_PACKAGED "/bin", HOME CONFIG NON_PACKAGED "/bin$a",
HOME CONFIG NON_PACKAGED "/data", HOME CONFIG NON_PACKAGED "/data",
HOME CONFIG NON_PACKAGED "/data/fonts", HOME CONFIG NON_PACKAGED "/data/fonts",
HOME CONFIG NON_PACKAGED "/data/sounds", HOME CONFIG NON_PACKAGED "/data/sounds",
HOME CONFIG NON_PACKAGED "/documentation", HOME CONFIG NON_PACKAGED "/documentation",
HOME CONFIG NON_PACKAGED "/lib", HOME CONFIG NON_PACKAGED "/lib$a",
HOME CONFIG NON_PACKAGED "/develop/headers", HOME CONFIG NON_PACKAGED "/develop/headers$a",
HOME CONFIG NON_PACKAGED "/develop", HOME CONFIG NON_PACKAGED "/develop",
HOME CONFIG "/develop", HOME CONFIG "/develop",
HOME CONFIG "/documentation", HOME CONFIG "/documentation",
HOME CONFIG "/servers", HOME CONFIG "/servers",
HOME CONFIG "/apps", HOME CONFIG "/apps",
HOME CONFIG "/bin", HOME CONFIG "/bin$a",
HOME CONFIG "/preferences", HOME CONFIG "/preferences",
HOME CONFIG "/settings/etc", HOME CONFIG "/settings/etc",
HOME CONFIG "/var/log", 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 - // #pragma mark -
status_t status_t
__find_directory(directory_which which, dev_t device, bool createIt, __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; status_t err = B_OK;
dev_t bootDevice = -1; dev_t bootDevice = -1;
struct fs_info fsInfo; struct fs_info fsInfo;
struct stat st; struct stat st;
char *buffer = NULL;
const char *home = NULL;
const char *templatePath = NULL; const char *templatePath = NULL;
/* as with the R5 version, no on-stack buffer */ /* 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); memset(buffer, 0, pathLength);
/* fiddle with non-boot volume for items that need it */ /* 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"); bootDevice = dev_for_path("/boot");
if (device <= 0) if (device <= 0)
device = bootDevice; device = bootDevice;
if (fs_stat_dev(device, &fsInfo) < B_OK) { if (fs_stat_dev(device, &fsInfo) != B_OK)
free(buffer);
return ENODEV; return ENODEV;
}
if (device != bootDevice) { if (device != bootDevice) {
#ifdef _KERNEL_MODE #ifdef _KERNEL_MODE
err = _user_entry_ref_to_path(device, fsInfo.root, /*"."*/ 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, /*"."*/ err = _kern_entry_ref_to_path(device, fsInfo.root, /*"."*/
NULL, buffer, pathLength); NULL, buffer, pathLength);
#endif #endif
if (err != B_OK)
return err;
} else { } else {
/* use the user id to find the home folder */ /* use the user id to find the home folder */
/* done later */ /* done later */
@ -269,11 +313,6 @@ __find_directory(directory_which which, dev_t device, bool createIt,
break; break;
} }
if (err < B_OK) {
free(buffer);
return err;
}
switch ((int)which) { switch ((int)which) {
/* Per volume directories */ /* Per volume directories */
case B_DESKTOP_DIRECTORY: case B_DESKTOP_DIRECTORY:
@ -394,71 +433,69 @@ __find_directory(directory_which which, dev_t device, bool createIt,
/* Global directories */ /* Global directories */
case B_APPS_DIRECTORY: case B_APPS_DIRECTORY:
case B_UTILITIES_DIRECTORY:
templatePath = SYSTEM "/apps"; templatePath = SYSTEM "/apps";
break; break;
case B_PREFERENCES_DIRECTORY: case B_PREFERENCES_DIRECTORY:
templatePath = SYSTEM "/preferences"; templatePath = SYSTEM "/preferences";
break; break;
case B_UTILITIES_DIRECTORY:
templatePath = "utilities";
break;
case B_PACKAGE_LINKS_DIRECTORY: case B_PACKAGE_LINKS_DIRECTORY:
templatePath = "packages"; templatePath = "packages";
break; break;
default: default:
free(buffer);
return EINVAL; return EINVAL;
} }
err = B_OK; if (templatePath == NULL)
if (templatePath) { return ENOENT;
if (!strncmp(templatePath, "$h", 2)) {
if (bootDevice > -1 && device != bootDevice) { PathBuffer pathBuffer(buffer, pathLength, strlen(buffer));
int l = pathLength - strlen(buffer);
if (l > 5) // resolve "$h" placeholder to the user's home directory
strncat(buffer, "/home", 5); if (!strncmp(templatePath, "$h", 2)) {
} else { 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 #ifndef _KERNEL_MODE
#ifdef USE_PWENTS const char* architecture = __get_architecture();
struct passwd pwBuffer; if (strcmp(architecture, __get_primary_architecture()) != 0) {
char pwStringBuffer[MAX_PASSWD_BUFFER_SIZE]; pathBuffer.Append('/');
struct passwd *pw; pathBuffer.Append(architecture);
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);
} }
templatePath += 2; #endif
} else templatePath = dollar + 2;
strlcat(buffer, "/", pathLength); }
}
if (!err && strlen(buffer) + 2 + strlen(templatePath) // append (remainder of) template path
< (uint32)pathLength) { pathBuffer.Append(templatePath);
strcat(buffer, templatePath);
} else
err = err ? err : E2BIG;
} else
err = err ? err : ENOENT;
if (!err && createIt && stat(buffer, &st) < 0) if (pathBuffer.Length() >= pathLength)
return E2BIG;
if (createIt && stat(buffer, &st) < 0) {
err = create_path(buffer, 0755); err = create_path(buffer, 0755);
if (!err) if (err != B_OK)
strlcpy(returnedPath, buffer, pathLength); return err;
}
free(buffer); strlcpy(returnedPath, buffer, pathLength);
return err; return B_OK;
} }

View File

@ -19,6 +19,8 @@
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <syscalls.h> #include <syscalls.h>
#include "PathBuffer.h"
static const char* const kInstallationLocations[] = { static const char* const kInstallationLocations[] = {
"/boot/home/config/non-packaged", "/boot/home/config/non-packaged",
@ -43,53 +45,6 @@ static size_t kArchitectureSpecificBaseDirectoryCount =
/ sizeof(kArchitectureSpecificBaseDirectories[0]); / 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 /*! Returns the installation location relative path for the given base directory
constant and installation location index. A '%' in the returned path must be constant and installation location index. A '%' in the returned path must be
replaced by "" for the primary architecture and by "/<arch>" for a secondary replaced by "" for the primary architecture and by "/<arch>" for a secondary