From 04c6cb37bb8e0115f90974e99d6d823857c6836e Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 17 Nov 2013 19:10:18 +0100 Subject: [PATCH] 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*(). --- src/system/kernel/lib/Jamfile | 24 +-- src/system/libroot/os/PathBuffer.h | 75 ++++++++ src/system/libroot/os/find_directory.cpp | 215 +++++++++++++---------- src/system/libroot/os/find_paths.cpp | 49 +----- 4 files changed, 216 insertions(+), 147 deletions(-) create mode 100644 src/system/libroot/os/PathBuffer.h diff --git a/src/system/kernel/lib/Jamfile b/src/system/kernel/lib/Jamfile index 58b88c2ed5..bcaa986205 100644 --- a/src/system/kernel/lib/Jamfile +++ b/src/system/kernel/lib/Jamfile @@ -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 ] ; diff --git a/src/system/libroot/os/PathBuffer.h b/src/system/libroot/os/PathBuffer.h new file mode 100644 index 0000000000..0fc0f9566b --- /dev/null +++ b/src/system/libroot/os/PathBuffer.h @@ -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 + +#include + + +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 diff --git a/src/system/libroot/os/find_directory.cpp b/src/system/libroot/os/find_directory.cpp index c7272fd40b..dd1c489b21 100644 --- a/src/system/libroot/os/find_directory.cpp +++ b/src/system/libroot/os/find_directory.cpp @@ -1,7 +1,8 @@ /* * Copyright 2004, François Revol. * Copyright 2007-2010, Axel Dörfler, axeld@pinc-software.de. - * Copyright 2011, Oliver Tappe + * 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 #include +#include #include #include +#include #include #include +#include + +#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; } diff --git a/src/system/libroot/os/find_paths.cpp b/src/system/libroot/os/find_paths.cpp index 717fb2ef11..35e628c4f7 100644 --- a/src/system/libroot/os/find_paths.cpp +++ b/src/system/libroot/os/find_paths.cpp @@ -19,6 +19,8 @@ #include #include +#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 "/" for a secondary