ls: round block counts up when scaling to a block size - #14330
Open
Socialpranker wants to merge 1 commit into
Open
ls: round block counts up when scaling to a block size#14330Socialpranker wants to merge 1 commit into
Socialpranker wants to merge 1 commit into
Conversation
A partly used block still occupies a whole block, so scaling an allocation to the block size rounds up. `ls -s --block-size=1000` on a 4096-byte allocation reported 4 blocks instead of 5, and every non-divisor block size was off the same way. The `total` line had a second, related defect: it summed the already scaled per-file figures, so the rounding error was repeated once per entry. It now sums the allocated bytes and scales the sum once. Splits the two steps apart: `get_block_bytes` reports the allocation in bytes and `scale_block_bytes` scales it, rounding up. Non-unix keeps its file-size fallback unscaled, as before.
|
GNU testsuite comparison: |
Contributor
it is old, please try with master binaries |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ls -s --block-size=1000on a 4096-byte allocation printed 4 blocks. A blockthat is only partly used still occupies a whole block, so it is 5:
Every block size that is not a divisor of the allocation was off the same way:
--block-size=Mon a 4 KiB file printed0,--block-size=3000printed 1where it should print 2.
--block-size=512,2048and the default1024divide evenly on a 4 KiB allocation, which is why the existing tests never
caught it.
The
totallinetotalhad a second defect on top of the first. It summed the already scaledper-file figures, so the rounding error was repeated once per entry:
GNU adds up the allocated bytes and scales the sum once. Rounding up per file
and then adding, which is what a one-line fix in the scaling function alone
would produce, overshoots by up to one block per entry.
So the two steps are split apart:
get_block_bytesreports the allocation inbytes,
scale_block_bytesscales a byte count to the block size and rounds up.The per-file cell scales one file;
totalscales the sum.-h/--sipass thebyte count through, as before, since the human-readable formatter scales it
itself.
Non-unix has no allocation figure and falls back to the file size, which was
never scaled here.
scale_block_bytesleaves it alone, so that path isunchanged;
cargo check --target x86_64-pc-windows-gnuis clean.How the GNU behavior was established
By running the installed GNU binary as a black box and recording its output --
the rounding rule and the
totalsemantics above are both read off thetranscripts shown here. I did not read GNU coreutils source.
Testing
cargo test --features ls --no-default-features -- test_ls: 160 passed, 0failed (159 pre-existing, 1 new). No existing test needed a change.
test_ls_block_size_rounds_upderives its expectations from thefilesystem's own
blocks()rather than assuming a 4 KiB granularity, andreturns early when the allocation divides evenly, so it cannot fail spuriously
on a filesystem with a different allocation unit.
ls.rsalone (test file untouched) makes the newtest fail.
cargo fmt --all --checkandcargo clippy -p uu_ls --all-targets: clean.debian:stable-slim, 17 blocksizes x 9 flag combinations over a directory of 6 files, a subdirectory, a
symlink and a FIFO: 63 cases moved from differing to byte-identical, 0
regressions. The
LS_BLOCK_SIZE,BLOCK_SIZEandBLOCKSIZEpaths matchGNU too, where they did not before.
The 27 cases that still differ are all suffix-only block sizes (
K,KB,M),where GNU prints the unit with the number (
4K, not4). That is a separatedefect in a different place -- the same one #13655 is fixing for
du-- and thefigures themselves now agree there as well.
Disclosure
Prepared with AI assistance (Claude Opus 5, via Claude Code), per the AI policy
in CONTRIBUTING.md. Every GNU behavior quoted above came from running the
installed binary, not from reading GPL source. All testing was run locally.