root/src/add-ons/kernel/file_systems/xfs/LeafAttribute.h
/*
 * Copyright 2022, Raghav Sharma, raghavself28@gmail.com
 * Distributed under the terms of the MIT License.
 */
#ifndef LEAF_ATTRIBUTE_H
#define LEAF_ATTRIBUTE_H


#include "Attribute.h"
#include "Inode.h"


#define XFS_ATTR_LEAF_MAPSIZE   3
#define XFS_ATTR_LEAF_MAGIC             0xfbee
#define XFS_ATTR3_LEAF_MAGIC    0x3bee
#define XFS_ATTR_LOCAL_BIT              0
#define XFS_ATTR_LOCAL                  (1 << XFS_ATTR_LOCAL_BIT)
#define XFS_ATTR3_RMT_MAGIC             0x5841524d


// Enum values to check which directory we are reading
enum AttrType {
        ATTR_LEAF,
        ATTR_NODE,
        ATTR_BTREE,
};


// xfs_attr_leaf_map
struct AttrLeafMap {
        uint16  base;
        uint16  size;
};


// This class will act as interface for V4 and V5 Attr leaf header
class AttrLeafHeader {
public:

                        virtual                                         ~AttrLeafHeader()                       =       0;
                        virtual uint16                          Magic()                                         =       0;
                        virtual uint64                          Blockno()                                       =       0;
                        virtual uint64                          Owner()                                         =       0;
                        virtual const uuid_t&           Uuid()                                          =       0;
                        virtual uint16                          Count()                                         =       0;
                        static  uint32                          ExpectedMagic(int8 WhichDirectory,
                                                                                Inode* inode);
                        static  uint32                          CRCOffset();
                        static  AttrLeafHeader*         Create(Inode* inode, const char* buffer);
                        static  uint32                          Size(Inode* inode);
};


//xfs_attr_leaf_hdr
class AttrLeafHeaderV4 : public AttrLeafHeader {
public:
                        struct OnDiskData {
                        public:
                                uint16                          count;
                                uint16                          usedbytes;
                                uint16                          firstused;
                                uint8                           holes;
                                uint8                           pad1;
                                AttrLeafMap                     freemap[3];
                                BlockInfo                       info;
                        };

                                                                AttrLeafHeaderV4(const char* buffer);
                                                                ~AttrLeafHeaderV4();
                        void                            SwapEndian();
                        uint16                          Magic();
                        uint64                          Blockno();
                        uint64                          Owner();
                        const uuid_t&           Uuid();
                        uint16                          Count();

private:
                        OnDiskData                      fData;
};


//xfs_attr3_leaf_hdr
class AttrLeafHeaderV5 : public AttrLeafHeader {
public:
                        struct OnDiskData {
                        public:
                                uint16                          count;
                                uint16                          usedbytes;
                                uint16                          firstused;
                                uint8                           holes;
                                uint8                           pad1;
                                AttrLeafMap                     freemap[3];
                                uint32                          pad2;
                                BlockInfoV5                     info;
                        };

                                                                AttrLeafHeaderV5(const char* buffer);
                                                                ~AttrLeafHeaderV5();
                        void                            SwapEndian();
                        uint16                          Magic();
                        uint64                          Blockno();
                        uint64                          Owner();
                        const uuid_t&           Uuid();
                        uint16                          Count();

private:
                        OnDiskData                      fData;
};


// xfs_attr_leaf_entry
struct AttrLeafEntry {
        uint32          hashval;
        uint16          nameidx;
        uint8           flags;
        uint8           pad2;
};


// xfs_attr_leaf_name_local
struct AttrLeafNameLocal {
        uint16          valuelen;
        uint8           namelen;
        uint8           nameval[];
};


// xfs_attr_leaf_name_remote
struct AttrLeafNameRemote {
        uint32          valueblk;
        uint32          valuelen;
        uint8           namelen;
        uint8           name[];
};


struct AttrRemoteHeader {
        uint32          rm_magic;
        uint32          rm_offset;
        uint32          rm_bytes;
        uint32          rm_crc;
        uuid_t          rm_uuid;
        uint64          rm_blkno;
        uint64          rm_lsn;
};

#define XFS_ATTR3_RMT_CRC_OFF   offsetof(struct AttrRemoteHeader, rm_crc)


class LeafAttribute : public Attribute {
public:
                                                                LeafAttribute(Inode* inode);
                                                                ~LeafAttribute();

                        status_t                        Init();

                        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:
                        status_t                        _FillMapEntry();

                        status_t                        _FillLeafBuffer();

                        Inode*                          fInode;
                        const char*                     fName;
                        ExtentMapEntry*         fMap;
                        char*                           fLeafBuffer;
                        uint16                          fLastEntryOffset;
                        AttrLeafNameLocal*      fLocalEntry;
                        AttrLeafNameRemote*     fRemoteEntry;
};

#endif