[hackers] [sbase] tail: Add rudimentary support to detect file truncation || sin

From: <git_AT_suckless.org>
Date: Mon, 9 Feb 2015 16:25:08 +0100 (CET)

commit 5dba7b6c44c53e44b25e62b90fe7da994ba2e34e
Author: sin <sin_AT_2f30.org>
Date: Mon Feb 9 14:41:49 2015 +0000

    tail: Add rudimentary support to detect file truncation
    
    We cannot in general detect that truncation happened. At the moment
    we use a heuristic to compare the file size before and after a write
    happened. If the new file size is smaller than the old, we correctly
    handle truncation and dump the entire file to stdout.
    
    If it so happened that the new size is larger or equal to the old size
    after the file had been truncated without any reads in between, we will
    assume the data was appended to the file.
    
    There is no known way around this other than using inotify or kevent
    which is outside the scope of sbase.

diff --git a/tail.c b/tail.c
index 36fec77..11af1dd 100644
--- a/tail.c
+++ b/tail.c
_AT_@ -1,4 +1,6 @@
 /* See LICENSE file for copyright and license details. */
+#include <sys/stat.h>
+
 #include <limits.h>
 #include <stdint.h>
 #include <stdio.h>
_AT_@ -59,6 +61,7 @@ usage(void)
 int
 main(int argc, char *argv[])
 {
+ struct stat st1, st2;
         FILE *fp;
         size_t n = 10, tmpsize;
         int ret = 0, newline, many;
_AT_@ -96,6 +99,8 @@ main(int argc, char *argv[])
                         if (many)
                                 printf("%s==> %s <==\n",
                                        newline ? "\n" : "", argv[0]);
+ if (stat(argv[0], &st1) < 0)
+ eprintf("stat %s:", argv[0]);
                         newline = 1;
                         tail(fp, argv[0], n);
 
_AT_@ -108,8 +113,18 @@ main(int argc, char *argv[])
                                                 fflush(stdout);
                                         }
                                         if (ferror(fp))
- eprintf("readline '%s':", argv[0]);
+ eprintf("readline %s:", argv[0]);
                                         clearerr(fp);
+ /* ignore error in case file was removed, we continue
+ * tracking the existing open file descriptor */
+ if (!stat(argv[0], &st2)) {
+ if (st2.st_size < st1.st_size) {
+ fprintf(stderr, "%s: file truncated\n", argv[0]);
+ rewind(fp);
+ }
+ st1 = st2;
+ }
+ sleep(1);
                                 }
                         }
                         fclose(fp);
Received on Mon Feb 09 2015 - 16:25:08 CET

This archive was generated by hypermail 2.3.0 : Mon Feb 09 2015 - 16:36:16 CET