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