Open/close attribute support for xattrs backend

For the xattr/BSD (untyped) attribute backend implement fs_fopen_attr()
and fs_close_attr(). A new AttributeDescriptor is created. It is
currently used in write_pos() only.
This commit is contained in:
Ingo Weinhold
2011-07-17 16:54:09 +02:00
parent 62fef8b3fc
commit e781b1b5a8
5 changed files with 305 additions and 87 deletions
+14 -1
View File
@@ -969,12 +969,25 @@ read_pos(int fd, off_t pos, void *buffer, size_t bufferSize)
ssize_t ssize_t
write_pos(int fd, off_t pos, const void *buffer, size_t bufferSize) write_pos(int fd, off_t pos, const void *buffer, size_t bufferSize)
{ {
// If this is an attribute descriptor, let it do the job.
AttributeDescriptor* descriptor
= dynamic_cast<AttributeDescriptor*>(get_descriptor(fd));
if (descriptor != NULL) {
status_t error = descriptor->Write(pos, buffer, bufferSize);
if (error != B_OK) {
errno = error;
return -1;
}
return 0;
}
// seek // seek
off_t result = lseek(fd, pos, SEEK_SET); off_t result = lseek(fd, pos, SEEK_SET);
if (result < 0) if (result < 0)
return errno; return errno;
// read // write
ssize_t bytesWritten = haiku_host_platform_write(fd, buffer, bufferSize); ssize_t bytesWritten = haiku_host_platform_write(fd, buffer, bufferSize);
if (bytesWritten < 0) { if (bytesWritten < 0) {
errno = bytesWritten; errno = bytesWritten;
+2 -2
View File
@@ -309,9 +309,9 @@ fs_rewind_attr_dir(DIR *dir)
rewinddir(dir); rewinddir(dir);
} }
// fs_open_attr // fs_fopen_attr
int int
fs_open_attr(int fd, const char *attribute, uint32 type, int openMode) fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode)
{ {
if (!attribute) { if (!attribute) {
errno = B_BAD_VALUE; errno = B_BAD_VALUE;
+36 -8
View File
@@ -452,22 +452,50 @@ fs_rewind_attr_dir(DIR *dir)
attrDir->RewindDir(); attrDir->RewindDir();
} }
// fs_open_attr // fs_fopen_attr
int int
fs_open_attr(int fd, const char *attribute, uint32 type, int openMode) fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode)
{ {
// not supported ATM if (fd < 0) {
errno = B_BAD_VALUE; errno = B_BAD_VALUE;
return -1; return -1;
}
AttributeDescriptor* descriptor = new(std::nothrow) AttributeDescriptor(fd,
attribute, type, openMode);
if (descriptor == NULL) {
errno = B_NO_MEMORY;
return -1;
}
status_t error = descriptor->Init();
if (error != B_OK) {
delete descriptor;
errno = error;
return -1;
}
int attributeFD = add_descriptor(descriptor);
if (attributeFD < 0) {
delete descriptor;
errno = B_NO_MEMORY;
return -1;
}
return attributeFD;
} }
// fs_close_attr // fs_close_attr
int int
fs_close_attr(int fd) fs_close_attr(int fd)
{ {
// not supported ATM status_t error = delete_descriptor(fd);
errno = B_BAD_VALUE; if (error != 0) {
return -1; errno = error;
return -1;
}
return 0;
} }
// fs_read_attr // fs_read_attr
+147
View File
@@ -11,7 +11,9 @@
#include <map> #include <map>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <fs_attr.h> #include <fs_attr.h>
@@ -250,6 +252,151 @@ SymlinkDescriptor::GetPath(string& path) const
} }
// #pragma mark - AttributeDescriptor
AttributeDescriptor::AttributeDescriptor(int fileFD, const char* attribute,
uint32 type, int openMode)
:
fFileFD(dup(fileFD)),
fType(type),
fOpenMode(openMode),
fData(NULL),
fDataSize(0)
{
strlcpy(fAttribute, attribute, sizeof(fAttribute));
}
AttributeDescriptor::~AttributeDescriptor()
{
Close();
}
status_t
AttributeDescriptor::Init()
{
if (fFileFD < 0)
return B_IO_ERROR;
// stat the attribute
attr_info info;
if (fs_stat_attr(fFileFD, fAttribute, &info) < 0) {
if (errno == B_ENTRY_NOT_FOUND) {
if ((fOpenMode & O_CREAT) == 0)
return errno;
// create the attribute
if (fs_write_attr(fFileFD, fAttribute, fType, 0, NULL, 0) < 0)
return errno;
return B_OK;
}
return errno;
}
if ((fOpenMode & O_TRUNC) == 0) {
// truncate the attribute
if (fs_write_attr(fFileFD, fAttribute, fType, 0, NULL, 0) < 0)
return errno;
return B_OK;
}
// we have to read in the attribute data
if (info.size == 0)
return B_OK;
fData = (uint8*)malloc(info.size);
if (fData == NULL)
return B_NO_MEMORY;
fDataSize = info.size;
ssize_t bytesRead = fs_read_attr(fFileFD, fAttribute, fType, 0, fData,
fDataSize);
if (bytesRead < 0)
return errno;
if ((size_t)bytesRead != fDataSize)
return B_IO_ERROR;
return B_OK;
}
status_t
AttributeDescriptor::Write(off_t offset, const void* buffer, size_t bufferSize)
{
if (offset < 0)
return B_BAD_VALUE;
if ((fOpenMode & O_ACCMODE) != O_WRONLY
&& (fOpenMode & O_ACCMODE) != O_RDWR) {
return B_NOT_ALLOWED;
}
// we may need to resize the buffer
size_t minSize = (size_t)offset + bufferSize;
if (minSize > fDataSize) {
uint8* data = (uint8*)realloc(fData, minSize);
if (data == NULL)
return B_NO_MEMORY;
if ((size_t)offset > fDataSize)
memset(data + offset, 0, offset - fDataSize);
fData = data;
fDataSize = minSize;
}
// copy the data and write all of it
if (bufferSize == 0)
return B_OK;
memcpy((uint8*)fData + offset, buffer, bufferSize);
ssize_t bytesWritten = fs_write_attr(fFileFD, fAttribute, fType, 0,
fData, fDataSize);
if (bytesWritten < 0)
return errno;
if ((size_t)bytesWritten != fDataSize)
return B_IO_ERROR;
return B_OK;
}
status_t
AttributeDescriptor::Close()
{
if (fFileFD < 0)
return B_BAD_VALUE;
close(fFileFD);
fFileFD = -1;
free(fData);
fData = NULL;
fDataSize = 0;
return B_OK;
}
status_t
AttributeDescriptor::Dup(Descriptor*& clone)
{
return B_NOT_SUPPORTED;
}
status_t
AttributeDescriptor::GetStat(bool traverseLink, struct stat* st)
{
return B_NOT_SUPPORTED;
}
// #pragma mark - AttrDirDescriptor // #pragma mark - AttrDirDescriptor
+30
View File
@@ -5,6 +5,7 @@
#include <string> #include <string>
#include <StorageDefs.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include "NodeRef.h" #include "NodeRef.h"
@@ -71,6 +72,35 @@ struct SymlinkDescriptor : Descriptor {
virtual status_t GetPath(string& path) const; virtual status_t GetPath(string& path) const;
}; };
// AttributeDescriptor
struct AttributeDescriptor : Descriptor {
AttributeDescriptor(int fileFD,
const char* attribute, uint32 type,
int openMode);
virtual ~AttributeDescriptor();
status_t Init();
status_t Write(off_t offset, const void* buffer,
size_t bufferSize);
int FileFD() const { return fFileFD; }
const char* Attribute() const { return fAttribute; }
uint32 Type() const { return fType; }
int OpenMode() const { return fOpenMode; }
virtual status_t Close();
virtual status_t Dup(Descriptor*& clone);
virtual status_t GetStat(bool traverseLink, struct stat* st);
private:
int fFileFD;
char fAttribute[B_ATTR_NAME_LENGTH];
uint32 fType;
int fOpenMode;
uint8* fData;
size_t fDataSize;
};
// AttrDirDescriptor // AttrDirDescriptor
struct AttrDirDescriptor : DirectoryDescriptor { struct AttrDirDescriptor : DirectoryDescriptor {