summaryrefslogtreecommitdiff
path: root/text-utils
diff options
context:
space:
mode:
authorDima Kogan <dkogan@cds.caltech.edu>2010-08-14 02:15:47 -0700
committerKarel Zak <kzak@redhat.com>2010-08-20 13:15:14 +0200
commit3a788d773b13078ce8c87247e7f5f556646203b3 (patch)
treeac33c8860b57f6862004c344787b30589b4a5d5d /text-utils
parent9695a7c653c5e1871f7bb78fa0e6ec8d4e74a83a (diff)
downloadutil-linux-old-3a788d773b13078ce8c87247e7f5f556646203b3.tar.gz
tailf: fixed timing issue that could cause duplicate data output
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>
Diffstat (limited to 'text-utils')
-rw-r--r--text-utils/tailf.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/text-utils/tailf.c b/text-utils/tailf.c
index 75998ce7..dc18b2a6 100644
--- a/text-utils/tailf.c
+++ b/text-utils/tailf.c
@@ -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