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 68a27fa..8753fcf 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.
 
+  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.
 
@@ -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.
 
-  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
index b95f8dc..8eb8ac9 100644 (file)
@@ -7721,9 +7721,11 @@ standard platforms.
 
 @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
 
index 0c24b46..8c9400b 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;
 
-/* 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.  */
@@ -259,8 +259,32 @@ static struct symbol_value const conversions[] =
   {"", 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="...".  */
-#define O_FULLBLOCK 010000000 /* Read only full blocks from input */
 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},
-  {"fullblock", O_FULLBLOCK}, /* Read only full blocks from input */
+  {"fullblock", O_FULLBLOCK}, /* Accumulate full blocks from input.  */
   {"",         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 (_("  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)
@@ -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)
 {
@@ -775,7 +801,7 @@ iread_fullblock (int fd, char *buf, size_t 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)
@@ -1031,9 +1057,10 @@ scanargs (int argc, char *const *argv)
       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}"));
index 24e5eba..e550d6a 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
-b" > out_ok
+printf 'a\nb\n' > out_ok || framework_failure
 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