>From b1387eb3e922398ab90cf6aa63cac6dea37971fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=A8=D0=B8=D0?= =?UTF-8?q?=BB=D0=B8=D0=BD?= Date: Wed, 29 Jan 2014 01:23:46 +0000 Subject: [PATCH] head: fix --lines=-0 outputting nothing if no newline at EOF * src/head.c (elide_tail_lines_pipe): Just output all input in this case to avoid the issue and also avoid redundant '\n' processing. (elide_tail_lines_seekable): Likewise. * tests/misc/head-elide-tail.pl: Add tests for no '\n' at EOF. * NEWS: Mention the fix. Fixes http://bugs.gnu.org/16329 --- NEWS | 4 ++++ src/head.c | 27 +++++++++++++++++++++------ tests/misc/head-elide-tail.pl | 7 +++++-- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index e091d18..f86e589 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,10 @@ GNU coreutils NEWS -*- outline -*- when reading the SELinux context for a file. [bug introduced in coreutils-8.22] + head --lines=-0, when the input does not contain a trailing '\n', + now copies all input to stdout. Previously nothing was output in this case. + [bug introduced with the --lines=-N feature in coreutils-5.0.1] + ln -sf now replaces symbolic links whose targets can't exist. Previously it would display an error, requiring --no-dereference to avoid the issue. [bug introduced in coreutils-5.3.0] diff --git a/src/head.c b/src/head.c index ddaa990..ef368d7 100644 --- a/src/head.c +++ b/src/head.c @@ -501,6 +501,13 @@ elide_tail_lines_pipe (const char *filename, int fd, uintmax_t n_elide) n_read = safe_read (fd, tmp->buffer, BUFSIZ); if (n_read == 0 || n_read == SAFE_READ_ERROR) break; + + if (! n_elide) + { + fwrite (tmp->buffer, 1, n_read, stdout); + continue; + } + tmp->nbytes = n_read; tmp->nlines = 0; tmp->next = NULL; @@ -636,8 +643,11 @@ elide_tail_lines_seekable (const char *pretty_filename, int fd, return false; } + /* n_lines == 0 case needs special treatment. */ + const bool all_lines = !n_lines; + /* Count the incomplete line on files that don't end with a newline. */ - if (bytes_read && buffer[bytes_read - 1] != '\n') + if (n_lines && bytes_read && buffer[bytes_read - 1] != '\n') --n_lines; while (1) @@ -647,11 +657,16 @@ elide_tail_lines_seekable (const char *pretty_filename, int fd, size_t n = bytes_read; while (n) { - char const *nl; - nl = memrchr (buffer, '\n', n); - if (nl == NULL) - break; - n = nl - buffer; + if (all_lines) + n -= 1; + else + { + char const *nl; + nl = memrchr (buffer, '\n', n); + if (nl == NULL) + break; + n = nl - buffer; + } if (n_lines-- == 0) { /* Found it. */ diff --git a/tests/misc/head-elide-tail.pl b/tests/misc/head-elide-tail.pl index 758e1c9..3c178d6 100755 --- a/tests/misc/head-elide-tail.pl +++ b/tests/misc/head-elide-tail.pl @@ -52,6 +52,8 @@ my @Tests = ['elide-l2', "--lines=-1", {IN=>"a"}, {OUT=>''}], ['elide-l3', "--lines=-1", {IN=>"a\nb"}, {OUT=>"a\n"}], ['elide-l4', "--lines=-1", {IN=>"a\nb\n"}, {OUT=>"a\n"}], + ['elide-l5', "--lines=-0", {IN=>"a\nb\n"}, {OUT=>"a\nb\n"}], + ['elide-l6', "--lines=-0", {IN=>"a\nb"}, {OUT=>"a\nb"}], ); if ($ENV{RUN_EXPENSIVE_TESTS}) @@ -80,9 +82,10 @@ if ($ENV{RUN_EXPENSIVE_TESTS}) } $s =~ s/(.)/$1\n/g; - for my $file_size (0..20) + $s .= 'u'; # test without trailing '\n' + for my $file_size (0..21) { - for my $n_elide (0..20) + for my $n_elide (0..21) { my $input = substr $s, 0, 2 * $file_size; my $out_len = $n_elide < $file_size ? $file_size - $n_elide : 0; -- 1.7.7.6