tail: fix "tail +N file_shorter_than_N"
authorDenys Vlasenko <vda.linux@googlemail.com>
Sun, 9 Aug 2009 20:06:56 +0000 (22:06 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 9 Aug 2009 20:06:56 +0000 (22:06 +0200)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
coreutils/tail.c
testsuite/tail.tests [new file with mode: 0755]

index ef1326c831d9f0c512d7789e4c7ac0b333d1f109..5f98bff820ee292cb6aefba69abf657f499fbb26 100644 (file)
@@ -50,12 +50,12 @@ static ssize_t tail_read(int fd, char *buf, size_t count)
        off_t current;
        struct stat sbuf;
 
-       /* (A good comment is missing here) */
-       current = lseek(fd, 0, SEEK_CUR);
        /* /proc files report zero st_size, don't lseek them. */
-       if (fstat(fd, &sbuf) == 0 && sbuf.st_size)
+       if (fstat(fd, &sbuf) == 0 && sbuf.st_size) {
+               current = lseek(fd, 0, SEEK_CUR);
                if (sbuf.st_size < current)
                        lseek(fd, 0, SEEK_SET);
+       }
 
        r = full_read(fd, buf, count);
        if (r < 0) {
@@ -119,10 +119,11 @@ int tail_main(int argc, char **argv)
 #if ENABLE_FEATURE_FANCY_TAIL
        /* q: make it impossible for nfiles to be > header_threshhold */
        if (opt & 0x8) header_threshhold = UINT_MAX; // -q
+       //if (opt & 0x10) // -s
        if (opt & 0x20) header_threshhold = 0; // -v
-#define FOLLOW_RETRY (opt & 0x40)
+# define FOLLOW_RETRY (opt & 0x40)
 #else
-#define FOLLOW_RETRY 0
+# define FOLLOW_RETRY 0
 #endif
        argc -= optind;
        argv += optind;
@@ -189,7 +190,7 @@ int tail_main(int argc, char **argv)
                        off_t current = lseek(fds[i], 0, SEEK_END);
                        if (current > 0) {
                                if (count == 0)
-                                       continue; /* showing zero lines is easy :) */
+                                       continue; /* showing zero bytes is easy :) */
                                current -= count;
                                if (current < 0)
                                        current = 0;
@@ -201,12 +202,15 @@ int tail_main(int argc, char **argv)
 
                buf = tailbuf;
                taillen = 0;
+               /* "We saw 1st line/byte".
+                * Used only by +N code ("start from Nth", 1-based) */
                seen = 1;
                newlines_seen = 0;
                while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
                        if (from_top) {
                                int nwrite = nread;
                                if (seen < count) {
+                                       /* We need to skip a few more bytes/lines */
                                        if (COUNT_BYTES) {
                                                nwrite -= (count - seen);
                                                seen = count;
diff --git a/testsuite/tail.tests b/testsuite/tail.tests
new file mode 100755 (executable)
index 0000000..d97bf7b
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright 2009 by Denys Vlasenko <vda.linux@googlemail.com>
+# Licensed under GPL v2, see file LICENSE for details.
+
+. testing.sh
+
+# testing "test name" "command" "expected result" "file input" "stdin"
+#   file input will be file called "input"
+#   test can create a file "actual" instead of writing to stdout
+
+testing "tail: +N with N > file length" \
+       "tail -c +55 2>&1; echo \$?" \
+       "0\n" \
+       "" "qw"
+
+exit $FAILCOUNT