Subject: bug#7362: dd strangeness

From: Pádraig Brady <[email-masked]>
Date: Fri, 25 Feb 2011 12:19:35 +0000

On 02/02/11 13:23, Pádraig Brady wrote:
> This looks like another candidate to auto enable fullblock for.
> https://bugzilla.redhat.com/show_bug.cgi?id=614605
> I.E. oflag=direct

Attached is a proposed solution to this.
I'm worried about the last condition though
where we enable 'fullblock' when both count and bs are specified.

For example this would still work:

# Output first 2 parts
$ (echo part1; sleep 1; echo part2; sleep 1; echo discard) |
  dd count=2 obs=1 2>/dev/null
part1
part2

However this would not:

# Output first 2 parts, each being up to 4096 bytes
$ (echo part1; sleep 1; echo part2; sleep 1; echo discard) |
  dd count=2 ibs=4096 obs=1 2>/dev/null
part1
part2
discard

So how contrived is the last example,
given how brittle such a construct is?

cheers,
Pádraig.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index ea35afe..9167537 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -8089,7 +8089,7 @@ Do not truncate the output file.
 @opindex sync @r{(padding with @acronym{ASCII} @sc{nul}s)}
 Pad every input block to size of @samp{ibs} with trailing zero bytes.
 When used with @samp{block} or @samp{unblock}, pad with spaces instead of
-zero bytes.
+zero bytes.  This implies the @samp{fullblock} flag.
 
 @item fdatasync
 @opindex fdatasync
@@ -8135,8 +8135,8 @@ output file to be truncated before being appended to.
 @cindex concurrent I/O
 Use concurrent I/O mode for data.  This mode performs direct I/O
 and drops the @acronym{POSIX} requirement to serialize all I/O to the same file.
-A file cannot be opened in CIO mode and with a standard open at the
-same time.
+A file cannot be opened in CIO mode and with a standard open at the same time.
+This implies the @samp{fullblock} flag.
 
 @item direct
 @opindex direct
@@ -8146,6 +8146,7 @@ Note that the kernel may impose restrictions on read or write buffer sizes.
 For example, with an ext4 destination file system and a linux-based kernel,
 using @samp{oflag=direct} will cause writes to fail with @code{EINVAL} if the
 output buffer size is not a multiple of 512.
+This implies the @samp{fullblock} flag.
 
 @item directory
 @opindex directory
diff --git a/src/dd.c b/src/dd.c
index daddc1e..5b56970 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -1075,6 +1075,19 @@ scanargs (int argc, char *const *argv)
       conversions_mask |= C_TWOBUFS;
     }
 
+  /* Enable 'fullblock' as one wouldn't want random
+     padding applied, when reading from a pipe for example.  */
+  if (conversions_mask & C_SYNC)
+    input_flags |= O_FULLBLOCK;
+  /* Enable 'fullblock' with 'direct' or 'cio' as again if reading from
+     a pipe, we're constrained in how we write to output.  */
+  else if ((input_flags | output_flags) & (O_DIRECT | O_CIO))
+    input_flags |= O_FULLBLOCK;
+  /* Enable 'fullblock' if we're reading a specific number of blocks,
+     with a specific block size.  */
+  else if (max_records && max_records != (uintmax_t) -1 && input_blocksize)
+    input_flags |= O_FULLBLOCK;
+
   if (input_blocksize == 0)
     input_blocksize = DEFAULT_BLOCKSIZE;
   if (output_blocksize == 0)