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.
This commit is contained in:
sin 2015-02-09 14:41:49 +00:00
parent ff7093f7b3
commit a25a57f6ac

17
tail.c
View File

@ -1,4 +1,6 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <sys/stat.h>
#include <limits.h> #include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@ -59,6 +61,7 @@ usage(void)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct stat st1, st2;
FILE *fp; FILE *fp;
size_t n = 10, tmpsize; size_t n = 10, tmpsize;
int ret = 0, newline, many; int ret = 0, newline, many;
@ -96,6 +99,8 @@ main(int argc, char *argv[])
if (many) if (many)
printf("%s==> %s <==\n", printf("%s==> %s <==\n",
newline ? "\n" : "", argv[0]); newline ? "\n" : "", argv[0]);
if (stat(argv[0], &st1) < 0)
eprintf("stat %s:", argv[0]);
newline = 1; newline = 1;
tail(fp, argv[0], n); tail(fp, argv[0], n);
@ -108,8 +113,18 @@ main(int argc, char *argv[])
fflush(stdout); fflush(stdout);
} }
if (ferror(fp)) if (ferror(fp))
eprintf("readline '%s':", argv[0]); eprintf("readline %s:", argv[0]);
clearerr(fp); 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); fclose(fp);