1/*
2 * Copyright 2022, Raghav Sharma, raghavself28@gmail.com
3 * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6#ifndef _LEAFDIRECTORY_H_
7#define _LEAFDIRECTORY_H_
8
9
10#include "Directory.h"
11#include "Extent.h"
12#include "Inode.h"
13#include "system_dependencies.h"
14
15
16#define V4_DATA_HEADER_MAGIC 0x58443244
17#define V5_DATA_HEADER_MAGIC 0x58444433
18
19#define V4_LEAF_HEADER_MAGIC 0xd2f1
20#define V5_LEAF_HEADER_MAGIC 0x3df1
21
22
23enum ContentType { DATA, LEAF };
24
25
26// This class will act as interface for V4 and V5 leaf header
27class ExtentLeafHeader {
28public:
29
30			virtual						~ExtentLeafHeader()		=	0;
31			virtual	uint16				Magic()					=	0;
32			virtual	uint64				Blockno()				=	0;
33			virtual	uint64				Lsn()					=	0;
34			virtual	uint64				Owner()					=	0;
35			virtual	const uuid_t&		Uuid()					=	0;
36			virtual	uint16				Count()					=	0;
37			virtual	uint32				Forw()					=	0;
38			static	uint32				ExpectedMagic(int8 WhichDirectory,
39										Inode* inode);
40			static	uint32				CRCOffset();
41			static	ExtentLeafHeader*	Create(Inode* inode, const char* buffer);
42			static	uint32				Size(Inode* inode);
43
44};
45
46
47//xfs_dir_leaf_hdr_t
48class ExtentLeafHeaderV4 : public ExtentLeafHeader {
49public:
50			struct OnDiskData {
51			public:
52				BlockInfo			info;
53				uint16				count;
54				uint16				stale;
55			};
56
57								ExtentLeafHeaderV4(const char* buffer);
58								~ExtentLeafHeaderV4();
59			void				SwapEndian();
60			uint16				Magic();
61			uint64				Blockno();
62			uint64				Lsn();
63			uint64				Owner();
64			const uuid_t&		Uuid();
65			uint16				Count();
66			uint32				Forw();
67
68private:
69			OnDiskData			fData;
70};
71
72
73// xfs_dir3_leaf_hdr_t
74class ExtentLeafHeaderV5 : public ExtentLeafHeader {
75public:
76			struct OnDiskData {
77				BlockInfoV5			info;
78				uint16				count;
79				uint16				stale;
80				uint32				pad;
81			};
82
83								ExtentLeafHeaderV5(const char* buffer);
84								~ExtentLeafHeaderV5();
85			void				SwapEndian();
86			uint16				Magic();
87			uint64				Blockno();
88			uint64				Lsn();
89			uint64				Owner();
90			const uuid_t&		Uuid();
91			uint16				Count();
92			uint32				Forw();
93
94
95private:
96			OnDiskData			fData;
97};
98
99
100// xfs_dir2_leaf_tail_t
101struct ExtentLeafTail {
102			uint32				bestcount;
103				// # of best free entries
104};
105
106
107class LeafDirectory : public DirectoryIterator {
108public:
109								LeafDirectory(Inode* inode);
110								~LeafDirectory();
111			status_t			Init();
112			bool				IsLeafType();
113			void				FillMapEntry(int num, ExtentMapEntry* map);
114			status_t			FillBuffer(int type, char* buffer,
115									int howManyBlocksFurthur);
116			void				SearchAndFillDataMap(uint64 blockNo);
117			ExtentLeafEntry*	FirstLeaf();
118			xfs_ino_t			GetIno();
119			uint32				GetOffsetFromAddress(uint32 address);
120			int					EntrySize(int len) const;
121			status_t			GetNext(char* name, size_t* length,
122									xfs_ino_t* ino);
123			status_t			Lookup(const char* name, size_t length,
124									xfs_ino_t* id);
125private:
126			Inode*				fInode;
127			ExtentMapEntry*		fDataMap;
128			ExtentMapEntry*		fLeafMap;
129			uint32				fOffset;
130			char*				fDataBuffer;
131				// This isn't inode data. It holds the directory block.
132			char*				fLeafBuffer;
133			uint32				fCurBlockNumber;
134};
135
136#endif
137