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:
Mashijams 2022-08-25 22:41:49 +05:30 committed by Adrien Destugues
parent 950809231f
commit b4b3f69fca
10 changed files with 402 additions and 10 deletions

View 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;
}

View 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

View File

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

View File

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

View File

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

View File

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

View 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;
}

View 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

View File

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

View File

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