]> err.no Git - util-linux/commitdiff
tailf: fixed timing issue that could cause duplicate data output
authorDima Kogan <dkogan@cds.caltech.edu>
Sat, 14 Aug 2010 09:15:47 +0000 (02:15 -0700)
committerKarel Zak <kzak@redhat.com>
Fri, 20 Aug 2010 11:15:14 +0000 (13:15 +0200)
The issue is that in roll_file() we fstat() to find the file size, then read()
as much data as we can and then use the previously saved file size to mark our
position. The bug occurs if we read past the file size reported by fstat()
because more data has arrived while we were reading it. The attached patch uses
the current file position as the location marker instead, with some extra logic
to handle tailing truncated files.

[kzak@redhat.com: - fix coding style]

Signed-off-by: Dima Kogan <dkogan@cds.caltech.edu>
Signed-off-by: Karel Zak <kzak@redhat.com>
text-utils/tailf.c

index 75998ce7353b3aeca4c34360873a8612920583b2..dc18b2a640fed3fbfde6e6fafff95845ca15ccb2 100644 (file)
@@ -88,6 +88,7 @@ roll_file(const char *filename, off_t *size)
        char buf[BUFSIZ];
        int fd;
        struct stat st;
+       off_t pos;
 
        if (!(fd = open(filename, O_RDONLY)))
                err(EXIT_FAILURE, _("cannot open \"%s\" for read"), filename);
@@ -111,8 +112,16 @@ roll_file(const char *filename, off_t *size)
                }
                fflush(stdout);
        }
+
+       pos = lseek(fd, 0, SEEK_CUR);
+
+       /* If we've successfully read something, use the file position, this
+        * avoids data duplication. If we read nothing or hit an error, reset
+        * to the reported size, this handles truncated files.
+        */
+       *size = (pos != -1 && pos != *size) ? pos : st.st_size;
+
        close(fd);
-       *size = st.st_size;
 }
 
 static void