⛏️ index : haiku.git

/*
 * 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