]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
head: fix --lines=-0 outputting nothing if no newline at EOF
authorАлексей Шилин <rootlexx@mail.ru>
Wed, 29 Jan 2014 01:23:46 +0000 (01:23 +0000)
committerPádraig Brady <P@draigBrady.com>
Sun, 9 Feb 2014 20:22:33 +0000 (20:22 +0000)
* 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
src/head.c
tests/misc/head-elide-tail.pl

diff --git a/NEWS b/NEWS
index 0da82accf8fb5ff82a4184bd090f558263f922ed..e72942b1020cf0ac85d24379f155605bd460add2 100644 (file)
--- 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]
index ddaa9906b41ecc20fbb67f87fab43304c9ccb674..ef368d7ccb009b2ff22d8b81afe592be77f59ffa 100644 (file)
@@ -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.  */
index 758e1c9d05c2178f179176aab449f7e4407c50d5..3c178d6957fe86a3313e23f32065677f97431bf8 100755 (executable)
@@ -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;