Looks great! Do you think we should include a different way to tell the user that some of their requested data didn't actually get written?
On Thu, Jan 25, 2018 at 11:01 AM, Denys Vlasenko <[email protected]> wrote: > Applied without the code which prints warning. > Please try current git. > > On Wed, Jan 24, 2018 at 7:05 PM, Nicholas Clark > <[email protected]> wrote: > > 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. > > > > Signed-off-by: Nicholas Clark <[email protected]> > > --- > > coreutils/dd.c | 64 ++++++++++++++++++++++++++++++ > +++++++++------- > > docs/posix_conformance.txt | 5 ++-- > > 2 files changed, 58 insertions(+), 11 deletions(-) > > > > diff --git a/coreutils/dd.c b/coreutils/dd.c > > index d302f35d3..760420687 100644 > > --- a/coreutils/dd.c > > +++ b/coreutils/dd.c > > @@ -37,7 +37,7 @@ > > //config: elapsed time and speed. > > //config: > > //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: depends on DD > > //config: help > > @@ -57,7 +57,7 @@ > > > > //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: " [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: "Copy a file with converting and formatting\n" > > //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=swab Swap every pair of bytes" > > //usage: "\n iflag=skip_bytes skip=N is in bytes" > > +//usage: "\n iflag=fullblock Try to read full blocks from > input" > > //usage: ) > > //usage: IF_FEATURE_DD_STATUS( > > //usage: "\n status=noxfer Suppress rate output" > > @@ -110,6 +111,10 @@ struct globals { > > unsigned long long begin_time_us; > > #endif > > int flags; > > +#if ENABLE_FEATURE_DD_IBS_OBS > > + char warn_en; > > + char previous_partial; > > +#endif > > } FIX_ALIASING; > > #define G (*(struct globals*)bb_common_bufsiz1) > > #define INIT_G() do { \ > > @@ -130,11 +135,13 @@ enum { > > /* start of input flags */ > > FLAG_IFLAG_SHIFT = 5, > > FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, > > + FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, > > /* end of input flags */ > > - FLAG_TWOBUFS = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, > > - FLAG_COUNT = 1 << 7, > > - FLAG_STATUS_NONE = 1 << 8, > > - FLAG_STATUS_NOXFER = 1 << 9, > > + FLAG_TWOBUFS = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, > > + FLAG_COUNT = 1 << 8, > > + FLAG_BS = 1 << 9, > > + FLAG_STATUS_NONE = 1 << 10, > > + FLAG_STATUS_NOXFER = 1 << 11, > > }; > > > > static void dd_output_status(int UNUSED_PARAM cur_signal) > > @@ -189,6 +196,25 @@ static ssize_t full_write_or_warn(const void *buf, > size_t len, > > return n; > > } > > > > +#if ENABLE_FEATURE_DD_IBS_OBS > > +static ssize_t read_and_warn(int fd, void *buf, size_t count) > > +{ > > + ssize_t result = safe_read(fd, buf, count); > > + > > + if (result <= 0) { > > + return result; > > + } > > + > > + if (G.previous_partial && G.warn_en) { > > + G.warn_en = 0; > > + bb_error_msg("warn: partial read; suggest > iflag=fullblock"); > > + } > > + > > + G.previous_partial = (result < count); > > + return result; > > +} > > +#endif > > + > > static bool write_and_stats(const void *buf, size_t len, size_t obs, > > const char *filename) > > { > > @@ -251,7 +277,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) > > static const char conv_words[] ALIGN1 = > > "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; > > static const char iflag_words[] ALIGN1 = > > - "skip_bytes\0"; > > + "skip_bytes\0""fullblock\0"; > > #endif > > #if ENABLE_FEATURE_DD_STATUS > > static const char status_words[] ALIGN1 = > > @@ -290,6 +316,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) > > /* Partially implemented: */ > > //swab swap every pair of input bytes: will abort on > non-even reads > > OP_iflag_skip_bytes, > > + OP_iflag_fullblock, > > #endif > > }; > > smallint exitcode = EXIT_FAILURE; > > @@ -347,6 +374,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) > > if (what == OP_ibs) { > > /* Must fit into positive ssize_t */ > > ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, > cwbkMG_suffixes); > > + G.flags |= FLAG_BS; > > /*continue;*/ > > } > > if (what == OP_obs) { > > @@ -365,6 +393,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv) > > if (what == OP_bs) { > > ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, > cwbkMG_suffixes); > > obs = ibs; > > +#if ENABLE_FEATURE_DD_IBS_OBS > > + G.flags |= FLAG_BS; > > +#endif > > /*continue;*/ > > } > > /* These can be large: */ > > @@ -405,6 +436,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) > > ibuf = xmalloc(ibs); > > obuf = ibuf; > > #if ENABLE_FEATURE_DD_IBS_OBS > > + G.warn_en = (G.flags & (FLAG_BS + FLAG_COUNT)) == (FLAG_BS + > FLAG_COUNT); > > if (ibs != obs) { > > G.flags |= FLAG_TWOBUFS; > > obuf = xmalloc(obs); > > @@ -450,7 +482,15 @@ int dd_main(int argc UNUSED_PARAM, char **argv) > > size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; > > if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { > > 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 > > + n = read_and_warn(ifd, ibuf, > blocksz); > > +#else > > + n = safe_read(ifd, ibuf, blocksz); > > +#endif > > if (n < 0) > > goto die_infile; > > if (n == 0) > > @@ -465,8 +505,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv) > > > > while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != > count)) { > > ssize_t n; > > - > > +#if ENABLE_FEATURE_DD_IBS_OBS > > + if (G.flags & FLAG_FULLBLOCK) > > + n = full_read(ifd, ibuf, ibs); > > + else > > + n = read_and_warn(ifd, ibuf, ibs); > > +#else > > n = safe_read(ifd, ibuf, ibs); > > +#endif > > if (n == 0) > > break; > > if (n < 0) { > > diff --git a/docs/posix_conformance.txt b/docs/posix_conformance.txt > > index 8b9112020..cdf89b744 100644 > > --- a/docs/posix_conformance.txt > > +++ b/docs/posix_conformance.txt > > @@ -178,9 +178,10 @@ dd POSIX options: > > conv=noerror | yes | | > > conv=notrunc | yes | | > > conv=sync | yes | | > > +dd compatibility options: > > + conv=fsync | yes | | > > iflag=skip_bytes| yes | | > > -dd Busybox specific options: > > - conv=fsync > > + iflag=fullblock | yes | | > > > > df POSIX options > > option | exists | compliant | remarks > > -- > > 2.14.1 > > > > _______________________________________________ > > busybox mailing list > > [email protected] > > http://lists.busybox.net/mailman/listinfo/busybox >
_______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
