From 03544bf000d43b4ddfe673554f70f6e58efc7225 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sat, 30 Dec 2017 14:15:29 -0500 Subject: [PATCH] libroot_build: Full passthrough to system attributes. As it turns out, using the xattr emulation layer plus "libgnu" causes some strange mixups at package build time, and so packages built with it were winding up with no attributes at all. So I've just bitten the bullet and written a full passthrough layer to the system attributes. Verified using a full build of haiku.hpkg this time ... after a lot of painful debugging of symlink mixups. Hopefully I am finally rid of this plague... --- headers/build/os/kernel/fs_attr.h | 2 + src/build/libroot/Jamfile | 7 +- src/build/libroot/LocalFD.h | 59 +++++ src/build/libroot/fs_attr.cpp | 6 +- src/build/libroot/fs_attr_haiku.cpp | 313 ++++++++++++++++++++++++++ src/build/libroot/fs_attr_untyped.cpp | 55 +---- 6 files changed, 382 insertions(+), 60 deletions(-) create mode 100644 src/build/libroot/LocalFD.h create mode 100644 src/build/libroot/fs_attr_haiku.cpp diff --git a/headers/build/os/kernel/fs_attr.h b/headers/build/os/kernel/fs_attr.h index d441301d08..454914f359 100644 --- a/headers/build/os/kernel/fs_attr.h +++ b/headers/build/os/kernel/fs_attr.h @@ -23,6 +23,7 @@ extern "C" { /* Since libroot_build is also used on Haiku and linked against the real * libroot which also has the fs*attr functions, these must be shadowed. */ +#ifndef BUILDING_FS_ATTR_HAIKU #define fs_read_attr build_fs_read_attr #define fs_write_attr build_fs_write_attr #define fs_remove_attr build_fs_remove_attr @@ -35,6 +36,7 @@ extern "C" { #define fs_close_attr_dir build_fs_close_attr_dir #define fs_read_attr_dir build_fs_read_attr_dir #define fs_rewind_attr_dir build_fs_rewind_attr_dir +#endif extern ssize_t fs_read_attr(int fd, const char *attribute, uint32 type, diff --git a/src/build/libroot/Jamfile b/src/build/libroot/Jamfile index ea648a6c7e..1d22d3cd33 100644 --- a/src/build/libroot/Jamfile +++ b/src/build/libroot/Jamfile @@ -78,15 +78,10 @@ local librootSources = USES_BE_API on [ FGristFiles $(librootSources:S=$(SUFOBJ)) ] = true ; -local extraLibs ; -if $(HOST_PLATFORM) = haiku_host { - extraLibs = gnu ; -} - BuildPlatformSharedLibrary libroot_build.so : $(librootSources) : - $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) $(extraLibs) + $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) ; # TODO: This doesn't work with the function remapping. diff --git a/src/build/libroot/LocalFD.h b/src/build/libroot/LocalFD.h new file mode 100644 index 0000000000..044357aeaf --- /dev/null +++ b/src/build/libroot/LocalFD.h @@ -0,0 +1,59 @@ +/* + * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +// no header guards: must be included at appropriate part of .cpp + + +class LocalFD { +public: + LocalFD() + { + } + + ~LocalFD() + { + } + + status_t Init(int fd) + { +#ifndef BUILDING_FS_SHELL + Descriptor* descriptor = get_descriptor(fd); + if (descriptor && !descriptor->IsSystemFD()) { + // we need to get a path + fFD = -1; + return descriptor->GetPath(fPath); + } +#endif + + fFD = fd; + fPath = ""; + return B_OK; + } + + int FD() const + { + return fFD; + } + + const char* Path() const + { + return (fFD < 0 ? fPath.c_str() : NULL); + } + + bool IsSymlink() const + { + struct stat st; + int result; + if (Path()) + result = lstat(Path(), &st); + else + result = fstat(fFD, &st); + + return (result == 0 && S_ISLNK(st.st_mode)); + } + +private: + string fPath; + int fFD; +}; diff --git a/src/build/libroot/fs_attr.cpp b/src/build/libroot/fs_attr.cpp index d52e690258..0bde8666d3 100644 --- a/src/build/libroot/fs_attr.cpp +++ b/src/build/libroot/fs_attr.cpp @@ -1,5 +1,9 @@ #ifdef HAIKU_HOST_USE_XATTR -# include "fs_attr_untyped.cpp" +# ifdef HAIKU_HOST_PLATFORM_HAIKU +# include "fs_attr_haiku.cpp" +# else +# include "fs_attr_untyped.cpp" +# endif #else # include "fs_attr_generic.cpp" #endif diff --git a/src/build/libroot/fs_attr_haiku.cpp b/src/build/libroot/fs_attr_haiku.cpp new file mode 100644 index 0000000000..0a931a2f6d --- /dev/null +++ b/src/build/libroot/fs_attr_haiku.cpp @@ -0,0 +1,313 @@ +/* + * Copyright 2017, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +/*! Shim over the host Haiku fs_attr API */ + +#define BUILDING_FS_ATTR_HAIKU + // so build fs_attr.h will not shadow the fs*attr functions + + +#ifdef BUILDING_FS_SHELL +# include "compat.h" +# define B_OK 0 +# define B_BAD_VALUE EINVAL +# define B_FILE_ERROR EBADF +# define B_ERROR EINVAL +# define B_ENTRY_NOT_FOUND ENOENT +# define B_NO_MEMORY ENOMEM +#else +# include + +# include "fs_impl.h" +# include "fs_descriptors.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +namespace BPrivate {} +using namespace BPrivate; + + +namespace { + +// LocalFD +#include "LocalFD.h" + +} // unnamed namspace + + +// # pragma mark - Public API + + +// fs_open_attr_dir +extern "C" DIR * +build_fs_open_attr_dir(const char *path) +{ + return fs_open_attr_dir(path); +} + +// fs_fopen_attr_dir +extern "C" DIR* fs_lopen_attr_dir(const char *path); +extern "C" DIR* +build_fs_fopen_attr_dir(int fd) +{ + LocalFD localFD; + status_t error = localFD.Init(fd); + if (error != B_OK) { + errno = error; + return NULL; + } + + if (localFD.FD() < 0) { + return fs_lopen_attr_dir(localFD.Path()); + } else { + return fs_fopen_attr_dir(localFD.FD()); + } +} + +// fs_close_attr_dir +extern "C" int +build_fs_close_attr_dir(DIR *dir) +{ + return fs_close_attr_dir(dir); +} + +// fs_read_attr_dir +extern "C" struct dirent * +build_fs_read_attr_dir(DIR *dir) +{ + return fs_read_attr_dir(dir); +} + +// fs_rewind_attr_dir +extern "C" void +build_fs_rewind_attr_dir(DIR *dir) +{ + return fs_rewind_attr_dir(dir); +} + +// fs_fopen_attr +extern "C" int +build_fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode) +{ + if (fd < 0) { + errno = B_BAD_VALUE; + return -1; + } + + LocalFD localFD; + status_t error = localFD.Init(fd); + if (error != B_OK) { + errno = error; + return -1; + } + + if (localFD.FD() < 0) { + return fs_open_attr(localFD.Path(), attribute, type, + openMode | O_NOTRAVERSE); + } else { + return fs_fopen_attr(localFD.FD(), attribute, type, openMode); + } +} + +// fs_close_attr +extern "C" int +build_fs_close_attr(int fd) +{ + return fs_close_attr(fd); +} + +// fs_read_attr +extern "C" ssize_t +build_fs_read_attr(int fd, const char* attribute, uint32 type, off_t pos, + void *buffer, size_t readBytes) +{ + LocalFD localFD; + status_t error = localFD.Init(fd); + if (error != B_OK) { + errno = error; + return -1; + } + + ssize_t bytesRead; + if (localFD.FD() < 0) { + int fd = open(localFD.Path(), O_RDONLY | O_NOTRAVERSE); + bytesRead = fs_read_attr(fd, attribute, type, + pos, buffer, readBytes); + close(fd); + } else { + bytesRead = fs_read_attr(localFD.FD(), attribute, type, + pos, buffer, readBytes); + } + if (bytesRead < 0) { + // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute + // doesn't exist. + if (errno == ENOATTR || errno == ENODATA) + errno = B_ENTRY_NOT_FOUND; + return -1; + } + + return bytesRead; +} + +// fs_write_attr +extern "C" ssize_t +build_fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos, + const void *buffer, size_t writeBytes) +{ + LocalFD localFD; + status_t error = localFD.Init(fd); + if (error != B_OK) { + errno = error; + return -1; + } + + ssize_t written; + if (localFD.FD() < 0) { + int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY); + written = fs_write_attr(fd, attribute, type, + pos, buffer, writeBytes); + close(fd); + } else { + written = fs_write_attr(localFD.FD(), attribute, type, + pos, buffer, writeBytes); + } + + return written; +} + +// fs_remove_attr +extern "C" int +build_fs_remove_attr(int fd, const char* attribute) +{ + LocalFD localFD; + status_t error = localFD.Init(fd); + if (error != B_OK) { + errno = error; + return -1; + } + + // remove attribute + int result; + if (localFD.FD() < 0) { + int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY); + result = fs_remove_attr(fd, attribute); + close(fd); + } else { + result = fs_remove_attr(localFD.FD(), attribute); + } + + if (result < 0) { + // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute + // doesn't exist. + if (errno == ENOATTR || errno == ENODATA) + errno = B_ENTRY_NOT_FOUND; + return -1; + } + return 0; +} + +// fs_stat_attr +extern "C" int +build_fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo) +{ + if (!attribute || !attrInfo) { + errno = B_BAD_VALUE; + return -1; + } + + LocalFD localFD; + status_t error = localFD.Init(fd); + if (error != B_OK) { + errno = error; + return -1; + } + + int result; + if (localFD.FD() < 0) { + int fd = open(localFD.Path(), O_NOTRAVERSE | O_RDONLY); + result = fs_stat_attr(fd, attribute, attrInfo); + close(fd); + } else { + result = fs_stat_attr(localFD.FD(), attribute, attrInfo); + } + + return result; +} + + +// #pragma mark - Private Syscalls + + +#ifndef BUILDING_FS_SHELL + +// _kern_open_attr_dir +int +_kern_open_attr_dir(int fd, const char *path) +{ + // get node ref for the node + struct stat st; + status_t error = _kern_read_stat(fd, path, false, &st, + sizeof(struct stat)); + if (error != B_OK) { + errno = error; + return -1; + } + NodeRef ref(st); + + DIR* dir; + if (path) { + // If a path was given, get a usable path. + string realPath; + status_t error = get_path(fd, path, realPath); + if (error != B_OK) + return error; + + dir = build_fs_open_attr_dir(realPath.c_str()); + } else + dir = build_fs_fopen_attr_dir(fd); + + if (!dir) + return errno; + + // create descriptor + AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref); + return add_descriptor(descriptor); +} + +// _kern_rename_attr +status_t +_kern_rename_attr(int fromFile, const char *fromName, int toFile, + const char *toName) +{ + // not supported ATM + return B_BAD_VALUE; +} + +// _kern_remove_attr +status_t +_kern_remove_attr(int fd, const char *name) +{ + if (!name) + return B_BAD_VALUE; + + if (build_fs_remove_attr(fd, name) < 0) + return errno; + return B_OK; +} + +#endif // ! BUILDING_FS_SHELL diff --git a/src/build/libroot/fs_attr_untyped.cpp b/src/build/libroot/fs_attr_untyped.cpp index f2359eff40..2b14a39c3a 100644 --- a/src/build/libroot/fs_attr_untyped.cpp +++ b/src/build/libroot/fs_attr_untyped.cpp @@ -39,7 +39,7 @@ // Include the interface to the host platform attributes support. -#if defined(HAIKU_HOST_PLATFORM_LINUX) || defined(HAIKU_HOST_PLATFORM_HAIKU) +#if defined(HAIKU_HOST_PLATFORM_LINUX) # include "fs_attr_xattr.h" #elif defined(HAIKU_HOST_PLATFORM_FREEBSD) # include "fs_attr_extattr.h" @@ -315,58 +315,7 @@ private: }; // LocalFD -class LocalFD { -public: - LocalFD() - { - } - - ~LocalFD() - { - } - - status_t Init(int fd) - { -#ifndef BUILDING_FS_SHELL - Descriptor* descriptor = get_descriptor(fd); - if (descriptor && !descriptor->IsSystemFD()) { - // we need to get a path - fFD = -1; - return descriptor->GetPath(fPath); - } -#endif - - fFD = fd; - fPath = ""; - return B_OK; - } - - int FD() const - { - return fFD; - } - - const char* Path() const - { - return (fFD < 0 ? fPath.c_str() : NULL); - } - - bool IsSymlink() const - { - struct stat st; - int result; - if (Path()) - result = lstat(Path(), &st); - else - result = fstat(fFD, &st); - - return (result == 0 && S_ISLNK(st.st_mode)); - } - -private: - string fPath; - int fFD; -}; +#include "LocalFD.h" } // unnamed namspace