1 /* 2 * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "Inode.h" 8 9 10 void 11 xfs_inode_t::SwapEndian() 12 { 13 di_magic = B_BENDIAN_TO_HOST_INT16(di_magic); 14 di_mode = B_BENDIAN_TO_HOST_INT16(di_mode); 15 di_onlink = B_BENDIAN_TO_HOST_INT16(di_onlink); 16 di_uid = B_BENDIAN_TO_HOST_INT32(di_uid); 17 di_gid = B_BENDIAN_TO_HOST_INT32(di_gid); 18 di_nlink = B_BENDIAN_TO_HOST_INT32(di_nlink); 19 di_projid = B_BENDIAN_TO_HOST_INT16(di_projid); 20 di_flushiter = B_BENDIAN_TO_HOST_INT16(di_flushiter); 21 di_atime.t_sec = B_BENDIAN_TO_HOST_INT32(di_atime.t_sec); 22 di_atime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_atime.t_nsec); 23 di_mtime.t_sec = B_BENDIAN_TO_HOST_INT32(di_mtime.t_sec); 24 di_mtime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_mtime.t_nsec); 25 di_ctime.t_sec = B_BENDIAN_TO_HOST_INT32(di_ctime.t_sec); 26 di_ctime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_ctime.t_nsec); 27 di_size = B_BENDIAN_TO_HOST_INT64(di_size); 28 di_nblocks = B_BENDIAN_TO_HOST_INT64(di_nblocks); 29 di_extsize = B_BENDIAN_TO_HOST_INT32(di_extsize); 30 di_nextents = B_BENDIAN_TO_HOST_INT32(di_nextents); 31 di_anextents = B_BENDIAN_TO_HOST_INT16(di_anextents); 32 di_dmevmask = B_BENDIAN_TO_HOST_INT32(di_dmevmask); 33 di_dmstate = B_BENDIAN_TO_HOST_INT16(di_dmstate); 34 di_flags = B_BENDIAN_TO_HOST_INT16(di_flags); 35 di_gen = B_BENDIAN_TO_HOST_INT32(di_gen); 36 di_next_unlinked = B_BENDIAN_TO_HOST_INT32(di_next_unlinked); 37 } 38 39 40 xfs_rfsblock_t 41 xfs_inode_t::BlockCount() const 42 { 43 return di_nblocks; 44 } 45 46 47 xfs_fsize_t 48 xfs_inode_t::Size() const 49 { 50 return di_size; 51 } 52 53 54 mode_t 55 xfs_inode_t::Mode() const 56 { 57 return di_mode; 58 } 59 60 61 uint32 62 xfs_inode_t::UserId() const 63 { 64 return di_uid; 65 } 66 67 68 uint32 69 xfs_inode_t::GroupId() const 70 { 71 return di_gid; 72 } 73 74 75 void 76 xfs_inode_t::GetModificationTime(struct timespec& stamp) 77 { 78 stamp.tv_sec = di_mtime.t_sec; 79 stamp.tv_nsec = di_mtime.t_nsec; 80 } 81 82 83 void 84 xfs_inode_t::GetAccessTime(struct timespec& stamp) 85 { 86 stamp.tv_sec = di_atime.t_sec; 87 stamp.tv_nsec = di_atime.t_nsec; 88 } 89 90 91 void 92 xfs_inode_t::GetChangeTime(struct timespec& stamp) 93 { 94 stamp.tv_sec = di_ctime.t_sec; 95 stamp.tv_nsec = di_ctime.t_nsec; 96 } 97 98 99 uint32 100 xfs_inode_t::NLink() const 101 { 102 return di_nlink; 103 } 104 105 106 int8 107 xfs_inode_t::Version() const 108 { 109 return di_version; 110 } 111 112 113 uint16 114 xfs_inode_t::Flags() const 115 { 116 return di_flags; 117 } 118 119 120 int8 121 xfs_inode_t::Format() const 122 { 123 return di_format; 124 } 125 126 127 xfs_extnum_t 128 xfs_inode_t::DataExtentsCount() const 129 { 130 return di_nextents; 131 } 132 133 134 Inode::Inode(Volume* volume, xfs_ino_t id) 135 : 136 fVolume(volume), 137 fId(id) 138 { 139 140 } 141 142 143 status_t 144 Inode::Init() 145 { 146 fNode = new(std::nothrow) xfs_inode_t; 147 if (fNode == NULL) 148 return B_NO_MEMORY; 149 150 uint16 inodeSize = fVolume->InodeSize(); 151 fBuffer = new(std::nothrow) char[inodeSize]; 152 if (fBuffer == NULL) 153 return B_NO_MEMORY; 154 155 status_t status = GetFromDisk(); 156 if (status == B_OK) { 157 if (fNode->di_magic == INODE_MAGIC) { 158 TRACE("Init(): Inode successfully read.\n"); 159 status = B_OK; 160 } else { 161 TRACE("Init(): Inode wasn't read successfully!\n"); 162 status = B_BAD_VALUE; 163 } 164 } 165 166 return status; 167 } 168 169 170 bool 171 Inode::HasFileTypeField() const 172 { 173 return fVolume->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE; 174 } 175 176 177 status_t 178 Inode::GetFromDisk() 179 { 180 xfs_agnumber_t agNo = INO_TO_AGNO(fId, fVolume); 181 // Get the AG number from the inode 182 uint32 agRelativeInodeNo = INO_TO_AGINO(fId, fVolume->AgInodeBits()); 183 // AG relative ino # 184 xfs_agblock_t agBlock = INO_TO_AGBLOCK(agRelativeInodeNo, fVolume); 185 // AG relative block number 186 xfs_off_t offset = INO_TO_BLOCKOFFSET(fId, fVolume); 187 // Offset into the block1 188 uint32 len = fVolume->InodeSize(); 189 // Inode len to read (size of inode) 190 191 TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d)," 192 "Offset: (%d), len: (%d)\n", agNo, 193 agRelativeInodeNo, agBlock, offset, len); 194 195 if (agNo > fVolume->AgCount()) { 196 ERROR("Inode::GetFromDisk : AG Number more than number of AGs"); 197 return B_ENTRY_NOT_FOUND; 198 } 199 200 xfs_agblock_t numberOfBlocksInAg = fVolume->AgBlocks(); 201 202 xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(), 203 ((uint64)(agNo * numberOfBlocksInAg) + agBlock)); 204 205 xfs_daddr_t readPos = blockToRead * BASICBLOCKSIZE + offset * len; 206 207 if (read_pos(fVolume->Device(), readPos, fBuffer, len) != len) { 208 ERROR("Inode::Inode(): IO Error"); 209 return B_IO_ERROR; 210 } 211 212 memcpy(fNode, fBuffer, INODE_CORE_UNLINKED_SIZE); 213 fNode->SwapEndian(); 214 215 return B_OK; 216 } 217 218 219 Inode::~Inode() 220 { 221 delete fBuffer; 222 delete fNode; 223 } 224 225 226 /* 227 * Basically take 4 characters at a time as long as you can, and xor with 228 * previous hashVal after rotating 4 bits of hashVal. Likewise, continue 229 * xor and rotating. This is quite a generic hash function. 230 */ 231 uint32 232 hashfunction(const char* name, int length) 233 { 234 uint32 hashVal = 0; 235 int lengthCovered = 0; 236 int index = 0; 237 if (length >= 4) { 238 for (;index < length && (length - index) >= 4; index += 4) 239 { 240 lengthCovered += 4; 241 hashVal = (name[index] << 21) ^ (name[index+1] << 14) 242 ^ (name[index+2] << 7) ^ (name[index+3] << 0) 243 ^ ((hashVal << 28) | (hashVal >> (4))); 244 } 245 } 246 247 int leftToCover = length - lengthCovered; 248 if (leftToCover == 3) { 249 hashVal = (name[index] << 14) ^ (name[index+1] << 7) 250 ^ (name[index+2] << 0) ^ ((hashVal << 21) | (hashVal >> (11))); 251 } 252 if (leftToCover == 2) { 253 hashVal = (name[index] << 7) ^ (name[index+1] << 0) 254 ^ ((hashVal << 14) | (hashVal >> (32 - 14))); 255 } 256 if (leftToCover == 1) { 257 hashVal = (name[index] << 0) 258 ^ ((hashVal << 7) | (hashVal >> (32 - 7))); 259 } 260 261 return hashVal; 262 } 263