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