From b616378ba0cbc1ffeb3c935390896daee0cd78ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teemu=20P=C3=A4tsi?= <44954973+frendsick@users.noreply.github.com> Date: Sun, 20 Apr 2025 10:50:09 +0300 Subject: [PATCH] Fix: miscalculation of NTFS mount file sizes inside WSL (#487) * fix: Limit file size based on the file system I/O block size * fix: Take possible file pre-allocation into account * refactor: Reduce indenting with early return * refactor: Fix clippy::manual_div_ceil * fix: Use target_size instead of max_size * fix: Take possible pre-allocation for a file into account https://github.com/bootandy/dust/pull/487#issuecomment-2816885444 --- src/platform.rs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/platform.rs b/src/platform.rs index 1a3dc23..7d0d145 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -27,19 +27,36 @@ pub fn get_metadata>( }; match metadata { Ok(md) => { + let file_size = md.len(); if use_apparent_size { - Some(( - md.len(), + return Some(( + file_size, Some((md.ino(), md.dev())), (md.mtime(), md.atime(), md.ctime()), - )) - } else { - Some(( - md.blocks() * get_block_size(), - Some((md.ino(), md.dev())), - (md.mtime(), md.atime(), md.ctime()), - )) + )); } + + // On NTFS mounts, the reported block count can be unexpectedly large. + // To avoid overestimating disk usage, cap the allocated size to what the + // file should occupy based on the file system I/O block size (blksize). + // Related: https://github.com/bootandy/dust/issues/295 + let blksize = md.blksize(); + let target_size = file_size.div_ceil(blksize) * blksize; + let reported_size = md.blocks() * get_block_size(); + + // File systems can pre-allocate more space for a file than what would be necessary + let pre_allocation_buffer = blksize * 65536; + let max_size = target_size + pre_allocation_buffer; + let allocated_size = if reported_size > max_size { + target_size + } else { + reported_size + }; + Some(( + allocated_size, + Some((md.ino(), md.dev())), + (md.mtime(), md.atime(), md.ctime()), + )) } Err(_e) => None, }