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:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
errno = error;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fs_read_attr
|
// fs_read_attr
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user