From 818bf75711938460f43815cfcca8dab16a93ac97 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 11 May 2006 15:31:33 +0200 Subject: simpletail is the new inotail --- simpletail.c | 263 ----------------------------------------------------------- 1 file changed, 263 deletions(-) delete mode 100644 simpletail.c (limited to 'simpletail.c') diff --git a/simpletail.c b/simpletail.c deleted file mode 100644 index 83ce280..0000000 --- a/simpletail.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * simpletail.c - * A fast implementation of tail which uses the inotify-API present in - * recent Linux Kernels. - * - * Copyright (C) 2005-2006, Tobias Klauser - * - * The idea and some code were taken from turbotail. - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "inotify.h" -#include "inotify-syscalls.h" - -#include "inotail.h" - -#define VERSION "0.0" - -#define BUFFER_SIZE 4096 -#define DEFAULT_N_LINES 10 - -/* Print header with filename before tailing the file? */ -static short verbose = 0; - -static void usage(void) -{ - fprintf(stderr, "usage: simpletail [-f] [-n ] \n"); - exit(EXIT_FAILURE); -} - -static void write_header(const char *filename) -{ - static unsigned short first_file = 1; - - fprintf (stdout, "%s==> %s <==\n", (first_file ? "" : "\n"), filename); - first_file = 0; -} - -static off_t lines(int fd, int file_size, unsigned int n_lines) -{ - int i; - char buf[BUFFER_SIZE]; - off_t offset = file_size; - - /* Negative offsets don't make sense here */ - if (offset < 0) - offset = 0; - - n_lines += 1; /* We also count the last \n */ - - while (offset > 0 && n_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); - n_lines--; - - if (n_lines == 0) { - /* We don't want the first \n */ - offset += i + 1; - break; - } - } - } - } - - return offset; -} - -static 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; - } - - block_size = finfo.st_size - offset; - - if (block_size < 0) - block_size = 0; - - /* XXX: Dirty hack for now to make sure - * block_size doesn't get bigger than - * BUFFER_SIZE - */ - if (block_size > BUFFER_SIZE) - block_size = BUFFER_SIZE; - - lseek(ffd, offset, SEEK_SET); - while (read(ffd, &fbuf, block_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 opt, fd, ret = 0; - int n_files = 0; - int n_lines = DEFAULT_N_LINES; - short forever = 0; - char **filenames; - char buf[BUFFER_SIZE]; - struct file_struct *files; - struct stat finfo; - off_t offset = 0; - - if (argc < 2) - usage(); - - for (opt = 1; (opt < argc) && (argv[opt][0] == '-'); opt++) { - switch (argv[opt][1]) { - case 'f': - forever = 1; - break; - case 'n': - n_lines = strtoul(argv[++opt], NULL, 0); - if (n_lines < 0) - n_lines = 0; - break; - case 'v': - verbose = 1; - break; - case 'V': - fprintf(stderr, "simpletail %s\n", VERSION); - return 0; - case 'h': - default: - usage(); - break; - } - } - - /* Do we have some files to read from? */ - if (opt < argc) { - n_files = argc - opt; - filenames = argv + opt; - } else { - usage(); - return -1; - } - - fd = open(*filenames, O_RDONLY); - - if (fd < 0) { - perror("open()"); - return -1; - } - - if (fstat(fd, &finfo) < 0) { - perror("fstat()"); - return -1; - } - - offset = lines(fd, finfo.st_size, n_lines); - dprintf(" offset: %lu.\n", offset); - - if (verbose) - write_header(*filenames); - - lseek(fd, offset, SEEK_SET); - while (read(fd, &buf, BUFFER_SIZE) != 0) { - write(STDOUT_FILENO, buf, finfo.st_size - offset); - } - - close(fd); - - if (forever) - ret = watch_file(*filenames, finfo.st_size); - - return ret; -} -- cgit v1.2.3-54-g00ecf