| 198 | } |
| 199 | |
| 200 | Vector<uint32_t> Ext2Volume::GetInodeBlocks(uint32_t index, uint32_t count, ext2_inode_t& ino){ |
| 201 | uint32_t blocksPerPointer = blocksize / sizeof(uint32_t); // Amount of blocks in a indirect block table |
| 202 | uint32_t singlyIndirectStart = EXT2_DIRECT_BLOCK_COUNT; |
| 203 | uint32_t doublyIndirectStart = singlyIndirectStart + blocksPerPointer; |
| 204 | uint32_t triplyIndirectStart = doublyIndirectStart + blocksPerPointer * blocksPerPointer; |
| 205 | |
| 206 | assert(index + count < triplyIndirectStart + blocksPerPointer * blocksPerPointer * blocksPerPointer); // Make sure that an invalid index was not passed |
| 207 | |
| 208 | unsigned i = index; |
| 209 | Vector<uint32_t> blocks; |
| 210 | blocks.reserve(count); |
| 211 | |
| 212 | while(i < EXT2_DIRECT_BLOCK_COUNT && i < index + count){ |
| 213 | // Index lies within the direct blocklist |
| 214 | blocks.add_back(ino.blocks[i++]); |
| 215 | } |
| 216 | |
| 217 | if(i < doublyIndirectStart && i < index + count){ |
| 218 | // Index lies within the singly indirect blocklist |
| 219 | uint32_t buffer[blocksize / sizeof(uint32_t)]; |
| 220 | |
| 221 | if(int e = ReadBlockCached(ino.blocks[EXT2_SINGLY_INDIRECT_INDEX], buffer)){ |
| 222 | Log::Info("[Ext2] GetInodeBlocks: Error %i reading block %u (singly indirect block)", e, ino.blocks[EXT2_SINGLY_INDIRECT_INDEX]); |
| 223 | error = DiskReadError; |
| 224 | |
| 225 | blocks.clear(); |
| 226 | return blocks; |
| 227 | } |
| 228 | |
| 229 | while(i < doublyIndirectStart && i < index + count){ |
| 230 | uint32_t block = buffer[(i++) - singlyIndirectStart]; |
| 231 | if(block >= super.blockCount){ |
| 232 | Log::Warning("[Ext2] GetInodeBlocks: Invalid singly indirect block %u, Singly indirect blocklist: %u", block, ino.blocks[EXT2_SINGLY_INDIRECT_INDEX]); |
| 233 | } |
| 234 | blocks.add_back(block); |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | if(i < triplyIndirectStart && i < index + count){ |
| 239 | // Index lies within the doubly indirect blocklist |
| 240 | uint32_t blockPointers[blocksize / sizeof(uint32_t)]; |
| 241 | uint32_t buffer[blocksize / sizeof(uint32_t)]; |
| 242 | |
| 243 | if(int e = ReadBlockCached(ino.blocks[EXT2_DOUBLY_INDIRECT_INDEX], blockPointers)){ |
| 244 | Log::Info("[Ext2] GetInodeBlocks: Error %i reading block %u (doubly indirect block)", e, ino.blocks[EXT2_DOUBLY_INDIRECT_INDEX]); |
| 245 | error = DiskReadError; |
| 246 | |
| 247 | blocks.clear(); |
| 248 | return blocks; |
| 249 | } |
| 250 | |
| 251 | while(i < triplyIndirectStart && i < index + count){ |
| 252 | uint32_t blockPointer = blockPointers[(i - doublyIndirectStart) / blocksPerPointer]; |
| 253 | |
| 254 | if(int e = ReadBlockCached(blockPointer, buffer)){ |
| 255 | Log::Info("[Ext2] GetInodeBlocks: Error %i reading block %u (doubly indirect block pointer)", e, blockPointer); |
| 256 | error = DiskReadError; |
| 257 | |