On Friday 18 July 2008 03:54:41 pm you wrote:
> As for the new name, iflag=block would be my preference if it weren't
> for the existence of conv=block/unblock and iflag=nonblock.  Too much
> room for misunderstanding.
>
> I'd be happy with either of the following, with a slight preference for
> the first (it's shorter and doesn't need the "read" prefix to indicate
> that it affects only how input is read):
>
>     iflag=fullblock
>     conv=readfullblock
Ok, changed to iflag=fullblock - new patch in attachment.

> Kamil, with new features, it is customary to write tests
> to exercise the new functionality.  One way would be
> to do something like this, but appending the new option
>
>     $ (echo a; sleep .1; echo b) \
>
>       | dd conv=block cbs=5 status=noxfer > out 2> err
>
> and then comparing "out" and "err" against expected outputs.
Ok, test added to dd/misc. Thank you for advice.

Kamil


From 0cf35cbb3747502bd961bdb8cb6135034d757e74 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <[EMAIL PROTECTED]>
Date: Mon, 21 Jul 2008 11:51:46 +0200
Subject: [PATCH] Added support for reading of full blocks to dd.

NEWS: mentioned new parameter iflag=fullblock of dd
doc/coretuils.texi: mentioned new parameter iflag=fullblock of dd
src/dd.c(iread_fullblock): warapper around iread for reading full blocks
src/dd.c(scanargs): check for parameter iflag=fullblock
src/dd.c(skip): using iread_fnc pointer instead of iread function
src/dd.c(dd_copy): using iread_fnc pointer instead of iread function
tests/dd/misc: test for new dd option iflag=fullblock
---
 NEWS               |    4 ++++
 doc/coreutils.texi |    6 ++++++
 src/dd.c           |   39 +++++++++++++++++++++++++++++++++++++--
 tests/dd/misc      |   10 ++++++++++
 4 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index d6ed89e..68a27fa 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,10 @@ 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
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 44df6b3..18098a5 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -7710,6 +7710,12 @@ platforms that distinguish binary from text I/O.
 Use text I/O.  Like @samp{binary}, this option has no effect on
 standard platforms.
 
[EMAIL PROTECTED] fullblock
[EMAIL PROTECTED] fullblock
+Read full blocks from input if possible. If 'read' call is terminated
+during read of input block, it will be called again for the remainder input.
+This flag can be used only for iflag option.
+
 @end table
 
 These flags are not supported on all systems, and @samp{dd} rejects
diff --git a/src/dd.c b/src/dd.c
index ead9574..e71d39f 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -225,6 +225,9 @@ 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) */
+static ssize_t (*iread_fnc) (int fd, char *buf, size_t size);
+
 /* A longest symbol in the struct symbol_values tables below.  */
 #define LONGEST_SYMBOL "fdatasync"
 
@@ -257,6 +260,7 @@ static struct symbol_value const conversions[] =
 };
 
 /* Flags, for iflag="..." and oflag="...".  */
+#define O_FULLBLOCK 010000000 /* Read only full blocks from input */
 static struct symbol_value const flags[] =
 {
   {"append",	O_APPEND},
@@ -271,6 +275,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 */
   {"",		0}
 };
 
@@ -762,6 +767,27 @@ iread (int fd, char *buf, size_t size)
     }
 }
 
+/* Wrapper around iread function which reads full blocks if possible */
+static ssize_t
+iread_fullblock (int fd, char *buf, size_t size)
+{
+  ssize_t nread = 0;
+
+  while (0 < size)
+    {
+      ssize_t ncurr = iread(fd, buf, size);
+      if (ncurr < 0)
+  return ncurr;
+      if (ncurr == 0)
+  break;
+      nread += ncurr;
+      buf   += ncurr;
+      size  -= ncurr;
+    }
+
+  return nread;
+}
+
 /* Write to FD the buffer BUF of size SIZE, processing any signals
    that arrive.  Return the number of bytes written, setting errno if
    this is less than SIZE.  Keep trying if there are partial
@@ -1000,6 +1026,15 @@ scanargs (int argc, char *const *argv)
   if (input_flags & (O_DSYNC | O_SYNC))
     input_flags |= O_RSYNC;
 
+  if (output_flags & O_FULLBLOCK)
+    {
+      error (0, 0, "%s: %s", _("invalid output flag"), "'fullblock'");
+      usage (EXIT_FAILURE);
+    }
+  iread_fnc = (input_flags & O_FULLBLOCK)?
+    iread_fullblock:
+    iread;
+
   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_BLOCK | C_UNBLOCK)))
@@ -1197,7 +1232,7 @@ skip (int fdesc, char const *file, uintmax_t records, size_t blocksize,
 
       do
 	{
-	  ssize_t nread = iread (fdesc, buf, blocksize);
+	  ssize_t nread = iread_fnc (fdesc, buf, blocksize);
 	  if (nread < 0)
 	    {
 	      if (fdesc == STDIN_FILENO)
@@ -1508,7 +1543,7 @@ dd_copy (void)
 		(conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
 		input_blocksize);
 
-      nread = iread (STDIN_FILENO, ibuf, input_blocksize);
+      nread = iread_fnc (STDIN_FILENO, ibuf, input_blocksize);
 
       if (nread == 0)
 	break;			/* EOF.  */
diff --git a/tests/dd/misc b/tests/dd/misc
index d54fbfa..9262a35 100755
--- a/tests/dd/misc
+++ b/tests/dd/misc
@@ -88,6 +88,16 @@ fi
 outbytes=`echo x | dd bs=3 ibs=10 obs=10 conv=sync 2>/dev/null | wc -c`
 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
+echo "1+0 records in
+1+0 records out" > err_ok
+diff out out_ok || fail=1
+diff err err_ok || fail=1
+rm -f out out_ok err err_ok
+
 test $fail -eq 0 && fail=$warn
 
 (exit $fail); exit $fail
-- 
1.5.4.1

_______________________________________________
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils

Reply via email to