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
This commit is contained in:
Ingo Weinhold 2008-09-06 23:46:59 +00:00
parent ab2b993da9
commit b360cc7f00
4 changed files with 187 additions and 31 deletions

View File

@ -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

View File

@ -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 <string.h>
#include <sys/extattr.h>
// 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 (<namelen>, <unterminated name>) 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

View File

@ -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 <unistd.h>
#include <sys/stat.h>
#include <attr/xattr.h>
#include <map>
#include <string>
#include <fs_attr.h>
// 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);
}

View File

@ -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 <attr/xattr.h>
// 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