Kamil Dudka c7a6ab
From 9f8be4b0b83d1e0cbf1326f8cb7e077d026d9b0b Mon Sep 17 00:00:00 2001
Kamil Dudka c7a6ab
From: Kamil Dudka <kdudka@redhat.com>
Kamil Dudka c7a6ab
Date: Wed, 23 Jul 2008 11:29:21 +0200
Kamil Dudka c7a6ab
Subject: [PATCH] dd: iflag=fullblock now read full blocks if possible
Kamil Dudka c7a6ab
* src/dd.c (iread_fullblock): New function for reading full blocks.
Kamil Dudka c7a6ab
(scanargs): Check for new parameter iflag=fullblock.
Kamil Dudka c7a6ab
(skip): Use iread_fnc pointer instead of iread function.
Kamil Dudka c7a6ab
(dd_copy): Use iread_fnc pointer instead of iread function.
Kamil Dudka c7a6ab
* tests/dd/misc: Add test for dd - read full blocks.
Kamil Dudka c7a6ab
* doc/coretuils.texi: Mention new parameter iflag=fullblock.
Kamil Dudka c7a6ab
* NEWS: Mentioned the change.
Kamil Dudka c7a6ab
Kamil Dudka c7a6ab
---
Kamil Dudka c7a6ab
 NEWS               |    4 ++++
Kamil Dudka c7a6ab
 doc/coreutils.texi |    6 ++++++
Kamil Dudka c7a6ab
 src/dd.c           |   39 +++++++++++++++++++++++++++++++++++++--
Kamil Dudka c7a6ab
 tests/dd/misc      |    9 +++++++++
Kamil Dudka c7a6ab
 4 files changed, 56 insertions(+), 2 deletions(-)
Kamil Dudka c7a6ab
Kamil Dudka c7a6ab
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
Kamil Dudka c7a6ab
index 81e3b91..b95f8dc 100644
Kamil Dudka c7a6ab
--- a/doc/coreutils.texi
Kamil Dudka c7a6ab
+++ b/doc/coreutils.texi
Kamil Dudka c7a6ab
@@ -7719,6 +7719,12 @@ platforms that distinguish binary from text I/O.
Kamil Dudka c7a6ab
 Use text I/O.  Like @samp{binary}, this option has no effect on
Kamil Dudka c7a6ab
 standard platforms.
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+@item fullblock
Kamil Dudka c7a6ab
+@opindex fullblock
Kamil Dudka c7a6ab
+Read full blocks from input if possible. read() may return early
Kamil Dudka c7a6ab
+if a full block is not available, so retry until data is available
Kamil Dudka c7a6ab
+or end of file is reached. This flag can be used only for the iflag option.
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 @end table
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 These flags are not supported on all systems, and @samp{dd} rejects
Kamil Dudka c7a6ab
diff --git a/src/dd.c b/src/dd.c
Kamil Dudka c7a6ab
index ead9574..1b620df 100644
Kamil Dudka c7a6ab
--- a/src/dd.c
Kamil Dudka c7a6ab
+++ b/src/dd.c
Kamil Dudka c7a6ab
@@ -225,6 +225,9 @@ static sig_atomic_t volatile interrupt_signal;
Kamil Dudka c7a6ab
 /* A count of the number of pending info signals that have been received.  */
Kamil Dudka c7a6ab
 static sig_atomic_t volatile info_signal_count;
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+/* Function used for read (to handle iflag=fullblock parameter) */
Kamil Dudka c7a6ab
+static ssize_t (*iread_fnc) (int fd, char *buf, size_t size);
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 /* A longest symbol in the struct symbol_values tables below.  */
Kamil Dudka c7a6ab
 #define LONGEST_SYMBOL "fdatasync"
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
@@ -257,6 +260,7 @@ static struct symbol_value const conversions[] =
Kamil Dudka c7a6ab
 };
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 /* Flags, for iflag="..." and oflag="...".  */
Kamil Dudka c7a6ab
+#define O_FULLBLOCK 010000000 /* Read only full blocks from input */
Kamil Dudka c7a6ab
 static struct symbol_value const flags[] =
Kamil Dudka c7a6ab
 {
Kamil Dudka c7a6ab
   {"append",	O_APPEND},
Kamil Dudka c7a6ab
@@ -271,6 +275,7 @@ static struct symbol_value const flags[] =
Kamil Dudka c7a6ab
   {"nonblock",	O_NONBLOCK},
Kamil Dudka c7a6ab
   {"sync",	O_SYNC},
Kamil Dudka c7a6ab
   {"text",	O_TEXT},
Kamil Dudka c7a6ab
+  {"fullblock", O_FULLBLOCK}, /* Read only full blocks from input */
Kamil Dudka c7a6ab
   {"",		0}
Kamil Dudka c7a6ab
 };
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
@@ -762,6 +767,27 @@ iread (int fd, char *buf, size_t size)
Kamil Dudka c7a6ab
     }
Kamil Dudka c7a6ab
 }
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+/* Wrapper around iread function which reads full blocks if possible */
Kamil Dudka c7a6ab
+static ssize_t
Kamil Dudka c7a6ab
+iread_fullblock (int fd, char *buf, size_t size)
Kamil Dudka c7a6ab
+{
Kamil Dudka c7a6ab
+  ssize_t nread = 0;
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+  while (0 < size)
Kamil Dudka c7a6ab
+    {
Kamil Dudka c7a6ab
+      ssize_t ncurr = iread(fd, buf, size);
Kamil Dudka c7a6ab
+      if (ncurr < 0)
Kamil Dudka c7a6ab
+	return ncurr;
Kamil Dudka c7a6ab
+      if (ncurr == 0)
Kamil Dudka c7a6ab
+	break;
Kamil Dudka c7a6ab
+      nread += ncurr;
Kamil Dudka c7a6ab
+      buf   += ncurr;
Kamil Dudka c7a6ab
+      size  -= ncurr;
Kamil Dudka c7a6ab
+    }
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+  return nread;
Kamil Dudka c7a6ab
+}
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 /* Write to FD the buffer BUF of size SIZE, processing any signals
Kamil Dudka c7a6ab
    that arrive.  Return the number of bytes written, setting errno if
Kamil Dudka c7a6ab
    this is less than SIZE.  Keep trying if there are partial
Kamil Dudka c7a6ab
@@ -1000,6 +1026,15 @@ scanargs (int argc, char *const *argv)
Kamil Dudka c7a6ab
   if (input_flags & (O_DSYNC | O_SYNC))
Kamil Dudka c7a6ab
     input_flags |= O_RSYNC;
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+  if (output_flags & O_FULLBLOCK)
Kamil Dudka c7a6ab
+    {
Kamil Dudka c7a6ab
+      error (0, 0, "%s: %s", _("invalid output flag"), "'fullblock'");
Kamil Dudka c7a6ab
+      usage (EXIT_FAILURE);
Kamil Dudka c7a6ab
+    }
Kamil Dudka c7a6ab
+  iread_fnc = (input_flags & O_FULLBLOCK)?
Kamil Dudka c7a6ab
+    iread_fullblock:
Kamil Dudka c7a6ab
+    iread;
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
   if (multiple_bits_set (conversions_mask & (C_ASCII | C_EBCDIC | C_IBM)))
Kamil Dudka c7a6ab
     error (EXIT_FAILURE, 0, _("cannot combine any two of {ascii,ebcdic,ibm}"));
Kamil Dudka c7a6ab
   if (multiple_bits_set (conversions_mask & (C_BLOCK | C_UNBLOCK)))
Kamil Dudka c7a6ab
@@ -1197,7 +1232,7 @@ skip (int fdesc, char const *file, uintmax_t records, size_t blocksize,
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
       do
Kamil Dudka c7a6ab
 	{
Kamil Dudka c7a6ab
-	  ssize_t nread = iread (fdesc, buf, blocksize);
Kamil Dudka c7a6ab
+	  ssize_t nread = iread_fnc (fdesc, buf, blocksize);
Kamil Dudka c7a6ab
 	  if (nread < 0)
Kamil Dudka c7a6ab
 	    {
Kamil Dudka c7a6ab
 	      if (fdesc == STDIN_FILENO)
Kamil Dudka c7a6ab
@@ -1508,7 +1543,7 @@ dd_copy (void)
Kamil Dudka c7a6ab
 		(conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
Kamil Dudka c7a6ab
 		input_blocksize);
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
-      nread = iread (STDIN_FILENO, ibuf, input_blocksize);
Kamil Dudka c7a6ab
+      nread = iread_fnc (STDIN_FILENO, ibuf, input_blocksize);
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
       if (nread == 0)
Kamil Dudka c7a6ab
 	break;			/* EOF.  */
Kamil Dudka c7a6ab
diff --git a/tests/dd/misc b/tests/dd/misc
Kamil Dudka c7a6ab
index d54fbfa..24e5eba 100755
Kamil Dudka c7a6ab
--- a/tests/dd/misc
Kamil Dudka c7a6ab
+++ b/tests/dd/misc
Kamil Dudka c7a6ab
@@ -88,6 +88,15 @@ fi
Kamil Dudka c7a6ab
 outbytes=`echo x | dd bs=3 ibs=10 obs=10 conv=sync 2>/dev/null | wc -c`
Kamil Dudka c7a6ab
 test "$outbytes" -eq 3 || fail=1
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+(echo a; sleep .1; echo b) \
Kamil Dudka c7a6ab
+  | LC_ALL=C dd bs=4 status=noxfer iflag=fullblock >out 2>err || fail=1
Kamil Dudka c7a6ab
+echo "a
Kamil Dudka c7a6ab
+b" > out_ok
Kamil Dudka c7a6ab
+echo "1+0 records in
Kamil Dudka c7a6ab
+1+0 records out" > err_ok
Kamil Dudka c7a6ab
+compare out out_ok || fail=1
Kamil Dudka c7a6ab
+compare err err_ok || fail=1
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 test $fail -eq 0 && fail=$warn
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 (exit $fail); exit $fail
Kamil Dudka c7a6ab
diff -ruN coreutils-6.12.old/doc/coreutils.info coreutils-6.12/doc/coreutils.info
Kamil Dudka c7a6ab
--- coreutils-6.12.old/doc/coreutils.info	2008-07-24 12:49:57.000000000 +0200
Kamil Dudka c7a6ab
+++ coreutils-6.12/doc/coreutils.info	2008-07-24 12:52:17.000000000 +0200
Kamil Dudka c7a6ab
@@ -6112,6 +6112,12 @@
Kamil Dudka c7a6ab
           Use text I/O.  Like `binary', this option has no effect on
Kamil Dudka c7a6ab
           standard platforms.
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+    'fullblock'
Kamil Dudka c7a6ab
+          Read full blocks from input if possible. read() may return
Kamil Dudka c7a6ab
+	  early if a full block is not available, so retry until data
Kamil Dudka c7a6ab
+	  is available or end of file is reached. This flag can be used
Kamil Dudka c7a6ab
+	  only for the iflag option.
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
      These flags are not supported on all systems, and `dd' rejects
Kamil Dudka c7a6ab
      attempts to use them when they are not supported.  When reading
Kamil Dudka c7a6ab
diff -ruN coreutils-6.12.old/man/dd.1 coreutils-6.12/man/dd.1
Kamil Dudka c7a6ab
--- coreutils-6.12.old/man/dd.1	2008-07-24 12:51:06.000000000 +0200
Kamil Dudka c7a6ab
+++ coreutils-6.12/man/dd.1	2008-07-24 12:59:06.000000000 +0200
Kamil Dudka c7a6ab
@@ -111,6 +111,13 @@
Kamil Dudka c7a6ab
 .TP
Kamil Dudka c7a6ab
 direct
Kamil Dudka c7a6ab
 use direct I/O for data
Kamil Dudka c7a6ab
+.PP
Kamil Dudka c7a6ab
+FLAG symbols only for iflag option:
Kamil Dudka c7a6ab
+.TP
Kamil Dudka c7a6ab
+fullblock
Kamil Dudka c7a6ab
+Read full blocks from input if possible. read() may return early
Kamil Dudka c7a6ab
+if a full block is not available, so retry until data is available
Kamil Dudka c7a6ab
+or end of file is reached.
Kamil Dudka c7a6ab
 .IP
Kamil Dudka c7a6ab
 directory fail unless a directory
Kamil Dudka c7a6ab
 dsync     use synchronized I/O for data