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 29enum DirectoryType { 30 XFS_BLOCK, 31 XFS_LEAF, 32 XFS_NODE, 33 XFS_BTREE, 34}; 35 36 37// xfs_dir2_data_free_t 38struct FreeRegion { 39 uint16 offset; 40 uint16 length; 41}; 42 43 44// This class will act as interface for V4 and V5 data header 45class ExtentDataHeader 46{ 47public: 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 64class ExtentDataHeaderV4 : public ExtentDataHeader 65{ 66public : 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 81private: 82 void _SwapEndian(); 83 84private: 85 OnDiskData fData; 86}; 87 88 89// xfs_dir3_data_hdr_t 90class ExtentDataHeaderV5 : public ExtentDataHeader 91{ 92public: 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 113private: 114 void _SwapEndian(); 115 116private: 117 OnDiskData fData; 118}; 119 120 121// xfs_dir2_data_entry_t 122struct 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 133struct 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 143struct ExtentLeafEntry { 144 uint32 hashval; 145 uint32 address; 146 // offset into block after >> 3 147}; 148 149 150// xfs_dir2_block_tail_t 151struct ExtentBlockTail { 152 uint32 count; 153 // # of entries in leaf 154 uint32 stale; 155 // # of free leaf entries 156}; 157 158 159class Extent : public DirectoryIterator { 160public: 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); 176private: 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