From 135b557f6d14c3ce4d60419602d8ca92316f9a71 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 13 Mar 2006 18:16:41 +0100 Subject: Initial import --- simpletail.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 simpletail.c (limited to 'simpletail.c') diff --git a/simpletail.c b/simpletail.c new file mode 100644 index 0000000..b5df235 --- /dev/null +++ b/simpletail.c @@ -0,0 +1,178 @@ +/* + * simpletail.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inotify.h" +#include "inotify-syscalls.h" + +#include "inotail.h" + +#define BUFFER_SIZE 4096 + +off_t lines(int fd, int file_size, unsigned int nr_lines) +{ + int i; + char buf[BUFFER_SIZE]; + off_t offset = file_size; + + /* Negative offsets don't make sense here */ + if (offset < 0) + offset = 0; + + while (offset > 0 && nr_lines > 0) { + int rc; + int block_size = BUFFER_SIZE; /* Size of the current block we're reading */ + + if (offset < BUFFER_SIZE) + block_size = offset; + + /* Start of current block */ + offset -= block_size; + + dprintf(" offset: %lu\n", offset); + + lseek(fd, offset, SEEK_SET); + + rc = read(fd, &buf, block_size); + + for (i = block_size; i > 0; i--) { + if (buf[i] == '\n') { + dprintf(" Found \\n at position %d\n", i); + nr_lines--; + + if (nr_lines == 0) + break; + } + } + } + + if (nr_lines == 0) + offset += i + 1; /* We don't want the first \n */ + + return offset; +} + +int watch_file(const char *filename, off_t offset) +{ + int ifd, watch; + struct inotify_event *inev; + char buf[BUFFER_SIZE]; + + dprintf(">> Watching %s\n", filename); + + ifd = inotify_init(); + if (ifd < 0) { + perror("inotify_init()"); + exit(-2); + } + + watch = inotify_add_watch(ifd, filename, IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT); + + memset(&buf, 0, sizeof(buf)); + + while (1) { + int len; + + len = read(ifd, buf, sizeof(buf)); + inev = (struct inotify_event *) &buf; + + while (len > 0) { + if (inev->mask & IN_MODIFY) { + int ffd, block_size; + char fbuf[BUFFER_SIZE]; + struct stat finfo; + + dprintf(" File '%s' modified.\n", filename); + dprintf(" offset: %lu.\n", offset); + + ffd = open(filename, O_RDONLY); + if (fstat(ffd, &finfo) < 0) { + perror("fstat()"); + return -1; + } + + /* XXX: block_size could be bigger than BUFFER_SIZE */ + block_size = finfo.st_size - offset; + if (block_size < 0) + block_size = 0; + + lseek(ffd, offset, SEEK_SET); + while (read(ffd, &fbuf, BUFFER_SIZE) != 0) { + write(STDOUT_FILENO, fbuf, block_size); + } + + offset = finfo.st_size; + + close(ffd); + } + + if (inev->mask & IN_DELETE_SELF) { + dprintf(" File '%s' deleted.\n", filename); + return -1; + } + if (inev->mask & IN_MOVE_SELF) { + dprintf(" File '%s' moved.\n", filename); + return -1; + } + if (inev->mask & IN_UNMOUNT) { + dprintf(" Device containing file '%s' unmounted.\n", filename); + return -1; + } + + len -= sizeof(struct inotify_event) + inev->len; + inev = (struct inotify_event *) ((char *) inev + sizeof(struct inotify_event) + inev->len); + } + } +} + +int main(int argc, char **argv) +{ + int fd; + int nr_lines = 0; + int ret = 0; + struct stat finfo; + char buf[BUFFER_SIZE]; + off_t offset = 0; + + if (argc < 3) { + fprintf(stderr, "%s \n", argv[0]); + return -1; + } + + nr_lines = strtol(argv[1], NULL, 0) + 1; + fd = open(argv[2], O_RDONLY); + + if (fd < 0) { + perror("open()"); + return -1; + } + + if (fstat(fd, &finfo) < 0) { + perror("fstat()"); + return -1; + } + + offset = lines(fd, finfo.st_size, nr_lines); + dprintf(" offset: %lu.\n", offset); + + lseek(fd, offset, SEEK_SET); + while (read(fd, &buf, BUFFER_SIZE) != 0) { + write(STDOUT_FILENO, buf, finfo.st_size - offset); + } + + close(fd); + + if (argv[3]) + ret = watch_file(argv[2], finfo.st_size); + + return ret; +} -- cgit v1.2.3-54-g00ecf