coreutils
coreutils copied to clipboard
wc: perform lseek once to correct the result from count_bytes_fast path
When using stdin, its possible that the given stdin does not start from the beginning. An example,
hbina@akarin:~/git/uutils$ stat --format='%s' /etc/group
1088
hbina@akarin:~/git/uutils$ (dd ibs=2 skip=1 count=0; wc -c) < /etc/group
0+0 records in
0+0 records out
0 bytes copied, 1.4948e-05 s, 0.0 kB/s
1086
hbina@akarin:~/git/uutils$ (dd ibs=2 skip=1 count=0; cargo run -- wc -c) < /etc/group
0+0 records in
0+0 records out
0 bytes copied, 1.4948e-05 s, 0.0 kB/s
1088
See: https://github.com/uutils/coreutils/issues/3977#issuecomment-1257208684
Signed-off-by: Hanif Bin Ariffin [email protected]
Looks excellent! Do you think you can create a test case for this?
Sure, if the testing library have something equivalent to this (dd ibs=2 skip=1 count=0; cargo run -- wc -c) < /etc/group but I have never seen one like it around here. Perhaps there's a different way to invoke this behavior?
Yeah I'm also not sure how to do this, that's why I asked :) Maybe we could call bash with that command as input? It's very hacky but I don't really see another way.
I have no idea how to do that. Any pointers?
I was thinking something like this:
#[test]
fn test_bash() {
let scene = TestScenario::new(util_name!());
scene
.cmd("bash")
.arg("-c")
.arg("(dd ibs=2 skip=1 count=0; wc -c) < /etc/group")
.succeeds()
.stdout_is("");
}
But we need to make sure that the dd and wc are the uutils versions. Oh and of course it needs to be unix only.
I guess you saw that it is failing with:
cannot subtract i64fromi32``
https://github.com/uutils/coreutils/actions/runs/3189440893/jobs/5204481975
Sorry yea, I was putting this PR on pause while I was trying to solve https://github.com/uutils/coreutils/pull/3987#issuecomment-1264348896 (specifically the part about using our uutil).
no worries ;)
@hbina are you planning to write a test or it is too hard?
It seems that my solution doesn't work in the context of a bash -c
hbina@akarin:~/git/uutils$ bash -c "(dd ibs=2 skip=3 count=0; /home/hbina/git/uutils/target/debug/build/coreutils-f4f87c7d4e42b737/out/../../../wc -c) < /etc/group"
0+0 records in
0+0 records out
0 bytes copied, 1.5279e-05 s, 0.0 kB/s
mode:32768
mode:32768
1088
hbina@akarin:~/git/uutils$ bash -c "(dd ibs=2 skip=3 count=0; wc -c) < /etc/group"
0+0 records in
0+0 records out
0 bytes copied, 1.6761e-05 s, 0.0 kB/s
1082
Any idea why?
Seems to work for me:
$ bash -c "(dd ibs=2 skip=3 count=0; wc -c) < /etc/group"
0+0 records in
0+0 records out
0 bytes copied, 1,1655e-05 s, 0,0 kB/s
1522
$ bash -c "(dd ibs=2 skip=3 count=0; target/debug/coreutils wc -c) < /etc/group"
0+0 records in
0+0 records out
0 bytes copied, 1,4239e-05 s, 0,0 kB/s
1522
Are you sure you got the correct binary?
https://github.com/uutils/coreutils/pull/3987#issuecomment-1272508062
Yep, i got the wrong wc somehow....There's a standalone wc binary in my build folder...where is this from?
Anyways, I have added a test. Hopefully it's good enough. Some of that .last().unwrap() weirdness can be removed if I know what options to pass to dd I think.
@tertsdiepraam the android test is failing because it can't find /etc/group. Do you know of a file that exists in all unix variants?
There's nothing special about /etc/group in this case right? I think it could just be a fixture of the tests. I think even something like echo "abcdefhijklm" > a.txt should work.
Turns out we have some sample files like lorem_ipsum.txt to work with. I can't create a file in the tests, each command seems to run a separate instance.
GNU testsuite comparison:
GNU test failed: tests/rm/rm2. tests/rm/rm2 is passing on 'main'. Maybe you have to rebase?
I can't create a file in the tests, each command seems to run a separate instance.
Each test indeed runs in a tmp directory. You can access it with
let at = &scene.fixtures;
at.touch("filename");
// and
at.write("filename", "contents");
That being said, using the lorem_ipsum.txt is great!
Oh I didn't know about those! Thanks for the suggestion.
I suppose we should write some more documentation for those 😄
GNU testsuite comparison:
GNU test failed: tests/rm/rm2. tests/rm/rm2 is passing on 'main'. Maybe you have to rebase?
GNU testsuite comparison:
GNU test failed: tests/misc/tee. tests/misc/tee is passing on 'main'. Maybe you have to rebase?
GNU testsuite comparison:
Congrats! The gnu test tests/tail-2/inotify-dir-recreate is no longer failing!
GNU testsuite comparison:
GNU test failed: tests/rm/rm2. tests/rm/rm2 is passing on 'main'. Maybe you have to rebase?
GNU testsuite comparison:
Congrats! The gnu test tests/tail-2/inotify-dir-recreate is no longer failing!
@hbina ping ?
I honestly don't remember at all why I made that change. I am going through it now and I don't think it make particular sense either. So I will close this PR and hopefully someone else picks it up. I think the logic is fine but the details are hard to get right. I think I remember this feature failing on WSL.