diff options
Diffstat (limited to 'inotail.c')
-rw-r--r-- | inotail.c | 51 |
1 files changed, 27 insertions, 24 deletions
@@ -3,7 +3,7 @@ * A fast implementation of tail which uses the inotify API present in * recent versions of the Linux kernel. * - * Copyright (C) 2005-2007, Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2005-2008, Tobias Klauser <tklauser@distanz.ch> * * The idea was taken from turbotail. * @@ -35,19 +35,14 @@ #include "inotify.h" #include "inotify-syscalls.h" - #include "inotail.h" #define PROGRAM_NAME "inotail" -/* inotify event buffer length for one file */ -#define INOTIFY_BUFLEN (4 * sizeof(struct inotify_event)) /* Print header with filename before tailing the file? */ static char verbose = 0; - /* Tailing relative to begin or end of file */ static char from_begin = 0; - /* Number of ignored files */ static int n_ignored = 0; @@ -67,7 +62,7 @@ static void *emalloc(size_t size) void *ret = malloc(size); if (unlikely(!ret)) { - fprintf(stderr, "Error: Failed to allocate %d bytes of memory (%s)\n", size, strerror(errno)); + fprintf(stderr, "Error: Failed to allocate %zu bytes of memory (%s)\n", size, strerror(errno)); exit(EXIT_FAILURE); } @@ -104,8 +99,10 @@ static void ignore_file(struct file_struct *f) close(f->fd); f->fd = -1; } - f->ignore = 1; - n_ignored++; + if (!f->ignore) { + f->ignore = 1; + n_ignored++; + } } static inline char *pretty_name(char *filename) @@ -480,7 +477,7 @@ out: return rc; } -static int tail_file(struct file_struct *f, unsigned long n_units, char mode, char forever) +static int tail_file(struct file_struct *f, unsigned long n_units, mode_t mode, char forever) { ssize_t bytes_read = 0; off_t offset = 0; @@ -566,33 +563,36 @@ static int handle_inotify_event(struct inotify_event *inev, struct file_struct * if (inev->mask & IN_MODIFY) { char *fbuf; - ssize_t rc; + ssize_t bytes_read; struct stat finfo; if (verbose) write_header(f->name); + if ((ret = fstat(f->fd, &finfo)) < 0) { + fprintf(stderr, "Error: Could not stat file '%s' (%s)\n", f->name, strerror(errno)); + goto ignore; + } + + /* Regular file got truncated */ + if (S_ISREG(finfo.st_mode) && finfo.st_size < f->size) { + fprintf(stderr, "File '%s' truncated\n", f->name); + f->size = finfo.st_size; + } + /* Seek to old file size */ - if (lseek(f->fd, f->size, SEEK_SET) == (off_t) -1) { + if ((ret = lseek(f->fd, f->size, SEEK_SET)) == (off_t) -1) { fprintf(stderr, "Error: Could not seek in file '%s' (%s)\n", f->name, strerror(errno)); - ret = -1; goto ignore; } fbuf = emalloc(f->blksize); - while ((rc = read(f->fd, fbuf, f->blksize)) != 0) - write(STDOUT_FILENO, fbuf, (size_t) rc); - - if (fstat(f->fd, &finfo) < 0) { - fprintf(stderr, "Error: Could not stat file '%s' (%s)\n", f->name, strerror(errno)); - ret = -1; - free(fbuf); - goto ignore; + while ((bytes_read = read(f->fd, fbuf, f->blksize)) != 0) { + write(STDOUT_FILENO, fbuf, (size_t) bytes_read); + f->size += bytes_read; } - f->size = finfo.st_size; - free(fbuf); return ret; } else if (inev->mask & IN_DELETE_SELF) { @@ -602,6 +602,8 @@ static int handle_inotify_event(struct inotify_event *inev, struct file_struct * return 0; } else if (inev->mask & IN_UNMOUNT) { fprintf(stderr, "Device containing file '%s' unmounted.\n", f->name); + } else if (inev->mask & IN_IGNORED) { + return 0; } ignore: @@ -686,7 +688,8 @@ int main(int argc, char **argv) int i, c, ret = 0; int n_files; unsigned long n_units = DEFAULT_N_LINES; - char forever = 0, mode = M_LINES; + mode_t mode = M_LINES; + char forever = 0; char **filenames; struct file_struct *files = NULL; |