dd: add 'fullblock' iflag
authorNicholas Clark <nicholas.clark@gmail.com>
Thu, 25 Jan 2018 18:00:19 +0000 (19:00 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 25 Jan 2018 18:00:19 +0000 (19:00 +0100)
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>
coreutils/dd.c
docs/posix_conformance.txt

index 38b2a6aa14ddf36e6eb2caf105a52c2b185113dc..0f130bcad27f4b20c3d1fd2c6ea1de8c04ebd59a 100644 (file)
@@ -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 Read full blocks"
 //usage:       )
 //usage:       IF_FEATURE_DD_STATUS(
 //usage:     "\n       status=noxfer   Suppress rate output"
@@ -130,11 +131,12 @@ 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_STATUS_NONE = 1 << 9,
+       FLAG_STATUS_NOXFER = 1 << 10,
 };
 
 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 =
                "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 =
@@ -294,6 +296,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;
@@ -454,7 +457,13 @@ 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
+#endif
+                                       n = safe_read(ifd, ibuf, blocksz);
                                if (n < 0)
                                        goto die_infile;
                                if (n == 0)
@@ -469,8 +478,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 
        while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
                ssize_t n;
-
-               n = safe_read(ifd, ibuf, ibs);
+#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);
                if (n == 0)
                        break;
                if (n < 0) {
index 8b9112020716ba1e2881898409a869da84cc8cb6..cdf89b744d931bcda3d8171b265e5f3bc1dfd64f 100644 (file)
@@ -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