1 /* 2 * Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com 3 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de. 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 #include "Inode.h" 8 #include <string.h> 9 10 11 #define TRACE_UFS2 12 #ifdef TRACE_UFS2 13 #define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x) 14 #else 15 #define TRACE(x...) ; 16 #endif 17 #define ERROR(x...) dprintf("\33[34mufs2:\33[0m " x) 18 19 20 Inode::Inode(Volume* volume, ino_t id) 21 : 22 fVolume(volume), 23 fID(id), 24 fCache(NULL), 25 fMap(NULL) 26 { 27 rw_lock_init(&fLock, "ufs2 inode"); 28 29 fInitStatus = B_OK;//UpdateNodeFromDisk(); 30 if (fInitStatus == B_OK) { 31 if (!IsDirectory() && !IsSymLink()) { 32 fCache = file_cache_create(fVolume->ID(), ID(), Size()); 33 fMap = file_map_create(fVolume->ID(), ID(), Size()); 34 } 35 } 36 int fd = fVolume->Device(); 37 ufs2_super_block* superblock = (ufs2_super_block* )&fVolume->SuperBlock(); 38 int64_t fs_block = ino_to_fsba(superblock, id); 39 int64_t offset_in_block = ino_to_fsbo(superblock, id); 40 int64_t offset = fs_block * MINBSIZE + offset_in_block * sizeof(fNode); 41 42 if (read_pos(fd, offset, (void*)&fNode, sizeof(fNode)) != sizeof(fNode)) 43 ERROR("Inode::Inode(): IO Error\n"); 44 45 46 } 47 48 49 Inode::Inode(Volume* volume, ino_t id, const ufs2_inode& item) 50 : 51 fVolume(volume), 52 fID(id), 53 fCache(NULL), 54 fMap(NULL), 55 fInitStatus(B_OK), 56 fNode(item) 57 { 58 if (!IsDirectory() && !IsSymLink()) { 59 fCache = file_cache_create(fVolume->ID(), ID(), Size()); 60 fMap = file_map_create(fVolume->ID(), ID(), Size()); 61 } 62 } 63 64 65 Inode::Inode(Volume* volume) 66 : 67 fVolume(volume), 68 fID(0), 69 fCache(NULL), 70 fMap(NULL), 71 fInitStatus(B_NO_INIT) 72 { 73 rw_lock_init(&fLock, "ufs2 inode"); 74 } 75 76 77 Inode::~Inode() 78 { 79 TRACE("Inode destructor\n"); 80 file_cache_delete(FileCache()); 81 file_map_delete(Map()); 82 TRACE("Inode destructor: Done\n"); 83 } 84 85 86 status_t 87 Inode::InitCheck() 88 { 89 return fInitStatus; 90 } 91 92 93 status_t 94 Inode::ReadAt(off_t file_offset, uint8* buffer, size_t* _length) 95 { 96 int fd = fVolume->Device(); 97 ufs2_super_block super_block = fVolume->SuperBlock(); 98 int32_t blockSize = super_block.fs_bsize; 99 off_t pos; 100 int64_t size = Size(); 101 off_t startBlockNumber = file_offset / blockSize; 102 off_t endBlockNumber = (file_offset + *_length) / blockSize; 103 off_t blockOffset = file_offset % blockSize; 104 ssize_t length = 0; 105 if (startBlockNumber != endBlockNumber) { 106 ssize_t remainingLength = blockSize - blockOffset; 107 for (; startBlockNumber <= endBlockNumber; startBlockNumber++) { 108 //code for reading multiple blocks 109 pos = FindBlock(startBlockNumber, blockOffset); 110 length += read_pos(fd, pos, buffer, remainingLength); 111 blockOffset = 0; 112 remainingLength = *_length - length; 113 if (remainingLength > blockSize) 114 remainingLength = blockSize; 115 } 116 *_length = length; 117 return B_OK; 118 } 119 pos = FindBlock(startBlockNumber, blockOffset); 120 length = read_pos(fd, pos, buffer, *_length); 121 *_length = length; 122 return B_OK; 123 124 } 125 126 127 off_t 128 Inode::FindBlock(off_t blockNumber, off_t blockOffset) 129 { 130 int fd = fVolume->Device(); 131 ufs2_super_block super_block = fVolume->SuperBlock(); 132 int32_t blockSize = super_block.fs_bsize; 133 int32_t fragmentSize = super_block.fs_fsize; 134 off_t indirectOffset; 135 int64_t directBlock; 136 off_t numberOfBlockPointers = blockSize / 8; 137 const off_t numberOfIndirectBlocks = numberOfBlockPointers; 138 const off_t numberOfDoubleIndirectBlocks = numberOfBlockPointers 139 * numberOfBlockPointers; 140 if (blockNumber < 12) { 141 // read from direct block 142 return GetBlockPointer(blockNumber) * fragmentSize + blockOffset; 143 144 } else if (blockNumber < numberOfIndirectBlocks + 12) { 145 //read from indirect block 146 blockNumber = blockNumber - 12; 147 indirectOffset = GetIndirectBlockPointer() * 148 fragmentSize + (8 * blockNumber); 149 read_pos(fd, indirectOffset, 150 (void*)&directBlock, sizeof(directBlock)); 151 152 return directBlock * fragmentSize + blockOffset; 153 154 } else if (blockNumber < numberOfDoubleIndirectBlocks 155 + numberOfIndirectBlocks + 12) { 156 // Data is in double indirect block 157 // Subract the already read blocks 158 blockNumber = blockNumber - numberOfBlockPointers - 12; 159 // Calculate indirect block inside double indirect block 160 off_t indirectBlockNumber = blockNumber / numberOfBlockPointers; 161 indirectOffset = GetDoubleIndirectBlockPtr() * 162 fragmentSize + (8 * indirectBlockNumber); 163 164 int64_t indirectPointer; 165 read_pos(fd, indirectOffset, 166 (void*)&indirectPointer, sizeof(directBlock)); 167 168 indirectOffset = indirectPointer * fragmentSize 169 + (8 * (blockNumber % numberOfBlockPointers)); 170 171 read_pos(fd, indirectOffset, 172 (void*)&directBlock, sizeof(directBlock)); 173 174 return directBlock * fragmentSize + blockOffset; 175 176 } else if (blockNumber < (numberOfIndirectBlocks 177 * numberOfDoubleIndirectBlocks) 178 + (numberOfDoubleIndirectBlocks + numberOfBlockPointers + 12)) { 179 // Reading from triple indirect block 180 blockNumber = blockNumber - numberOfDoubleIndirectBlocks 181 - numberOfBlockPointers - 12; 182 183 // Get double indirect block 184 // Double indirect block no 185 off_t indirectBlockNumber = blockNumber / numberOfDoubleIndirectBlocks; 186 187 // offset to double indirect block ptr 188 indirectOffset = GetTripleIndirectBlockPtr() * 189 fragmentSize + (8 * indirectBlockNumber); 190 191 int64_t indirectPointer; 192 // Get the double indirect block ptr 193 read_pos(fd, indirectOffset, 194 (void*)&indirectPointer, sizeof(directBlock)); 195 196 // Get the indirect block 197 // number of indirect block ptr 198 indirectBlockNumber = blockNumber / numberOfBlockPointers; 199 // Indirect block ptr offset 200 indirectOffset = indirectPointer * fragmentSize 201 + (8 * indirectBlockNumber); 202 203 read_pos(fd, indirectOffset, 204 (void*)&indirectPointer, sizeof(directBlock)); 205 206 // Get direct block pointer 207 indirectOffset = indirectPointer * fragmentSize 208 + (8 * (blockNumber % numberOfBlockPointers)); 209 210 read_pos(fd, indirectOffset, 211 (void*)&directBlock, sizeof(directBlock)); 212 213 return directBlock * fragmentSize + blockOffset; 214 } 215 216 return B_BAD_VALUE; 217 } 218 219 220 status_t 221 Inode::ReadLink(char* buffer, size_t *_bufferSize) 222 { 223 strlcpy(buffer, fNode.symlinkpath, *_bufferSize); 224 return B_OK; 225 } 226