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 _EXTENT_H_ 7 #define _EXTENT_H_ 8 9 10 #include "Inode.h" 11 #include "system_dependencies.h" 12 13 14 #define DIR2_BLOCK_HEADER_MAGIC 0x58443242 15 // for v4 system 16 #define DIR3_BLOCK_HEADER_MAGIC 0x58444233 17 // for v5 system 18 #define DIR2_FREE_TAG 0xffff 19 #define XFS_DIR2_DATA_FD_COUNT 3 20 #define EXTENT_REC_SIZE 128 21 #define EXTENT_SIZE 16 22 #define BLOCKNO_FROM_ADDRESS(n, volume) \ 23 ((n) >> (volume->BlockLog() + volume->DirBlockLog())) 24 #define BLOCKOFFSET_FROM_ADDRESS(n, inode) ((n) & (inode->DirBlockSize() - 1)) 25 #define LEAF_STARTOFFSET(n) 1UL << (35 - (n)) 26 27 28 // xfs_exntst_t 29 enum ExtentState { 30 XFS_EXT_NORM, 31 XFS_EXT_UNWRITTEN, 32 XFS_EXT_INVALID 33 }; 34 35 36 // Enum values to check which directory we are reading 37 enum DirectoryType { 38 XFS_BLOCK, 39 XFS_LEAF, 40 XFS_NODE, 41 XFS_BTREE, 42 }; 43 44 45 // xfs_dir2_data_free_t 46 struct FreeRegion { 47 uint16 offset; 48 uint16 length; 49 }; 50 51 52 // This class will act as interface for V4 and V5 data header 53 class ExtentDataHeader { 54 public: 55 56 virtual ~ExtentDataHeader() = 0; 57 virtual uint32 Magic() = 0; 58 virtual uint64 Blockno() = 0; 59 virtual uint64 Lsn() = 0; 60 virtual uint64 Owner() = 0; 61 virtual uuid_t* Uuid() = 0; 62 static uint32 ExpectedMagic(int8 WhichDirectory, 63 Inode* inode); 64 static uint32 CRCOffset(); 65 }; 66 67 68 //xfs_dir_data_hdr_t 69 class ExtentDataHeaderV4 : public ExtentDataHeader { 70 public : 71 72 ExtentDataHeaderV4(const char* buffer); 73 ~ExtentDataHeaderV4(); 74 void SwapEndian(); 75 uint32 Magic(); 76 uint64 Blockno(); 77 uint64 Lsn(); 78 uint64 Owner(); 79 uuid_t* Uuid(); 80 81 uint32 magic; 82 private: 83 FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT]; 84 }; 85 86 87 // xfs_dir3_data_hdr_t 88 class ExtentDataHeaderV5 : public ExtentDataHeader { 89 public: 90 ExtentDataHeaderV5(const char* buffer); 91 ~ExtentDataHeaderV5(); 92 void SwapEndian(); 93 uint32 Magic(); 94 uint64 Blockno(); 95 uint64 Lsn(); 96 uint64 Owner(); 97 uuid_t* Uuid(); 98 public: 99 uint32 magic; 100 uint32 crc; 101 private: 102 uint64 blkno; 103 uint64 lsn; 104 uuid_t uuid; 105 uint64 owner; 106 FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT]; 107 uint32 pad; 108 }; 109 110 #define XFS_EXTENT_CRC_OFF offsetof(ExtentDataHeaderV5, crc) 111 #define XFS_EXTENT_V5_VPTR_OFF offsetof(ExtentDataHeaderV5, magic) 112 #define XFS_EXTENT_V4_VPTR_OFF offsetof(ExtentDataHeaderV4, magic) 113 114 115 // xfs_dir2_data_entry_t 116 struct ExtentDataEntry { 117 xfs_ino_t inumber; 118 uint8 namelen; 119 uint8 name[]; 120 121 // Followed by a file type (8bit) if applicable and a 16bit tag 122 // tag is the offset from start of the block 123 }; 124 125 126 // xfs_dir2_data_unused_t 127 struct ExtentUnusedEntry { 128 uint16 freetag; 129 // takes the value 0xffff 130 uint16 length; 131 // freetag+length overrides the inumber of an entry 132 uint16 tag; 133 }; 134 135 136 // xfs_dir2_leaf_entry_t 137 struct ExtentLeafEntry { 138 uint32 hashval; 139 uint32 address; 140 // offset into block after >> 3 141 }; 142 143 144 // xfs_dir2_block_tail_t 145 struct ExtentBlockTail { 146 uint32 count; 147 // # of entries in leaf 148 uint32 stale; 149 // # of free leaf entries 150 }; 151 152 153 class Extent 154 { 155 public: 156 Extent(Inode* inode); 157 ~Extent(); 158 status_t Init(); 159 bool IsBlockType(); 160 void FillMapEntry(void* pointerToMap); 161 status_t FillBlockBuffer(); 162 ExtentBlockTail* BlockTail(); 163 ExtentLeafEntry* BlockFirstLeaf(ExtentBlockTail* tail); 164 xfs_ino_t GetIno(); 165 uint32 GetOffsetFromAddress(uint32 address); 166 int EntrySize(int len) const; 167 status_t GetNext(char* name, size_t* length, 168 xfs_ino_t* ino); 169 status_t Lookup(const char* name, size_t length, 170 xfs_ino_t* id); 171 private: 172 Inode* fInode; 173 ExtentMapEntry* fMap; 174 uint32 fOffset; 175 char* fBlockBuffer; 176 // This isn't inode data. It holds the directory block. 177 }; 178 179 180 ExtentDataHeader* 181 CreateDataHeader(Inode* inode, const char* buffer); 182 183 184 uint32 185 SizeOfDataHeader(Inode* inode); 186 187 #endif 188