1 /* 2 * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 #ifndef _INODE_H_ 6 #define _INODE_H_ 7 8 9 #include "system_dependencies.h" 10 #include "Volume.h" 11 #include "xfs_types.h" 12 13 14 #define INODE_MAGIC 0x494e 15 #define INODE_MINSIZE_LOG 8 16 #define INODE_MAXSIZE_LOG 11 17 #define INODE_CORE_SIZE 96 18 #define INODE_CORE_UNLINKED_SIZE 100 19 // Inode core but with unlinked pointer 20 #define DATA_FORK_OFFSET 0x64 21 // For v4 FS 22 #define INO_MASK(x) ((1ULL << (x)) - 1) 23 // Gets 2^x - 1 24 #define INO_TO_AGNO(id, volume) (xfs_agnumber_t)id >> (volume->AgInodeBits()) 25 // Gets AG number from inode number 26 #define INO_TO_AGINO(id, bits) (uint32) id & INO_MASK(bits); 27 // Gets the AG relative inode number 28 #define INO_TO_AGBLOCK(id, volume) \ 29 (id >> (volume->InodesPerBlkLog())) \ 30 & (INO_MASK(volume->AgBlocksLog())) 31 // Gets the AG relative block number that contains inode 32 #define INO_TO_BLOCKOFFSET(id, volume) (id & INO_MASK(volume->InodesPerBlkLog())) 33 // Gets the offset into the block from the inode number 34 #define DIR_DFORK_PTR(dir_ino_ptr) (void*) \ 35 ((char*) dir_ino_ptr + DATA_FORK_OFFSET) 36 #define DIR_AFORK_PTR(dir_ino_ptr, forkoff) \ 37 (void*)((char*)DIR_DFORK_PTR(dir_ino_ptr) + \ 38 (((uint32)forkoff)<<3)) 39 #define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0 40 #define MASK(n) ((1UL << n) - 1) 41 #define FSBLOCKS_TO_AGNO(n, volume) ((n) >> volume->AgBlocksLog()) 42 #define FSBLOCKS_TO_AGBLOCKNO(n, volume) ((n) & MASK(volume->AgBlocksLog())) 43 #define BLOCKNO_FROM_POSITION(n, volume) \ 44 ((n) >> (volume->BlockLog())) 45 #define BLOCKOFFSET_FROM_POSITION(n, inode) ((n) & (inode->BlockSize() - 1)) 46 47 48 // xfs_bmdr_block 49 struct BlockInDataFork { 50 uint16 Levels() 51 { return 52 B_BENDIAN_TO_HOST_INT16(bb_level); } 53 uint16 NumRecords() 54 { return 55 B_BENDIAN_TO_HOST_INT16(bb_numrecs); } 56 uint16 bb_level; 57 uint16 bb_numrecs; 58 }; 59 60 61 // xfs_da_blkinfo_t 62 struct BlockInfo { 63 uint32 forw; 64 uint32 back; 65 uint16 magic; 66 uint16 pad; 67 }; 68 69 70 struct ExtentMapEntry { 71 xfs_fileoff_t br_startoff; 72 // logical file block offset 73 xfs_fsblock_t br_startblock; 74 // absolute block number 75 xfs_filblks_t br_blockcount; 76 // # of blocks 77 uint8 br_state; 78 // state of the extent 79 }; 80 81 82 uint32 83 hashfunction(const char* name, int length); 84 85 86 struct xfs_timestamp_t { 87 int32 t_sec; 88 int32 t_nsec; 89 }; 90 91 92 enum xfs_dinode_fmt_t { 93 XFS_DINODE_FMT_DEV, 94 // For devices 95 XFS_DINODE_FMT_LOCAL, 96 // For Directories and links 97 XFS_DINODE_FMT_EXTENTS, 98 // For large number of extents 99 XFS_DINODE_FMT_BTREE, 100 // Extents and Directories 101 XFS_DINODE_FMT_UUID, 102 // Not used 103 }; 104 105 /* 106 * The xfs_ino_t is the same for all types of inodes, the data and attribute 107 * fork might be different and that is to be handled accordingly. 108 */ 109 struct xfs_inode_t { 110 void SwapEndian(); 111 int8 Version() const; 112 mode_t Mode() const; 113 void GetModificationTime(struct timespec& 114 timestamp); 115 void GetChangeTime(struct timespec& timestamp); 116 void GetAccessTime(struct timespec& timestamp); 117 int8 Format() const; 118 // The format of the inode 119 xfs_fsize_t Size() const; 120 xfs_rfsblock_t BlockCount() const; 121 uint32 NLink() const; 122 uint16 Flags() const; 123 uint32 UserId() const; 124 uint32 GroupId() const; 125 xfs_extnum_t DataExtentsCount() const; 126 uint8 ForkOffset() const; 127 uint16 di_magic; 128 uint16 di_mode; 129 // uses standard S_Ixxx 130 int8 di_version; 131 //This either would be 1 or 2 132 int8 di_format; 133 uint16 di_onlink; 134 uint32 di_uid; 135 uint32 di_gid; 136 uint32 di_nlink; 137 uint16 di_projid; 138 uint8 di_pad[8]; 139 uint16 di_flushiter; 140 xfs_timestamp_t di_atime; 141 xfs_timestamp_t di_mtime; 142 xfs_timestamp_t di_ctime; 143 xfs_fsize_t di_size; 144 // size in bytes or length if link 145 xfs_rfsblock_t di_nblocks; 146 // blocks used including metadata 147 // extended attributes not included 148 xfs_extlen_t di_extsize; 149 // extent size 150 xfs_extnum_t di_nextents; 151 // number of data extents 152 xfs_aextnum_t di_anextents; 153 // number of EA extents 154 uint8 di_forkoff; 155 // decides where di_a starts 156 int8 di_aformat; 157 // similar to di_format 158 uint32 di_dmevmask; 159 uint16 di_dmstate; 160 uint16 di_flags; 161 uint32 di_gen; 162 uint32 di_next_unlinked; 163 }; 164 165 166 class Inode { 167 public: 168 Inode(Volume* volume, xfs_ino_t id); 169 ~Inode(); 170 status_t Init(); 171 172 xfs_ino_t ID() const { return fId; } 173 174 bool IsDirectory() const 175 { return S_ISDIR(Mode()); } 176 177 bool IsFile() const 178 { return S_ISREG(Mode()); } 179 180 bool IsSymLink() const 181 { return S_ISLNK(Mode()); } 182 183 mode_t Mode() const { return fNode->Mode(); } 184 185 Volume* GetVolume() { return fVolume;} 186 187 int8 Format() const { return fNode->Format(); } 188 189 bool IsLocal() const 190 { return 191 Format() == XFS_DINODE_FMT_LOCAL; } 192 193 uint32 NLink() const { return fNode->NLink(); } 194 195 int8 Version() const { return fNode->Version(); } 196 197 xfs_rfsblock_t BlockCount() const 198 { return fNode->BlockCount(); } 199 200 char* Buffer() { return fBuffer; } 201 202 int16 Flags() const { return fNode->Flags(); } 203 204 xfs_fsize_t Size() const { return fNode->Size(); } 205 206 uint32 DirBlockSize() const 207 { return fVolume->DirBlockSize(); } 208 209 uint32 BlockSize() const 210 { return fVolume->BlockSize(); } 211 212 void GetChangeTime(struct timespec& timestamp) const 213 { fNode->GetChangeTime(timestamp); } 214 215 void GetModificationTime(struct timespec& timestamp) 216 const 217 { fNode->GetModificationTime(timestamp); } 218 219 void GetAccessTime(struct timespec& timestamp) const 220 { fNode->GetAccessTime(timestamp); } 221 222 status_t CheckPermissions(int accessMode) const; 223 uint32 UserId() const { return fNode->UserId(); } 224 uint32 GroupId() const { return fNode->GroupId(); } 225 bool HasFileTypeField() const; 226 xfs_extnum_t DataExtentsCount() const 227 { return fNode->DataExtentsCount(); } 228 uint64 FileSystemBlockToAddr(uint64 block); 229 uint8 ForkOffset() const 230 { return fNode->ForkOffset(); } 231 status_t ReadExtents(); 232 status_t ReadAt(off_t pos, uint8* buffer, size_t* length); 233 status_t GetNodefromTree(uint16& levelsInTree, 234 Volume* volume, size_t& len, 235 size_t DirBlockSize, char* block); 236 int SearchMapInAllExtent(int blockNo); 237 void UnWrapExtentFromWrappedEntry( 238 uint64 wrappedExtent[2], 239 ExtentMapEntry* entry); 240 status_t ReadExtentsFromExtentBasedInode(); 241 status_t ReadExtentsFromTreeInode(); 242 size_t MaxRecordsPossibleInTreeRoot(); 243 size_t MaxRecordsPossibleNode(); 244 TreePointer* GetPtrFromRoot(int pos); 245 TreePointer* GetPtrFromNode(int pos, void* buffer); 246 size_t GetPtrOffsetIntoRoot(int pos); 247 size_t GetPtrOffsetIntoNode(int pos); 248 private: 249 status_t GetFromDisk(); 250 xfs_inode_t* fNode; 251 xfs_ino_t fId; 252 Volume* fVolume; 253 char* fBuffer; 254 // Contains the disk inode in BE format 255 ExtentMapEntry* fExtents; 256 }; 257 258 #endif 259