From b360cc7f0003ab716c974ee4bca3113d08054ed5 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 6 Sep 2008 23:46:59 +0000 Subject: [PATCH] Refactored the BeOS attribute emulation using xattr a bit: * Renamed fs_attr_xattr.cpp to libroot/fs_attr_untyped.cpp. * Pulled the xattr specifics into a separate fs_attr_xattr.h. * Added fs_attr_extattr.h, interfacing with FreeBSD's extattr support. Totally untested yet. Might not even compile. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27350 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/build/libroot/fs_attr.cpp | 2 +- src/build/libroot/fs_attr_extattr.h | 89 +++++++++++++++++++ ...{fs_attr_xattr.cpp => fs_attr_untyped.cpp} | 69 +++++++------- src/build/libroot/fs_attr_xattr.h | 58 ++++++++++++ 4 files changed, 187 insertions(+), 31 deletions(-) create mode 100644 src/build/libroot/fs_attr_extattr.h rename src/build/libroot/{fs_attr_xattr.cpp => fs_attr_untyped.cpp} (89%) create mode 100644 src/build/libroot/fs_attr_xattr.h diff --git a/src/build/libroot/fs_attr.cpp b/src/build/libroot/fs_attr.cpp index 8da88f2a7c..7dea6a015f 100644 --- a/src/build/libroot/fs_attr.cpp +++ b/src/build/libroot/fs_attr.cpp @@ -1,5 +1,5 @@ #ifdef HAIKU_HOST_USE_XATTR -# include "fs_attr_xattr.cpp" +# include "fs_attr_untyped.cpp" #else # include "fs_attr_generic.cpp" #endif diff --git a/src/build/libroot/fs_attr_extattr.h b/src/build/libroot/fs_attr_extattr.h new file mode 100644 index 0000000000..527c5df389 --- /dev/null +++ b/src/build/libroot/fs_attr_extattr.h @@ -0,0 +1,89 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef FS_ATTR_EXTATTR_H +#define FS_ATTR_EXTATTR_H + +/*! Included by fs_attr_untyped.cpp. Interfaces with FreeBSD extattr support. +*/ + + +#include +#include + + +// the namespace all attributes live in +static const char* kAttributeNamespace = "haiku."; +static const int kAttributeNamespaceLen = 6; + + +static ssize_t +list_attributes(int fd, const char* path, char* buffer, size_t bufferSize) +{ + ssize_t bytesRead; + if (fd >= 0) { + bytesRead = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, buffer, + bufferSize); + } else { + bytesRead = extattr_list_link(path, EXTATTR_NAMESPACE_USER, buffer, + bufferSize); + } + + if (bytesRead <= 0) + return bytesRead; + + // The listing is in a different format than expected by the caller. Here + // we get a sequence of (, ) pairs, but expected + // is a sequence of null-terminated names. Let's convert it. + int index = *buffer; + memmove(buffer, buffer + 1, bytesRead - 1); + + while (index < bytesRead - 1) { + int len = buffer[index]; + buffer[index] = '\0'; + index += len + 1; + } + + buffer[bytesRead - 1] = '\0'; + + return bytesRead; +} + + +static ssize_t +get_attribute(int fd, const char* path, const char* attribute, void* buffer, + size_t bufferSize) +{ + if (fd >= 0) { + return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, attribute, buffer, + bufferSize); + } + return extattr_get_link(path, EXTATTR_NAMESPACE_USER, attribute, buffer, + bufferSize); +} + + +static int +set_attribute(int fd, const char* path, const char* attribute, + const void* buffer, size_t bufferSize) +{ + if (fd >= 0) { + return extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, attribute, buffer, + bufferSize); + } + return extattr_set_link(path, EXTATTR_NAMESPACE_USER, attribute, buffer, + bufferSize); +} + + +static int +remove_attribute(int fd, const char* path, const char* attribute) +{ + if (fd >= 0) + return extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, attribute); + return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, attribute); +} + + +#endif // FS_ATTR_EXTATTR_H diff --git a/src/build/libroot/fs_attr_xattr.cpp b/src/build/libroot/fs_attr_untyped.cpp similarity index 89% rename from src/build/libroot/fs_attr_xattr.cpp rename to src/build/libroot/fs_attr_untyped.cpp index 37e957f4b5..a0c4b22279 100644 --- a/src/build/libroot/fs_attr_xattr.cpp +++ b/src/build/libroot/fs_attr_untyped.cpp @@ -1,3 +1,12 @@ +/* + * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +/*! Emulation BeOS-style attributes by mapping them to untyped attributes of + the host platform (xattr on Linux, extattr on FreeBSD). +*/ + #ifdef BUILDING_FS_SHELL # include "compat.h" @@ -23,22 +32,27 @@ #include #include -#include - #include #include #include + +// Include the interface to the host platform attributes support. +#if defined(HAIKU_HOST_PLATFORM_LINUX) +# include "fs_attr_xattr.h" +#elif defined(HAIKU_HOST_PLATFORM_FREEBSD) +# include "fs_attr_extattr.h" +#else +# error No attribute support for this host platform! +#endif + + namespace BPrivate {} using namespace BPrivate; using std::map; using std::string; -// the namespace all attributes live in -static const char* kAttributeNamespace = "user.haiku."; -static const int kAttributeNamespaceLen = 11; - // the maximum length of an attribute listing we support static const int kMaxAttributeListingLength = 10240; @@ -270,13 +284,8 @@ private: char listing[kMaxAttributeListingLength]; // get the listing - ssize_t length; - if (fFileFD >= 0) { - length = flistxattr(fFileFD, listing, kMaxAttributeListingLength); - } else { - length = llistxattr(fPath.c_str(), listing, - kMaxAttributeListingLength); - } + ssize_t length = list_attributes(fFileFD, fPath.c_str(), listing, + kMaxAttributeListingLength); if (length < 0) return errno; @@ -487,11 +496,11 @@ fs_read_attr(int fd, const char *_attribute, uint32 type, off_t pos, ssize_t bytesRead = min_c((size_t)kMaxAttributeLength, readBytes) + sizeof(AttributeHeader); if (localFD.Path()) { - bytesRead = lgetxattr(localFD.Path(), attribute.c_str(), + bytesRead = get_attribute(-1, localFD.Path(), attribute.c_str(), attributeBuffer, bytesRead); } else { - bytesRead = fgetxattr(localFD.FD(), attribute.c_str(), attributeBuffer, - bytesRead); + bytesRead = get_attribute(localFD.FD(), NULL, attribute.c_str(), + attributeBuffer, bytesRead); } if (bytesRead < 0) { // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute @@ -554,16 +563,16 @@ fs_write_attr(int fd, const char *_attribute, uint32 type, off_t pos, ssize_t toWrite = sizeof(AttributeHeader) + pos + writeBytes; int result; if (localFD.Path()) { - result = lsetxattr(localFD.Path(), attribute.c_str(), attributeBuffer, - toWrite, 0); + result = set_attribute(-1, localFD.Path(), attribute.c_str(), + attributeBuffer, toWrite); } else { - result = fsetxattr(localFD.FD(), attribute.c_str(), attributeBuffer, - toWrite, 0); + result = set_attribute(localFD.FD(), NULL, attribute.c_str(), + attributeBuffer, toWrite); } if (result < 0) { - // Setting user attributes on symlinks is not allowed. So, if this is - // a symlink and we're only supposed to write a "BEOS:TYPE" attribute - // we silently pretend to have succeeded. + // Setting user attributes on symlinks is not allowed (xattr). So, if + // this is a symlink and we're only supposed to write a "BEOS:TYPE" + // attribute we silently pretend to have succeeded. if (localFD.IsSymlink() && strcmp(_attribute, "BEOS:TYPE") == 0) return writeBytes; return -1; @@ -596,9 +605,9 @@ fs_remove_attr(int fd, const char *_attribute) // remove attribute int result; if (localFD.Path()) - result = lremovexattr(localFD.Path(), attribute.c_str()); + result = remove_attribute(-1, localFD.Path(), attribute.c_str()); else - result = fremovexattr(localFD.FD(), attribute.c_str()); + result = remove_attribute(localFD.FD(), NULL, attribute.c_str()); if (result < 0) { // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute @@ -634,11 +643,11 @@ fs_stat_attr(int fd, const char *_attribute, struct attr_info *attrInfo) char attributeBuffer[sizeof(AttributeHeader) + kMaxAttributeLength]; ssize_t bytesRead = sizeof(AttributeHeader) + kMaxAttributeLength; if (localFD.Path()) { - bytesRead = lgetxattr(localFD.Path(), attribute.c_str(), + bytesRead = get_attribute(-1, localFD.Path(), attribute.c_str(), attributeBuffer, bytesRead); } else { - bytesRead = fgetxattr(localFD.FD(), attribute.c_str(), attributeBuffer, - bytesRead); + bytesRead = get_attribute(localFD.FD(), NULL, attribute.c_str(), + attributeBuffer, bytesRead); } if (bytesRead < 0) { // Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute @@ -696,8 +705,8 @@ _kern_open_attr_dir(int fd, const char *path) if (!dir) return errno; - - // create descriptor + + // create descriptor AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref); return add_descriptor(descriptor); } diff --git a/src/build/libroot/fs_attr_xattr.h b/src/build/libroot/fs_attr_xattr.h new file mode 100644 index 0000000000..ab3faf0cd5 --- /dev/null +++ b/src/build/libroot/fs_attr_xattr.h @@ -0,0 +1,58 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef FS_ATTR_XATTR_H +#define FS_ATTR_XATTR_H + +/*! Included by fs_attr_untyped.cpp. Interfaces with Linux xattr support. +*/ + + +#include + + +// the namespace all attributes live in +static const char* kAttributeNamespace = "user.haiku."; +static const int kAttributeNamespaceLen = 11; + + +static ssize_t +list_attributes(int fd, const char* path, char* buffer, size_t bufferSize) +{ + if (fd >= 0) + return flistxattr(fd, buffer, bufferSize); + return llistxattr(path, buffer, bufferSize); +} + + +static ssize_t +get_attribute(int fd, const char* path, const char* attribute, void* buffer, + size_t bufferSize) +{ + if (fd >= 0) + return fgetxattr(fd, attribute, buffer, bufferSize); + return lgetxattr(path, attribute, buffer, bufferSize); +} + + +static int +set_attribute(int fd, const char* path, const char* attribute, + const void* buffer, size_t bufferSize) +{ + if (fd >= 0) + return fsetxattr(fd, attribute, buffer, bufferSize, 0); + return lsetxattr(path, attribute, buffer, bufferSize, 0); +} + + +static int +remove_attribute(int fd, const char* path, const char* attribute) +{ + if (fd >= 0) + return fremovexattr(fd, attribute); + return lremovexattr(path, attribute); +} + + +#endif // FS_ATTR_XATTR_H