Skip to content

dd: unexpectedly consumes all bytes from stdin #3008

@jfinkels

Description

@jfinkels

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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions