xfs: extended attributes necessary hooks and shortform attributes support
- Implemented all necessary hooks for extended attributes in kernel_interface.cpp - Implemented an abstract class attribute which will act as an interface between all forms of extended attributes in xfs - An attempt to read shortform extended attributes Change-Id: Icff9329b790f9fcfc0b078f61059795af9d9e486 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5570 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
parent
950809231f
commit
b4b3f69fca
28
src/add-ons/kernel/file_systems/xfs/Attribute.cpp
Normal file
28
src/add-ons/kernel/file_systems/xfs/Attribute.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2022, Raghav Sharma, raghavself28@gmail.com
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Attribute.h"
|
||||
|
||||
#include "ShortAttribute.h"
|
||||
|
||||
|
||||
Attribute::~Attribute()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Attribute*
|
||||
Attribute::Init(Inode* inode)
|
||||
{
|
||||
if (inode->AttrFormat() == XFS_DINODE_FMT_LOCAL) {
|
||||
TRACE("Attribute:Init: LOCAL\n");
|
||||
ShortAttribute* shortAttr = new(std::nothrow) ShortAttribute(inode);
|
||||
return shortAttr;
|
||||
}
|
||||
|
||||
// Invalid format
|
||||
return NULL;
|
||||
}
|
41
src/add-ons/kernel/file_systems/xfs/Attribute.h
Normal file
41
src/add-ons/kernel/file_systems/xfs/Attribute.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2022, Raghav Sharma, raghavself28@gmail.com
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ATTRIBUTE_H
|
||||
#define ATTRIBUTE_H
|
||||
|
||||
|
||||
#include "Inode.h"
|
||||
|
||||
|
||||
struct attr_cookie {
|
||||
char name[B_ATTR_NAME_LENGTH];
|
||||
uint32 type;
|
||||
int open_mode;
|
||||
bool create;
|
||||
};
|
||||
|
||||
|
||||
// This class will act as an interface between all types of attributes for xfs
|
||||
class Attribute {
|
||||
public:
|
||||
|
||||
virtual ~Attribute() = 0;
|
||||
|
||||
virtual status_t Open(const char* name, int openMode,
|
||||
attr_cookie** _cookie) = 0;
|
||||
|
||||
virtual status_t Stat(attr_cookie* cookie, struct stat& stat) = 0;
|
||||
|
||||
virtual status_t Read(attr_cookie* cookie, off_t pos,
|
||||
uint8* buffer, size_t* length) = 0;
|
||||
|
||||
virtual status_t GetNext(char* name, size_t* nameLength) = 0;
|
||||
|
||||
virtual status_t Lookup(const char* name, size_t* nameLength) = 0;
|
||||
|
||||
static Attribute* Init(Inode* inode);
|
||||
};
|
||||
|
||||
#endif
|
@ -9,7 +9,7 @@
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
//#define TRACE_XFS
|
||||
#define TRACE_XFS
|
||||
#ifdef TRACE_XFS
|
||||
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
||||
#ifdef FS_SHELL
|
||||
|
@ -150,6 +150,13 @@ xfs_inode_t::Format() const
|
||||
}
|
||||
|
||||
|
||||
int8
|
||||
xfs_inode_t::AttrFormat() const
|
||||
{
|
||||
return di_aformat;
|
||||
}
|
||||
|
||||
|
||||
xfs_extnum_t
|
||||
xfs_inode_t::DataExtentsCount() const
|
||||
{
|
||||
|
@ -210,6 +210,7 @@ struct xfs_inode_t {
|
||||
|
||||
int8 Format() const;
|
||||
// The format of the inode
|
||||
int8 AttrFormat() const;
|
||||
xfs_fsize_t Size() const;
|
||||
xfs_rfsblock_t BlockCount() const;
|
||||
uint32 NLink() const;
|
||||
@ -360,6 +361,8 @@ public:
|
||||
|
||||
int8 Format() const { return fNode->Format(); }
|
||||
|
||||
int8 AttrFormat() const { return fNode->AttrFormat(); }
|
||||
|
||||
bool IsLocal() const
|
||||
{ return
|
||||
Format() == XFS_DINODE_FMT_LOCAL; }
|
||||
|
@ -21,6 +21,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] : true ;
|
||||
|
||||
local xfsSources =
|
||||
Attribute.cpp
|
||||
BPlusTree.cpp
|
||||
Directory.cpp
|
||||
Extent.cpp
|
||||
@ -29,6 +30,7 @@ local xfsSources =
|
||||
kernel_interface.cpp
|
||||
LeafDirectory.cpp
|
||||
Node.cpp
|
||||
ShortAttribute.cpp
|
||||
ShortDirectory.cpp
|
||||
Volume.cpp
|
||||
xfs.cpp
|
||||
|
170
src/add-ons/kernel/file_systems/xfs/ShortAttribute.cpp
Normal file
170
src/add-ons/kernel/file_systems/xfs/ShortAttribute.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2022, Raghav Sharma, raghavself28@gmail.com
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ShortAttribute.h"
|
||||
|
||||
|
||||
ShortAttribute::ShortAttribute(Inode* inode)
|
||||
:
|
||||
fInode(inode),
|
||||
fName(NULL)
|
||||
{
|
||||
fHeader = (AShortFormHeader*)(DIR_AFORK_PTR(fInode->Buffer(),
|
||||
fInode->CoreInodeSize(), fInode->ForkOffset()));
|
||||
|
||||
fLastEntryOffset = 0;
|
||||
}
|
||||
|
||||
|
||||
ShortAttribute::~ShortAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
ShortAttribute::_DataLength(AShortFormEntry* entry)
|
||||
{
|
||||
return entry->namelen + entry->valuelen;
|
||||
}
|
||||
|
||||
|
||||
AShortFormEntry*
|
||||
ShortAttribute::_FirstEntry()
|
||||
{
|
||||
return (AShortFormEntry*) ((char*) fHeader + sizeof(AShortFormHeader));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShortAttribute::Open(const char* name, int openMode, attr_cookie** _cookie)
|
||||
{
|
||||
TRACE("ShortAttribute::Open\n");
|
||||
status_t status;
|
||||
|
||||
size_t length = strlen(name);
|
||||
status = Lookup(name, &length);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
attr_cookie* cookie = new(std::nothrow) attr_cookie;
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fName = name;
|
||||
|
||||
// initialize the cookie
|
||||
strlcpy(cookie->name, fName, B_ATTR_NAME_LENGTH);
|
||||
cookie->open_mode = openMode;
|
||||
cookie->create = false;
|
||||
|
||||
*_cookie = cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShortAttribute::Stat(attr_cookie* cookie, struct stat& stat)
|
||||
{
|
||||
TRACE("Short Attribute : Stat\n");
|
||||
|
||||
fName = cookie->name;
|
||||
|
||||
size_t namelength = strlen(fName);
|
||||
|
||||
// check if this attribute exists
|
||||
status_t status = Lookup(fName, &namelength);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
// We have valid attribute entry to stat
|
||||
stat.st_type = B_XATTR_TYPE;
|
||||
stat.st_size = _DataLength(fEntry);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShortAttribute::Read(attr_cookie* cookie, off_t pos, uint8* buffer, size_t* length)
|
||||
{
|
||||
TRACE("Short Attribute : Read\n");
|
||||
|
||||
if (pos < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
fName = cookie->name;
|
||||
|
||||
size_t namelength = strlen(fName);
|
||||
|
||||
status_t status = Lookup(fName, &namelength);
|
||||
|
||||
uint32 lengthToRead = 0;
|
||||
|
||||
if (pos + *length > fEntry->valuelen)
|
||||
lengthToRead = fEntry->valuelen - pos;
|
||||
else
|
||||
lengthToRead = *length;
|
||||
|
||||
char* ptrToOffset = (char*) fHeader + sizeof(AShortFormHeader)
|
||||
+ 3 * sizeof(uint8) + fEntry->namelen;
|
||||
|
||||
memcpy(buffer, ptrToOffset, lengthToRead);
|
||||
|
||||
*length = lengthToRead;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShortAttribute::GetNext(char* name, size_t* nameLength)
|
||||
{
|
||||
TRACE("Short Attribute : GetNext\n");
|
||||
|
||||
AShortFormEntry* entry = _FirstEntry();
|
||||
uint16 curOffset = 1;
|
||||
for (int i = 0; i < fHeader->count; i++) {
|
||||
if (curOffset > fLastEntryOffset) {
|
||||
|
||||
fLastEntryOffset = curOffset;
|
||||
|
||||
char* PtrToOffset = (char*)entry + 3 * sizeof(uint8);
|
||||
|
||||
memcpy(name, PtrToOffset, entry->namelen);
|
||||
name[entry->namelen] = '\0';
|
||||
*nameLength = entry->namelen + 1;
|
||||
TRACE("Entry found name : %s, namelength : %ld", name, *nameLength);
|
||||
return B_OK;
|
||||
}
|
||||
entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry));
|
||||
curOffset += 3 * sizeof(uint8) + _DataLength(entry);
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShortAttribute::Lookup(const char* name, size_t* nameLength)
|
||||
{
|
||||
TRACE("Short Attribute : Lookup\n");
|
||||
|
||||
AShortFormEntry* entry = _FirstEntry();
|
||||
|
||||
int status;
|
||||
|
||||
for (int i = 0; i < fHeader->count; i++) {
|
||||
char* PtrToOffset = (char*)entry + 3 * sizeof(uint8);
|
||||
status = strncmp(name, PtrToOffset, *nameLength);
|
||||
if (status == 0) {
|
||||
fEntry = entry;
|
||||
return B_OK;
|
||||
}
|
||||
entry = (AShortFormEntry*)((char*)entry + 3 * sizeof(uint8) + _DataLength(entry));
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
57
src/add-ons/kernel/file_systems/xfs/ShortAttribute.h
Normal file
57
src/add-ons/kernel/file_systems/xfs/ShortAttribute.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2022, Raghav Sharma, raghavself28@gmail.com
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SHORT_ATTRIBUTE_H
|
||||
#define SHORT_ATTRIBUTE_H
|
||||
|
||||
|
||||
#include "Attribute.h"
|
||||
#include "Inode.h"
|
||||
|
||||
|
||||
// xfs_attr_sf_hdr
|
||||
struct AShortFormHeader {
|
||||
uint16 totsize;
|
||||
uint8 count;
|
||||
uint8 padding;
|
||||
};
|
||||
|
||||
|
||||
// xfs_attr_sf_entry
|
||||
struct AShortFormEntry {
|
||||
uint8 namelen;
|
||||
uint8 valuelen;
|
||||
uint8 flags;
|
||||
uint8 nameval[];
|
||||
};
|
||||
|
||||
|
||||
class ShortAttribute : public Attribute {
|
||||
public:
|
||||
ShortAttribute(Inode* inode);
|
||||
~ShortAttribute();
|
||||
|
||||
status_t Stat(attr_cookie* cookie, struct stat& stat);
|
||||
|
||||
status_t Read(attr_cookie* cookie, off_t pos,
|
||||
uint8* buffer, size_t* length);
|
||||
|
||||
status_t Open(const char* name, int openMode, attr_cookie** _cookie);
|
||||
|
||||
status_t GetNext(char* name, size_t* nameLength);
|
||||
|
||||
status_t Lookup(const char* name, size_t* nameLength);
|
||||
private:
|
||||
uint32 _DataLength(AShortFormEntry* entry);
|
||||
|
||||
AShortFormEntry* _FirstEntry();
|
||||
|
||||
Inode* fInode;
|
||||
const char* fName;
|
||||
AShortFormHeader* fHeader;
|
||||
AShortFormEntry* fEntry;
|
||||
uint32 fLastEntryOffset;
|
||||
};
|
||||
|
||||
#endif
|
@ -8,6 +8,7 @@
|
||||
#include "system_dependencies.h"
|
||||
#include "Directory.h"
|
||||
#include "Inode.h"
|
||||
#include "ShortAttribute.h"
|
||||
#include "Utility.h"
|
||||
#include "Volume.h"
|
||||
|
||||
@ -471,21 +472,35 @@ xfs_free_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||
static status_t
|
||||
xfs_open_attr_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
TRACE("%s()\n", __FUNCTION__);
|
||||
|
||||
// Attributes are only on files
|
||||
if (!inode->IsFile())
|
||||
return B_NOT_SUPPORTED;
|
||||
|
||||
Attribute* iterator = Attribute::Init(inode);
|
||||
if (iterator == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
*_cookie = iterator;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
xfs_close_attr_dir(fs_volume *_volume, fs_vnode *_node, void *cookie)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
TRACE("%s()\n", __FUNCTION__);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
xfs_free_attr_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
delete (Attribute*)_cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -493,7 +508,27 @@ static status_t
|
||||
xfs_read_attr_dir(fs_volume *_volume, fs_vnode *_node,
|
||||
void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
TRACE("%s()\n", __FUNCTION__);
|
||||
Attribute* iterator = (Attribute*)_cookie;
|
||||
|
||||
size_t length = bufferSize;
|
||||
status_t status = iterator->GetNext(dirent->d_name, &length);
|
||||
if (status == B_ENTRY_NOT_FOUND) {
|
||||
*_num = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
dirent->d_dev = volume->ID();
|
||||
dirent->d_ino = inode->ID();
|
||||
dirent->d_reclen = offsetof(struct dirent, d_name) + length + 1;
|
||||
*_num = 1;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -517,7 +552,26 @@ static status_t
|
||||
xfs_open_attr(fs_volume *_volume, fs_vnode *_node, const char *name,
|
||||
int openMode, void **_cookie)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
TRACE("%s()\n", __FUNCTION__);
|
||||
|
||||
status_t status;
|
||||
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
|
||||
int accessMode = open_mode_to_access(openMode) | (openMode & O_TRUNC ? W_OK : 0);
|
||||
status = inode->CheckPermissions(accessMode);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
Attribute* attribute = Attribute::Init(inode);
|
||||
|
||||
if (attribute == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status = attribute->Open(name, openMode, (attr_cookie**)_cookie);
|
||||
delete attribute;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -525,14 +579,15 @@ static status_t
|
||||
xfs_close_attr(fs_volume *_volume, fs_vnode *_node,
|
||||
void *cookie)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
xfs_free_attr_cookie(fs_volume *_volume, fs_vnode *_node, void *cookie)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
delete (attr_cookie*)cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -540,7 +595,20 @@ static status_t
|
||||
xfs_read_attr(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||
off_t pos, void *buffer, size_t *_length)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
TRACE("%s()\n", __FUNCTION__);
|
||||
|
||||
attr_cookie* cookie = (attr_cookie*)_cookie;
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
|
||||
Attribute* attribute = Attribute::Init(inode);
|
||||
|
||||
if (attribute == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t status = attribute->Read(cookie, pos, (uint8*)buffer, _length);
|
||||
delete attribute;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -556,7 +624,20 @@ static status_t
|
||||
xfs_read_attr_stat(fs_volume *_volume, fs_vnode *_node,
|
||||
void *_cookie, struct stat *stat)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
TRACE("%s()\n", __FUNCTION__);
|
||||
|
||||
attr_cookie* cookie = (attr_cookie*)_cookie;
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
|
||||
Attribute* attribute = Attribute::Init(inode);
|
||||
|
||||
if (attribute == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t status = attribute->Stat(cookie, *stat);
|
||||
delete attribute;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -763,6 +844,7 @@ file_system_module_info sxfsFileSystem = {
|
||||
xfs_initialize,
|
||||
xfs_uninitialize};
|
||||
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&sxfsFileSystem,
|
||||
NULL,
|
||||
|
@ -41,6 +41,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] : true ;
|
||||
|
||||
local xfsSource =
|
||||
Attribute.cpp
|
||||
BPlusTree.cpp
|
||||
Directory.cpp
|
||||
Extent.cpp
|
||||
@ -48,6 +49,7 @@ local xfsSource =
|
||||
kernel_interface.cpp
|
||||
LeafDirectory.cpp
|
||||
Node.cpp
|
||||
ShortAttribute.cpp
|
||||
ShortDirectory.cpp
|
||||
Volume.cpp
|
||||
xfs.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user