* 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
This commit is contained in:
Axel Dörfler
2009-08-05 14:23:13 +00:00
parent cfd22919f2
commit b7d46b7558
+37 -14
View File
@@ -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");