dd: minor fullblock changes
authorJim Meyering <meyering@redhat.com>
Wed, 23 Jul 2008 12:50:52 +0000 (14:50 +0200)
committerJim Meyering <meyering@redhat.com>
Wed, 23 Jul 2008 13:55:45 +0000 (15:55 +0200)
* src/dd.c (O_FULLBLOCK): Define using an enum, not #define.
Derive the value, rather than hard-coding to one that might conflict.
(usage): Mention iflag=fullblock in --help output.
(scanargs): Reset the O_FULLBLOCK bit, so that we don't try to set
an undefined attribute via fcntl (fd, F_SETFL, ...
* tests/dd/misc: Signal framework_failure when necessary.
Use "compare actual expected", so any diffs look "right".
* NEWS (dd): Alphabetize and reword.
* coreutils.texi (dd invocation): Adjust wording.

NEWS
doc/coreutils.texi
src/dd.c
tests/dd/misc

diff --git a/NEWS b/NEWS
index 68a27fae928df0f3c9b89c9a33fa1cddc6e587ca..8753fcfc6920a116d9159cb0022069642089d90e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   comm accepts new option, --output-delimiter=STR, that allows specification
   of an output delimiter other than the default single TAB.
 
   comm accepts new option, --output-delimiter=STR, that allows specification
   of an output delimiter other than the default single TAB.
 
+  dd accepts iflag=fullblock to make it accumulate full input blocks.
+  With this new option, after a short read, dd repeatedly calls read,
+  until it fills the incomplete block, reaches EOF, or encounters an error.
+
   md5sum now accepts the new option, --quiet, to suppress the printing of
   'OK' messages.  sha1sum, sha224sum, sha384sum, and sha512sum accept it, too.
 
   md5sum now accepts the new option, --quiet, to suppress the printing of
   'OK' messages.  sha1sum, sha224sum, sha384sum, and sha512sum accept it, too.
 
@@ -27,10 +31,6 @@ GNU coreutils NEWS                                    -*- outline -*-
   represents the maximum number of inputs that will be merged at once.
   When processing more than NMERGE inputs, sort uses temporary files.
 
   represents the maximum number of inputs that will be merged at once.
   When processing more than NMERGE inputs, sort uses temporary files.
 
-  dd accepts a new parameter iflag=fullblock which turn on reading of full
-  blocks  where possible. If this parameter is used and 'read' call is
-  terminated during read, it will be called again for remainder input.
-
 ** Bug fixes
 
   chcon --verbose now prints a newline after each message
 ** Bug fixes
 
   chcon --verbose now prints a newline after each message
index b95f8dc50506303377882f3909dae60f39a3c173..8eb8ac9da4fe26335ea2d9cacf64b3c944539812 100644 (file)
@@ -7721,9 +7721,11 @@ standard platforms.
 
 @item fullblock
 @opindex fullblock
 
 @item fullblock
 @opindex fullblock
-Read full blocks from input if possible. read() may return early
-if a full block is not available, so retry until data is available
-or end of file is reached. This flag can be used only for the iflag option.
+Accumulate full blocks from input.  The @code{read} system call
+may return early if a full block is not available.
+When that happens, continue calling @code{read} to fill the remainder
+of the block.
+This flag can be used only with @code{iflag}.
 
 @end table
 
 
 @end table
 
index 0c24b468ab25854c85a240e628c7990451ff4059..8c9400b11641cfe1691a5be6aff007cce75f64f4 100644 (file)
--- a/src/dd.c
+++ b/src/dd.c
@@ -225,7 +225,7 @@ static sig_atomic_t volatile interrupt_signal;
 /* A count of the number of pending info signals that have been received.  */
 static sig_atomic_t volatile info_signal_count;
 
 /* A count of the number of pending info signals that have been received.  */
 static sig_atomic_t volatile info_signal_count;
 
-/* Function used for read (to handle iflag=fullblock parameter) */
+/* Function used for read (to handle iflag=fullblock parameter) */
 static ssize_t (*iread_fnc) (int fd, char *buf, size_t size);
 
 /* A longest symbol in the struct symbol_values tables below.  */
 static ssize_t (*iread_fnc) (int fd, char *buf, size_t size);
 
 /* A longest symbol in the struct symbol_values tables below.  */
@@ -259,8 +259,32 @@ static struct symbol_value const conversions[] =
   {"", 0}
 };
 
   {"", 0}
 };
 
+enum
+  {
+    /* Use a value that is larger than that of any other O_ symbol.  */
+    O_FULLBLOCK = ((MAX (O_APPEND,
+                   MAX (O_BINARY,
+                   MAX (O_DIRECT,
+                   MAX (O_DIRECTORY,
+                   MAX (O_DSYNC,
+                   MAX (O_NOATIME,
+                   MAX (O_NOCTTY,
+                   MAX (O_NOFOLLOW,
+                   MAX (O_NOLINKS,
+                   MAX (O_NONBLOCK,
+                   MAX (O_SYNC, O_TEXT)))))))))))) << 1)
+  };
+
+/* Ensure that we didn't shift it off the end.  */
+verify (O_FULLBLOCK != 0);
+
+/* Ensure that this is a single-bit value.  */
+verify ((O_FULLBLOCK &
+        ( O_APPEND | O_BINARY | O_DIRECT | O_DIRECTORY | O_DSYNC
+          | O_NOATIME | O_NOCTTY | O_NOFOLLOW | O_NOLINKS | O_NONBLOCK
+          | O_SYNC | O_TEXT)) == 0);
+
 /* Flags, for iflag="..." and oflag="...".  */
 /* Flags, for iflag="..." and oflag="...".  */
-#define O_FULLBLOCK 010000000 /* Read only full blocks from input */
 static struct symbol_value const flags[] =
 {
   {"append",   O_APPEND},
 static struct symbol_value const flags[] =
 {
   {"append",   O_APPEND},
@@ -275,7 +299,7 @@ static struct symbol_value const flags[] =
   {"nonblock", O_NONBLOCK},
   {"sync",     O_SYNC},
   {"text",     O_TEXT},
   {"nonblock", O_NONBLOCK},
   {"sync",     O_SYNC},
   {"text",     O_TEXT},
-  {"fullblock", O_FULLBLOCK}, /* Read only full blocks from input */
+  {"fullblock", O_FULLBLOCK}, /* Accumulate full blocks from input.  */
   {"",         0}
 };
 
   {"",         0}
 };
 
@@ -493,6 +517,8 @@ Each FLAG symbol may be:\n\
        fputs (_("  dsync     use synchronized I/O for data\n"), stdout);
       if (O_SYNC)
        fputs (_("  sync      likewise, but also for metadata\n"), stdout);
        fputs (_("  dsync     use synchronized I/O for data\n"), stdout);
       if (O_SYNC)
        fputs (_("  sync      likewise, but also for metadata\n"), stdout);
+      fputs (_("  fullblock  accumulate full blocks of input (iflag only)\n"),
+            stdout);
       if (O_NONBLOCK)
        fputs (_("  nonblock  use non-blocking I/O\n"), stdout);
       if (O_NOATIME)
       if (O_NONBLOCK)
        fputs (_("  nonblock  use non-blocking I/O\n"), stdout);
       if (O_NOATIME)
@@ -767,7 +793,7 @@ iread (int fd, char *buf, size_t size)
     }
 }
 
     }
 }
 
-/* Wrapper around iread function which reads full blocks if possible */
+/* Wrapper around iread function to accumulate full blocks.  */
 static ssize_t
 iread_fullblock (int fd, char *buf, size_t size)
 {
 static ssize_t
 iread_fullblock (int fd, char *buf, size_t size)
 {
@@ -775,7 +801,7 @@ iread_fullblock (int fd, char *buf, size_t size)
 
   while (0 < size)
     {
 
   while (0 < size)
     {
-      ssize_t ncurr = iread(fd, buf, size);
+      ssize_t ncurr = iread (fd, buf, size);
       if (ncurr < 0)
        return ncurr;
       if (ncurr == 0)
       if (ncurr < 0)
        return ncurr;
       if (ncurr == 0)
@@ -1031,9 +1057,10 @@ scanargs (int argc, char *const *argv)
       error (0, 0, "%s: %s", _("invalid output flag"), "'fullblock'");
       usage (EXIT_FAILURE);
     }
       error (0, 0, "%s: %s", _("invalid output flag"), "'fullblock'");
       usage (EXIT_FAILURE);
     }
-  iread_fnc = (input_flags & O_FULLBLOCK)?
-    iread_fullblock:
-    iread;
+  iread_fnc = ((input_flags & O_FULLBLOCK)
+              ? iread_fullblock
+              : iread);
+  input_flags &= ~O_FULLBLOCK;
 
   if (multiple_bits_set (conversions_mask & (C_ASCII | C_EBCDIC | C_IBM)))
     error (EXIT_FAILURE, 0, _("cannot combine any two of {ascii,ebcdic,ibm}"));
 
   if (multiple_bits_set (conversions_mask & (C_ASCII | C_EBCDIC | C_IBM)))
     error (EXIT_FAILURE, 0, _("cannot combine any two of {ascii,ebcdic,ibm}"));
index 24e5eba55d5de0fcd578d1edb08edc120378e3c0..e550d6a523f1a15f271cf0d951cdbc6e414c75bd 100755 (executable)
@@ -90,12 +90,11 @@ test "$outbytes" -eq 3 || fail=1
 
 (echo a; sleep .1; echo b) \
   | LC_ALL=C dd bs=4 status=noxfer iflag=fullblock >out 2>err || fail=1
 
 (echo a; sleep .1; echo b) \
   | LC_ALL=C dd bs=4 status=noxfer iflag=fullblock >out 2>err || fail=1
-echo "a
-b" > out_ok
+printf 'a\nb\n' > out_ok || framework_failure
 echo "1+0 records in
 echo "1+0 records in
-1+0 records out" > err_ok
-compare out out_ok || fail=1
-compare err err_ok || fail=1
+1+0 records out" > err_ok || framework_failure
+compare out_ok out || fail=1
+compare err_ok err || fail=1
 
 test $fail -eq 0 && fail=$warn
 
 
 test $fail -eq 0 && fail=$warn