dd: add 'fullblock' iflag

Adds a fullblock iflag for improved compatibility with GNU dd.
The new iflag can be used to ensure that dd calls retrieve the
expected amount of data when reading from pipes or unusual
filesystems.

function                                             old     new   delta
packed_usage                                       32249   32334     +85
dd_main                                             1582    1632     +50
static.iflag_words                                    12      22     +10
------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 145/0)             Total: 145 bytes

Signed-off-by: Nicholas Clark <nicholas.clark@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Nicholas Clark 2018-01-25 19:00:19 +01:00 committed by Denys Vlasenko
parent 043be55691
commit 77a6678c42
2 changed files with 26 additions and 12 deletions

View File

@ -37,7 +37,7 @@
//config: elapsed time and speed. //config: elapsed time and speed.
//config: //config:
//config:config FEATURE_DD_IBS_OBS //config:config FEATURE_DD_IBS_OBS
//config: bool "Enable ibs, obs and conv options" //config: bool "Enable ibs, obs, iflag and conv options"
//config: default y //config: default y
//config: depends on DD //config: depends on DD
//config: help //config: help
@ -57,7 +57,7 @@
//usage:#define dd_trivial_usage //usage:#define dd_trivial_usage
//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" //usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n"
//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes]") //usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes|fullblock]")
//usage:#define dd_full_usage "\n\n" //usage:#define dd_full_usage "\n\n"
//usage: "Copy a file with converting and formatting\n" //usage: "Copy a file with converting and formatting\n"
//usage: "\n if=FILE Read from FILE instead of stdin" //usage: "\n if=FILE Read from FILE instead of stdin"
@ -79,6 +79,7 @@
//usage: "\n conv=fsync Physically write data out before finishing" //usage: "\n conv=fsync Physically write data out before finishing"
//usage: "\n conv=swab Swap every pair of bytes" //usage: "\n conv=swab Swap every pair of bytes"
//usage: "\n iflag=skip_bytes skip=N is in bytes" //usage: "\n iflag=skip_bytes skip=N is in bytes"
//usage: "\n iflag=fullblock Read full blocks"
//usage: ) //usage: )
//usage: IF_FEATURE_DD_STATUS( //usage: IF_FEATURE_DD_STATUS(
//usage: "\n status=noxfer Suppress rate output" //usage: "\n status=noxfer Suppress rate output"
@ -130,11 +131,12 @@ enum {
/* start of input flags */ /* start of input flags */
FLAG_IFLAG_SHIFT = 5, FLAG_IFLAG_SHIFT = 5,
FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
/* end of input flags */ /* end of input flags */
FLAG_TWOBUFS = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, FLAG_TWOBUFS = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_COUNT = 1 << 7, FLAG_COUNT = 1 << 8,
FLAG_STATUS_NONE = 1 << 8, FLAG_STATUS_NONE = 1 << 9,
FLAG_STATUS_NOXFER = 1 << 9, FLAG_STATUS_NOXFER = 1 << 10,
}; };
static void dd_output_status(int UNUSED_PARAM cur_signal) static void dd_output_status(int UNUSED_PARAM cur_signal)
@ -255,7 +257,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
static const char conv_words[] ALIGN1 = static const char conv_words[] ALIGN1 =
"notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
static const char iflag_words[] ALIGN1 = static const char iflag_words[] ALIGN1 =
"skip_bytes\0"; "skip_bytes\0""fullblock\0";
#endif #endif
#if ENABLE_FEATURE_DD_STATUS #if ENABLE_FEATURE_DD_STATUS
static const char status_words[] ALIGN1 = static const char status_words[] ALIGN1 =
@ -294,6 +296,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
/* Partially implemented: */ /* Partially implemented: */
//swab swap every pair of input bytes: will abort on non-even reads //swab swap every pair of input bytes: will abort on non-even reads
OP_iflag_skip_bytes, OP_iflag_skip_bytes,
OP_iflag_fullblock,
#endif #endif
}; };
smallint exitcode = EXIT_FAILURE; smallint exitcode = EXIT_FAILURE;
@ -454,7 +457,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs;
if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) {
do { do {
ssize_t n = safe_read(ifd, ibuf, blocksz); ssize_t n;
#if ENABLE_FEATURE_DD_IBS_OBS
if (G.flags & FLAG_FULLBLOCK)
n = full_read(ifd, ibuf, blocksz);
else
#endif
n = safe_read(ifd, ibuf, blocksz);
if (n < 0) if (n < 0)
goto die_infile; goto die_infile;
if (n == 0) if (n == 0)
@ -469,7 +478,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
ssize_t n; ssize_t n;
#if ENABLE_FEATURE_DD_IBS_OBS
if (G.flags & FLAG_FULLBLOCK)
n = full_read(ifd, ibuf, ibs);
else
#endif
n = safe_read(ifd, ibuf, ibs); n = safe_read(ifd, ibuf, ibs);
if (n == 0) if (n == 0)
break; break;

View File

@ -178,9 +178,10 @@ dd POSIX options:
conv=noerror | yes | | conv=noerror | yes | |
conv=notrunc | yes | | conv=notrunc | yes | |
conv=sync | yes | | conv=sync | yes | |
dd compatibility options:
conv=fsync | yes | |
iflag=skip_bytes| yes | | iflag=skip_bytes| yes | |
dd Busybox specific options: iflag=fullblock | yes | |
conv=fsync
df POSIX options df POSIX options
option | exists | compliant | remarks option | exists | compliant | remarks