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