diff --git a/src/add-ons/kernel/file_systems/exfat/DataStream.cpp b/src/add-ons/kernel/file_systems/exfat/DataStream.cpp index 4a2788cc3c..48edf05709 100644 --- a/src/add-ons/kernel/file_systems/exfat/DataStream.cpp +++ b/src/add-ons/kernel/file_systems/exfat/DataStream.cpp @@ -24,6 +24,7 @@ DataStream::DataStream(Volume* volume, Inode* inode, off_t size) : kBlockSize(volume->BlockSize()), + kClusterSize(volume->ClusterSize()), fVolume(volume), fInode(inode), fSize(size) @@ -44,8 +45,8 @@ DataStream::FindBlock(off_t pos, off_t& physical, off_t *_length) TRACE("FindBlock: offset larger than size\n"); return B_ENTRY_NOT_FOUND; } - cluster_t clusterIndex = pos / fVolume->ClusterSize(); - uint32 offset = pos % fVolume->ClusterSize(); + cluster_t clusterIndex = pos / kClusterSize; + uint32 offset = pos % kClusterSize; cluster_t cluster = fInode->StartCluster(); for (uint32 i = 0; i < clusterIndex; i++) @@ -53,9 +54,16 @@ DataStream::FindBlock(off_t pos, off_t& physical, off_t *_length) fsblock_t block; fVolume->ClusterToBlock(cluster, block); physical = block * kBlockSize + offset; - *_length = min_c(kBlockSize, fSize - pos); + for (uint32 i = 0; i < 64; i++) { + cluster_t extentEnd = fInode->NextCluster(cluster); + if (extentEnd == EXFAT_CLUSTER_END || extentEnd == cluster + 1) + break; + cluster = extentEnd; + } + *_length = min_c((cluster - clusterIndex + 1) * kClusterSize - offset, + fSize - pos); TRACE("inode %" B_PRIdINO ": cluster %ld, pos %lld, %lld\n", - fInode->ID(), fInode->StartCluster(), pos, physical); + fInode->ID(), clusterIndex, pos, physical); return B_OK; } diff --git a/src/add-ons/kernel/file_systems/exfat/DataStream.h b/src/add-ons/kernel/file_systems/exfat/DataStream.h index ab43f6ece9..53a706fb54 100644 --- a/src/add-ons/kernel/file_systems/exfat/DataStream.h +++ b/src/add-ons/kernel/file_systems/exfat/DataStream.h @@ -27,6 +27,7 @@ public: off_t *_length = NULL); private: const uint32 kBlockSize; + const uint32 kClusterSize; Volume* fVolume; Inode* fInode; off_t fNumBlocks;