Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dd: unexpectedly consumes all bytes from stdin #3008

Closed
jfinkels opened this issue Feb 1, 2022 · 5 comments · Fixed by #4189
Closed

dd: unexpectedly consumes all bytes from stdin #3008

jfinkels opened this issue Feb 1, 2022 · 5 comments · Fixed by #4189
Labels

Comments

@jfinkels
Copy link
Collaborator

jfinkels commented Feb 1, 2022

Executive summary:

Setup:

cargo build -p uu_dd
echo 'abcd' > infile

GNU dd:

$ (dd bs=1 skip=1 count=0 status=none && cat -) < infile
bcd

uutils dd:

$ (./target/debug/dd bs=1 skip=1 count=0 status=none && cat -) < infile

(it produces no output).


I'm going to be very explicit about this because it helped me understand the problem here. The way I'm reading the command line is:

  • dd means copy bytes from stdin to stdout,
  • bs=1 means blocks of 1 byte from the input and write blocks of 1 byte to the output,
  • skip=1 means skip 1 block of the input,
  • count=0 means write 0 blocks to the output,
  • && means do the second command only if the first command terminates with exit status 0,
  • cat - means copy bytes from stdin to stdout,
  • < infile means redirect the bytes of infile into stdin,

Altogether this could be described in English as "send bytes of infile into stdin, have dd skip the first byte and stop, then have cat copy the remaining bytes to stdout".

So the problem seems to be that by the time cat attempts to read from stdin, there are no bytes available to read, but there should be. I took a look in the code for dd and it doesn't seem to be reading more bytes than it should:

match self.src.read(&mut buf[base_idx..]) {
Perhaps this has something to do with how Rust provides a handle to stdin?

(I discovered this issue when looking into test failures in the GNU test tests/misc/head-c.sh.)

@jfinkels
Copy link
Collaborator Author

jfinkels commented Feb 2, 2022

The corresponding GNU test for dd is in tests/dd/not-rewound.sh.

@jfinkels
Copy link
Collaborator Author

jfinkels commented Feb 8, 2022

There's a similar issue with od; a corresponding test is in tests/misc/od-N.sh.

@ArtemSkrebkov
Copy link

I made an attempt to solve this issue. The problem is that an attempt to skip bytes by read_skip leads to consuming all stdin by a rust application: here we lose stdin

A possible workaround is to seek Stdin by interpreting it as File https:/ArtemSkrebkov/coreutils/tree/stop_dd_consume_whole_stdin

Inspired by rust-lang/rust#72802
So if rust-lang/rust#72802 is resolved, the implementation above can be updated to make it safe

Let me know your opinions for the approach suggested.
If maintainers are fine with that, I will clean up the branch and make a PR.

@jfinkels
Copy link
Collaborator Author

I think it would be a welcome addition.

@ArtemSkrebkov
Copy link

Alright, I'll clean that up and make a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants