csplit: report the size of the split the input failed in - #14295
csplit: report the size of the split the input failed in#14295arbelonson-source wants to merge 2 commits into
Conversation
`dd` puts the value it rejected into the message unquoted, so a byte the
terminal will not show is sent to the terminal as itself:
$ dd status=$'\1'
dd: invalid status level: <the byte>
GNU spells it out instead, and quotes the value even when it is ordinary:
$ dd status=$'\1'
dd: invalid status level: '\001'
$ dd status=bogus
dd: invalid status level: 'bogus'
GNU uses two quoting styles here, and which one goes where is visible from
the outside. The choices -- `status=`, `iflag=`, `oflag=`, `conv=` -- take
plain quoting, where an escape stays inside the quotes:
dd: invalid status level: 'a\'b'
while numbers and operand names take shell syntax, where an unprintable
byte ends the quoted run and a quote in the value switches which quotes
are used:
dd: invalid number: ''$'\001'
dd: invalid number: "a'b"
dd: unrecognized operand ''$'\001''=1'
Both are already in `uucore::quoting_style`, so this is a matter of asking
for them. The quotes move out of the message and into the quoting, which
is what supplies them for every value now.
Fixes uutils#13868.
`csplit` prints the size of each split as it closes it, but a read error
returns straight out of the split loop, so the split that was open when
the input went wrong is never accounted for:
$ csplit a_directory '/^a/'
csplit: read error: Is a directory
GNU closes it first, and prints its size the way it prints any other:
$ csplit a_directory '/^a/'
csplit: read error: Is a directory
0
The two other ways a split can end early, `MatchNotFound` and
`LineOutOfRange`, already call `finish_split` before returning their
error. Read errors take the same path now, via a helper on the writer, so
`--quiet` still silences the count, `-z` still drops an empty split, and
`-k` still keeps the file it counted.
Fixes uutils#13139.
Merging this PR will degrade performance by 4.66%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
|
GNU testsuite comparison: |
Fixes #13139.
csplitprints the size of each split as it closes it, but a read error returns straight out of the split loop, so the split that was open when the input went wrong is never accounted for:The two other ways a split can end early —
MatchNotFoundandLineOutOfRange— already callfinish_splitbefore returning their error, which is whycsplit f '/^zzz/'prints its count today and this one does not. Read errors now take the same path, through a small helper on the writer that closes the split before handing the error on. That keeps the count subject to the same options as any other:--quietsilences it,-zdrops the empty split instead of counting it,-kkeeps the file it counted, and a%REGEXP%section that writes nowhere still prints nothing.One difference remains, in ordering rather than content: GNU prints the count after the error, because it closes the split during its cleanup; we print it before, because the error is reported by the caller once
csplitreturns. The streams are separate, so this is only visible when both are pointed at the same terminal.Testing
/proc/self/memas input, crossed with-k,-z,-s,-b, line patterns, regex patterns,{N}repeats and%REGEXP%, plus the ordinary successful splits and the no-match and out-of-range cases that had to keep their existing counts. All 24 match.test_read_error_reports_the_size_of_the_open_splitcovering the count under-k,-zand-s.test_directory_input_fileusedstderr_only, which asserted the missing count; it now checks both streams and the GNU-matching output.cargo test --features csplit --test tests -- test_csplit: 93 passed, 0 failed;cargo test -p uu_csplit: 41 passed.cargo fmt --checkandcargo clippy -p uu_csplit --all-targets: clean.Disclosure
Prepared with AI assistance (Claude Opus 5, via Claude Code), per the AI policy in CONTRIBUTING.md. GNU's behaviour was established by running the installed GNU binary as a black box; I did not read GNU coreutils source. All testing was run locally.