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::NoOfBlocks() 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 Inode::Inode(Volume* volume, xfs_ino_t id) 128 : 129 fVolume(volume), 130 fId(id) 131 { 132 133 } 134 135 136 status_t 137 Inode::Init() 138 { 139 fNode = new(std::nothrow) xfs_inode_t; 140 if (fNode == NULL) 141 return B_NO_MEMORY; 142 143 uint16 inodeSize = fVolume->InodeSize(); 144 fBuffer = new(std::nothrow) char[inodeSize]; 145 if (fBuffer == NULL) 146 return B_NO_MEMORY; 147 148 status_t status = GetFromDisk(); 149 if (status == B_OK) { 150 if (fNode->di_magic == INODE_MAGIC) { 151 TRACE("Init(): Inode successfully read.\n"); 152 status = B_OK; 153 } else { 154 TRACE("Init(): Inode wasn't read successfully!\n"); 155 status = B_BAD_VALUE; 156 } 157 } 158 159 return status; 160 } 161 162 163 status_t 164 Inode::GetFromDisk() 165 { 166 xfs_agnumber_t agNo = INO_TO_AGNO(fId, fVolume); 167 // Get the AG number from the inode 168 uint32 agRelativeInodeNo = INO_TO_AGINO(fId, fVolume->AgInodeBits()); 169 // AG relative ino # 170 xfs_agblock_t agBlock = INO_TO_AGBLOCK(agRelativeInodeNo, fVolume); 171 // AG relative block number 172 xfs_off_t offset = INO_TO_BLOCKOFFSET(fId, fVolume); 173 // Offset into the block1 174 uint32 len = fVolume->InodeSize(); 175 // Inode len to read (size of inode) 176 177 TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d)," 178 "Offset: (%d), len: (%d)\n", agNo, 179 agRelativeInodeNo, agBlock, offset, len); 180 181 if (agNo > fVolume->AgCount()) { 182 ERROR("Inode::GetFromDisk : AG Number more than number of AGs"); 183 return B_ENTRY_NOT_FOUND; 184 } 185 186 xfs_agblock_t numberOfBlocksInAg = fVolume->AgBlocks(); 187 188 xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(), 189 ((uint64)(agNo * numberOfBlocksInAg) + agBlock)); 190 191 xfs_daddr_t readPos = blockToRead * (BASICBLOCKSIZE) + offset * len; 192 193 if (read_pos(fVolume->Device(), readPos, fBuffer, len) != len) { 194 ERROR("Inode::Inode(): IO Error"); 195 return B_IO_ERROR; 196 } 197 198 memcpy(fNode, fBuffer, INODE_CORE_UNLINKED_SIZE); 199 fNode->SwapEndian(); 200 201 return B_OK; 202 } 203 204 205 Inode::~Inode() 206 { 207 delete fBuffer; 208 delete fNode; 209 } 210 211 212 uint32 213 hashfunction(const char* name, int length) 214 { 215 uint32 hashVal = 0; 216 217 int lengthCovered = 0; 218 int index = 0; 219 if (length >= 4) { 220 for (; index <= length; index+=4) 221 { 222 lengthCovered = index; 223 hashVal = (name[index] << 21) ^ (name[index+1] << 14) 224 ^ (name[index+2] << 7) ^ (name[index+3] << 0) 225 ^ ((hashVal << 28) | (hashVal >> (4))); 226 } 227 } 228 229 int leftToCover = length - lengthCovered; 230 if (leftToCover == 3) { 231 hashVal = (name[index] << 14) ^ (name[index+1] << 7) 232 ^ (name[index+2] << 0) ^ ((hashVal << 21) | (hashVal >> (11))); 233 } 234 if (leftToCover == 2) { 235 hashVal = (name[index] << 7) ^ (name[index+1] << 0) 236 ^ ((hashVal << 14) | (hashVal >> (32 - 14))); 237 } 238 if (leftToCover == 1) { 239 hashVal = (name[index] << 0) 240 ^ ((hashVal << 7) | (hashVal >> (32 - 7))); 241 } 242 243 return hashVal; 244 } 245