less: rearrange detection of non-regular files
authorRon Yorston <rmy@pobox.com>
Fri, 24 Jul 2015 13:28:08 +0000 (14:28 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 31 Jul 2015 14:22:07 +0000 (16:22 +0200)
Move the code to detect non-regular files to the point where the
file is being opened.  If num_lines == READING_FILE guarantees
that the file is regular.

Detect when a file becomes unreadable between it first being opened
and the call to update_num_lines.  Mark the file as being non-regular
so we don't try that again.

function                                             old     new   delta
reinitialize                                         197     245     +48
update_num_lines                                     159     127     -32
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 48/-32)             Total: 16 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
miscutils/less.c

index 8fd0874e228854e4ee0b6b34b22fad580172350a..91a933a3add27dd8d32d4a794b39458f72f48f13 100644 (file)
@@ -167,7 +167,8 @@ enum { pattern_valid = 0 };
 
 enum {
        READING_FILE = -1,
-       READING_STDIN = -2
+       READING_STDIN = -2,
+       READING_NONREG = -3
 };
 
 struct globals {
@@ -615,15 +616,16 @@ static void update_num_lines(void)
        int count, fd;
        ssize_t len, i;
        char buf[4096];
-       struct stat stbuf;
 
+       /* only do this for regular files */
        if (num_lines == READING_FILE) {
                count = 0;
                fd = open(filename, O_RDONLY);
-               if (fd < 0)
-                       goto skip;
-               if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode))
-                       goto do_close;
+               if (fd < 0) {
+                       /* somebody stole my file! */
+                       num_lines = READING_NONREG;
+                       return;
+               }
                while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
                        for (i = 0; i < len; ++i) {
                                if (buf[i] == '\n' && ++count == MAXLINES)
@@ -632,9 +634,7 @@ static void update_num_lines(void)
                }
  done:
                num_lines = count;
- do_close:
                close(fd);
- skip: ;
        }
 }
 
@@ -943,6 +943,13 @@ static void buffer_line(int linenum)
 static void open_file_and_read_lines(void)
 {
        if (filename) {
+#if ENABLE_FEATURE_LESS_FLAGS
+               struct stat stbuf;
+
+               xstat(filename, &stbuf);
+               if (!S_ISREG(stbuf.st_mode))
+                       num_lines = READING_NONREG;
+#endif
                xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
        } else {
                /* "less" with no arguments in argv[] */