From b7d46b7558ab0ee3c7b1d8423905dc847900fbcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 5 Aug 2009 14:23:13 +0000 Subject: [PATCH] * Also the indirect array indices can point to a sparse point if they are 0; this fixes problems with large files with sparse ranges (for example, Haiku images). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32131 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/ext2/Inode.cpp | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.cpp b/src/add-ons/kernel/file_systems/ext2/Inode.cpp index 577c810837..409c43b214 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Inode.cpp @@ -110,6 +110,9 @@ Inode::FindBlock(off_t offset, uint32& block) if (offset >= Size()) return B_ENTRY_NOT_FOUND; + // TODO: we could return the size of the sparse range, as this might be more + // than just a block + if (index < EXT2_DIRECT_BLOCKS) { // direct blocks block = B_LENDIAN_TO_HOST_INT32(Node().stream.direct[index]); @@ -130,12 +133,19 @@ Inode::FindBlock(off_t offset, uint32& block) if (indirectBlocks == NULL) return B_IO_ERROR; - indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32( - indirectBlocks[index / perBlock])); - if (indirectBlocks == NULL) - return B_IO_ERROR; + uint32 indirectIndex + = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index / perBlock]); + if (indirectIndex == 0) { + // a sparse indirect block + block = 0; + } else { + indirectBlocks = (uint32*)cached.SetTo(indirectIndex); + if (indirectBlocks == NULL) + return B_IO_ERROR; - block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index & (perBlock - 1)]); + block = B_LENDIAN_TO_HOST_INT32( + indirectBlocks[index & (perBlock - 1)]); + } } else if ((index -= perIndirectBlock) / perBlock < perIndirectBlock) { // triple indirect blocks CachedBlock cached(fVolume); @@ -144,17 +154,30 @@ Inode::FindBlock(off_t offset, uint32& block) if (indirectBlocks == NULL) return B_IO_ERROR; - indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32( - indirectBlocks[index / perIndirectBlock])); - if (indirectBlocks == NULL) - return B_IO_ERROR; + uint32 indirectIndex + = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index / perIndirectBlock]); + if (indirectIndex == 0) { + // a sparse indirect block + block = 0; + } else { + indirectBlocks = (uint32*)cached.SetTo(indirectIndex); + if (indirectBlocks == NULL) + return B_IO_ERROR; - indirectBlocks = (uint32*)cached.SetTo(B_LENDIAN_TO_HOST_INT32( - indirectBlocks[(index / perBlock) & (perBlock - 1)])); - if (indirectBlocks == NULL) - return B_IO_ERROR; + indirectIndex = B_LENDIAN_TO_HOST_INT32( + indirectBlocks[(index / perBlock) & (perBlock - 1)]); + if (indirectIndex == 0) { + // a sparse indirect block + block = 0; + } else { + indirectBlocks = (uint32*)cached.SetTo(indirectIndex); + if (indirectBlocks == NULL) + return B_IO_ERROR; - block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index & (perBlock - 1)]); + block = B_LENDIAN_TO_HOST_INT32( + indirectBlocks[index & (perBlock - 1)]); + } + } } else { // outside of the possible data stream dprintf("ext2: block outside datastream!\n");