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 public: 56 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 uuid_t* Uuid() = 0; 63 static uint32 ExpectedMagic(int8 WhichDirectory, 64 Inode* inode); 65 static uint32 CRCOffset(); 66 static ExtentDataHeader* Create(Inode* inode, const char* buffer); 67 static uint32 Size(Inode* inode); 68 }; 69 70 71 //xfs_dir_data_hdr_t 72 class ExtentDataHeaderV4 : public ExtentDataHeader { 73 public : 74 75 ExtentDataHeaderV4(const char* buffer); 76 ~ExtentDataHeaderV4(); 77 void SwapEndian(); 78 uint32 Magic(); 79 uint64 Blockno(); 80 uint64 Lsn(); 81 uint64 Owner(); 82 uuid_t* Uuid(); 83 84 uint32 magic; 85 private: 86 FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT]; 87 }; 88 89 90 // xfs_dir3_data_hdr_t 91 class ExtentDataHeaderV5 : public ExtentDataHeader { 92 public: 93 ExtentDataHeaderV5(const char* buffer); 94 ~ExtentDataHeaderV5(); 95 void SwapEndian(); 96 uint32 Magic(); 97 uint64 Blockno(); 98 uint64 Lsn(); 99 uint64 Owner(); 100 uuid_t* Uuid(); 101 public: 102 uint32 magic; 103 uint32 crc; 104 private: 105 uint64 blkno; 106 uint64 lsn; 107 uuid_t uuid; 108 uint64 owner; 109 FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT]; 110 uint32 pad; 111 }; 112 113 #define XFS_EXTENT_CRC_OFF offsetof(ExtentDataHeaderV5, crc) 114 #define XFS_EXTENT_V5_VPTR_OFF offsetof(ExtentDataHeaderV5, magic) 115 #define XFS_EXTENT_V4_VPTR_OFF offsetof(ExtentDataHeaderV4, magic) 116 117 118 // xfs_dir2_data_entry_t 119 struct ExtentDataEntry { 120 xfs_ino_t inumber; 121 uint8 namelen; 122 uint8 name[]; 123 124 // Followed by a file type (8bit) if applicable and a 16bit tag 125 // tag is the offset from start of the block 126 }; 127 128 129 // xfs_dir2_data_unused_t 130 struct ExtentUnusedEntry { 131 uint16 freetag; 132 // takes the value 0xffff 133 uint16 length; 134 // freetag+length overrides the inumber of an entry 135 uint16 tag; 136 }; 137 138 139 // xfs_dir2_leaf_entry_t 140 struct ExtentLeafEntry { 141 uint32 hashval; 142 uint32 address; 143 // offset into block after >> 3 144 }; 145 146 147 // xfs_dir2_block_tail_t 148 struct ExtentBlockTail { 149 uint32 count; 150 // # of entries in leaf 151 uint32 stale; 152 // # of free leaf entries 153 }; 154 155 156 class Extent : public DirectoryIterator { 157 public: 158 Extent(Inode* inode); 159 ~Extent(); 160 status_t Init(); 161 bool IsBlockType(); 162 void FillMapEntry(void* pointerToMap); 163 status_t FillBlockBuffer(); 164 ExtentBlockTail* BlockTail(); 165 ExtentLeafEntry* BlockFirstLeaf(ExtentBlockTail* tail); 166 xfs_ino_t GetIno(); 167 uint32 GetOffsetFromAddress(uint32 address); 168 int EntrySize(int len) const; 169 status_t GetNext(char* name, size_t* length, 170 xfs_ino_t* ino); 171 status_t Lookup(const char* name, size_t length, 172 xfs_ino_t* id); 173 private: 174 Inode* fInode; 175 ExtentMapEntry* fMap; 176 uint32 fOffset; 177 char* fBlockBuffer; 178 // This isn't inode data. It holds the directory block. 179 }; 180 181 #endif 182