1/*
2 * Copyright 2022, Raghav Sharma, raghavself28@gmail.com
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef LEAF_ATTRIBUTE_H
6#define LEAF_ATTRIBUTE_H
7
8
9#include "Attribute.h"
10#include "Inode.h"
11
12
13#define	XFS_ATTR_LEAF_MAPSIZE	3
14#define	XFS_ATTR_LEAF_MAGIC		0xfbee
15#define	XFS_ATTR3_LEAF_MAGIC	0x3bee
16#define	XFS_ATTR_LOCAL_BIT		0
17#define XFS_ATTR_LOCAL			(1 << XFS_ATTR_LOCAL_BIT)
18#define	XFS_ATTR3_RMT_MAGIC		0x5841524d
19
20
21// Enum values to check which directory we are reading
22enum AttrType {
23	ATTR_LEAF,
24	ATTR_NODE,
25	ATTR_BTREE,
26};
27
28
29// xfs_attr_leaf_map
30struct AttrLeafMap {
31	uint16	base;
32	uint16	size;
33};
34
35
36// This class will act as interface for V4 and V5 Attr leaf header
37class AttrLeafHeader {
38public:
39
40			virtual						~AttrLeafHeader()			=	0;
41			virtual uint16				Magic()						=	0;
42			virtual uint64				Blockno()					=	0;
43			virtual uint64				Owner()						=	0;
44			virtual const uuid_t&		Uuid()						=	0;
45			virtual	uint16				Count()						=	0;
46			static	uint32				ExpectedMagic(int8 WhichDirectory,
47										Inode* inode);
48			static	uint32				CRCOffset();
49			static	AttrLeafHeader*		Create(Inode* inode, const char* buffer);
50			static	uint32				Size(Inode* inode);
51};
52
53
54//xfs_attr_leaf_hdr
55class AttrLeafHeaderV4 : public AttrLeafHeader {
56public:
57			struct OnDiskData {
58			public:
59				uint16				count;
60				uint16				usedbytes;
61				uint16				firstused;
62				uint8				holes;
63				uint8				pad1;
64				AttrLeafMap			freemap[3];
65				BlockInfo			info;
66			};
67
68								AttrLeafHeaderV4(const char* buffer);
69								~AttrLeafHeaderV4();
70			void				SwapEndian();
71			uint16				Magic();
72			uint64				Blockno();
73			uint64				Owner();
74			const uuid_t&		Uuid();
75			uint16				Count();
76
77private:
78			OnDiskData			fData;
79};
80
81
82//xfs_attr3_leaf_hdr
83class AttrLeafHeaderV5 : public AttrLeafHeader {
84public:
85			struct OnDiskData {
86			public:
87				uint16				count;
88				uint16				usedbytes;
89				uint16				firstused;
90				uint8				holes;
91				uint8				pad1;
92				AttrLeafMap			freemap[3];
93				uint32				pad2;
94				BlockInfoV5			info;
95			};
96
97								AttrLeafHeaderV5(const char* buffer);
98								~AttrLeafHeaderV5();
99			void				SwapEndian();
100			uint16				Magic();
101			uint64				Blockno();
102			uint64				Owner();
103			const uuid_t&		Uuid();
104			uint16				Count();
105
106private:
107			OnDiskData			fData;
108};
109
110
111// xfs_attr_leaf_entry
112struct AttrLeafEntry {
113	uint32		hashval;
114	uint16		nameidx;
115	uint8		flags;
116	uint8		pad2;
117};
118
119
120// xfs_attr_leaf_name_local
121struct AttrLeafNameLocal {
122	uint16		valuelen;
123	uint8		namelen;
124	uint8		nameval[];
125};
126
127
128// xfs_attr_leaf_name_remote
129struct AttrLeafNameRemote {
130	uint32		valueblk;
131	uint32		valuelen;
132	uint8		namelen;
133	uint8		name[];
134};
135
136
137struct AttrRemoteHeader {
138	uint32		rm_magic;
139	uint32		rm_offset;
140	uint32		rm_bytes;
141	uint32		rm_crc;
142	uuid_t		rm_uuid;
143	uint64		rm_blkno;
144	uint64		rm_lsn;
145};
146
147#define XFS_ATTR3_RMT_CRC_OFF	offsetof(struct AttrRemoteHeader, rm_crc)
148
149
150class LeafAttribute : public Attribute {
151public:
152								LeafAttribute(Inode* inode);
153								~LeafAttribute();
154
155			status_t			Init();
156
157			status_t			Stat(attr_cookie* cookie, struct stat& stat);
158
159			status_t			Read(attr_cookie* cookie, off_t pos,
160									uint8* buffer, size_t* length);
161
162			status_t			Open(const char* name, int openMode, attr_cookie** _cookie);
163
164			status_t			GetNext(char* name, size_t* nameLength);
165
166			status_t			Lookup(const char* name, size_t* nameLength);
167private:
168			status_t			_FillMapEntry();
169
170			status_t			_FillLeafBuffer();
171
172			Inode*				fInode;
173			const char*			fName;
174			ExtentMapEntry*		fMap;
175			char*				fLeafBuffer;
176			uint16				fLastEntryOffset;
177			AttrLeafNameLocal*	fLocalEntry;
178			AttrLeafNameRemote*	fRemoteEntry;
179};
180
181#endif
182