I don't like last-minute changes, but this seems safe, considering it's in an obscure corner of dd. Who actually uses dd's conv=unblock option? Of those precious few, who would notice the additional newline that dd-with-this-patch now prints for most combinations of output size and conversion block size?
Comments welcome. BTW, this change makes GNU dd compatible with the vendor dd from at least Solaris 10 and FreeBSD. >From 0bbb9d7785957437182fc633b2d387cc51ee918e Mon Sep 17 00:00:00 2001 From: Jim Meyering <[email protected]> Date: Wed, 9 Sep 2009 16:48:02 +0200 Subject: [PATCH] dd conv=unblock: print final newline consistently * src/dd.c (dd_copy) [C_UNBLOCK]: Always print the final newline for non-empty output, not just when output size is a multiple of cbs. * doc/coreutils.texi (dd invocation) [conv=unblock]: Mention that dd prints a newline after each output record, not just when replacing trailing spaces. Reported by Ulrich Drepper. * tests/dd/unblock: New file. Test for this. * tests/Makefile.am (TESTS): Add it. * NEWS (Bug fixes): Mention it. --- NEWS | 4 +++ doc/coreutils.texi | 4 +- src/dd.c | 9 ++++--- tests/Makefile.am | 1 + tests/dd/unblock | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 6 deletions(-) create mode 100755 tests/dd/unblock diff --git a/NEWS b/NEWS index 7805fe5..26dcd59 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,10 @@ GNU coreutils NEWS -*- outline -*- printing a summary to stderr. [bug introduced in coreutils-6.11] + dd cbs=N conv=unblock would fail to print a final newline when the size + of the input was not a multiple of N bytes. + [the non-conforming behavior dates back to the initial implementation] + df no longer requires that each command-line argument be readable [bug introduced in coreutils-7.3] diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 16ff613..93f9390 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -7775,8 +7775,8 @@ dd invocation @item unblock @opindex unblock -Replace trailing spaces in each @samp{cbs}-sized input block with a -newline. +Remove any trailing spaces in each @samp{cbs}-sized input block, +and append a newline. The @samp{block} and @samp{unblock} conversions are mutually exclusive. diff --git a/src/dd.c b/src/dd.c index 04665f9..76a31e9 100644 --- a/src/dd.c +++ b/src/dd.c @@ -1785,10 +1785,11 @@ dd_copy (void) output_char (space_character); } - if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize) - /* Add a final '\n' if there are exactly `conversion_blocksize' - characters in the final record. */ - output_char (newline_character); + if (col && (conversions_mask & C_UNBLOCK)) + { + /* If there was any output, add a final '\n'. */ + output_char (newline_character); + } /* Write out the last block. */ if (oc != 0) diff --git a/tests/Makefile.am b/tests/Makefile.am index 42a12cf..1de53bf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -309,6 +309,7 @@ TESTS = \ dd/skip-seek2 \ dd/skip-seek-past-file \ dd/stderr \ + dd/unblock \ dd/unblock-sync \ df/total-verify \ du/2g \ diff --git a/tests/dd/unblock b/tests/dd/unblock new file mode 100755 index 0000000..6a3634c --- /dev/null +++ b/tests/dd/unblock @@ -0,0 +1,59 @@ +#!/usr/bin/perl +# Exercise dd's conv=unblock mode + +# Copyright (C) 2009 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +use strict; + +(my $program_name = $0) =~ s|.*/||; + +# Turn off localization of executable's output. +...@env{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; +my $out = 'out'; + +my @t = + ( + # An empty test name signals that these are the arguments to use for the + # following tests. + ['', [qw (cbs=3 conv=unblock status=noxfer < )]], + ['0', '', ''], + ['1', "a\n ", "a\n\n\n"], + ['2', "a\n ", "a\n\n"], + ['3', "a ", "a\n"], + ['4', "a \n ", "a \n\n\n"], + ['5', "a \n", "a \n\n"], + ['6', "a ", "a\n\n"], + ['7', "a \n", "a\n\n\n"], + ); + +my @Tests; +my $args; +foreach my $t (@t) + { + $t->[0] eq '' + and $args = $t->[1], next; + + push @Tests, [$t->[0], @$args, {IN=>$t->[1]}, {OUT=>$t->[2]}, + {ERR_SUBST=>'s/^\d+\+\d+ records (?:in|out)$//'}, + {ERR=>"\n\n"}]; + } + +my $save_temps = $ENV{DEBUG}; +my $verbose = $ENV{VERBOSE}; + +my $prog = 'dd'; +my $fail = run_tests ($program_name, $prog, \...@tests, $save_temps, $verbose); +exit $fail; -- 1.6.5.rc0.164.g5f6b0
