Improve the display of the total time spent transferring bytes so that
the number of seconds is displayed using the `%g` format specifier as
in `printf`. This matches the behavior of GNU `dd`.
Before this commit, the precision was always set to one digit after
the decimal point. For example,
$ dd count=100000 if=/dev/zero of=/dev/null
100000+0 records in
100000+0 records out
51200000 bytes (51 MB, 49 MiB) copied, 0.2 s, 268.1 MB/s
After this commit, the precision increases dynamically as the duration
decreases. For example,
$ dd count=100000 if=/dev/zero of=/dev/null
100000+0 records in
100000+0 records out
51200000 bytes (51 MB, 49 MiB) copied, 0.1019 s, 507 MB/s
$ dd count=1000 if=/dev/zero of=/dev/null
1000+0 records in
1000+0 records out
512000 bytes (512 kB, 500 KiB) copied, 0.002663 s, 256 MB/s
$ dd count=10 if=/dev/zero of=/dev/null
10+0 records in
10+0 records out
5120 bytes (5.1 kB, 5.0 KiB) copied, 0.000182 s, 5.1 MB/s
Open stdin using its file descriptor so that a `dd skip=N` command in
a subshell does not consume all bytes from stdin.
For example, before this commit, multiple instances of `dd` reading
from stdin and appearing in a single command line would incorrectly
result in an empty stdin for each instance of `dd` after the first:
$ printf "abcdef\n" | (dd bs=1 skip=3 count=0 && dd) 2> /dev/null
# incorrectly results in no output
After this commit, the `dd skip=3` process reads three bytes from the
file descriptor referring to stdin without draining the remaining
three bytes when it terminates:
$ printf "abcdef\n" | (dd bs=1 skip=3 count=0 && dd) 2> /dev/null
def
Move the `dd_out()` function out of the `impl Output` and up to the
module level, renaming it to `dd_copy()`. This change aligns it with
the pattern set by `std::io::copy()`, which similarly takes an input
reader and an output writer.
This does not change the behavior of `dd`, just the code organization
to make it more closely match the idioms in the Rust standard library.
This mirrors a recent commit that introduced the `Dest` enum and a
simplified `Output` struct. These changes allow us to add new types of
inputs and output more easily.
Adjust the rendering of the concise byte counts in both SI and IEC
units to better match the behavior of GNU dd.
Before this commit,
$ head -c 1024 /dev/zero | dd > /dev/null
2+0 records in
2+0 records out
1024 bytes (1 KB, 1024 B) copied, 0.0 s, 1.0 MB/s
After this commit,
$ head -c 1024 /dev/zero | dd > /dev/null
2+0 records in
2+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.0 s, 1.0 MB/s
For comparison, GNU dd produces the following:
$ head -c 1024 /dev/zero | dd > /dev/null
2+0 records in
2+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.000332864 s, 3.1 MB/s
Before this commit, if `sparsefile` were a regular file of non-zero
size whose contents are all null bytes, then
dd if=sparsefile of=outfile conv=notrunc
would have resulted in `outfile` having zero size as reported by
`stat`. After this commit, `outfile` will have the same size as
`sparsefile` (even if the contents are represented sparsely by the
filesystem).
Move some tests that simulate a slow reader from `dd.rs` to
`tests/by-util/test_dd.rs`, and employ a FIFO and `sleep()` to
simulate the slow reader instead of a custom struct that implements
`Read`. This change restricts the type of `Input`s the
`Output::dd_out()` function can accept, facilitating a future change
to make `Input` an enum.
Allow uppercase "B" on its own as a unit specifier for the `count`,
`seek`, and `skip` arguments to `dd`.
For example,
$ printf "abcdef" | dd count=3B status=none
abc
* dd: move argument parsing outside of Input, Output
Move the argument parsing code out of the `Input::new()` and
`Output::new()` functions and into the calling code. This allows the
calling code to make decisions about how to instantiate the `Input`
and `Output` objects if necessary.
* dd: handle stdout redirected to seekable file
Fix a bug in `dd` where null bytes would be unintentionally written if
stdout were redirected to a seekable file. For example, before this
commit, if `dd` were invoked from the command-line as
dd if=infile bs=1 count=10 seek=5 > /dev/sda1
then five zeros would be written to `/dev/sda1` before copying ten
bytes of `infile` to `/dev/sda1`. After this commit, `dd` will
correctly seek five bytes forward in `/dev/sda1` before copying the
ten bytes of `infile`.
Fixes#3542.
The previous encoding handling was unnecessarily complex. This commit removes the enum that specifies the handling and instead has two separate methods to collect the strings either with lossy conversion or by ignoring invalidly encoded strings.
Outside of tests, only `accept_any` was used, meaning that this unnecessarily complicated the code. The behaviour of `accept_any` is now the default (and only) option.