From ee9871f1934910cd8e88f10d5958afdbf3f0b5ac Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 26 Oct 2006 20:31:43 +0200 Subject: inotail.c: Support inotail -n + Add function lines_to_offset_from_begin() to allow tailing relative to the begin of the file. Also handle the case where the argument for '-c' or 'n' is '+0'. Like GNU tail (and according to its source also tail in UNIX) print the whole file in this case. --- inotail.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/inotail.c b/inotail.c index ded9e43..9356158 100644 --- a/inotail.c +++ b/inotail.c @@ -96,15 +96,58 @@ static void write_header(char *filename) first_file = 0; } +static off_t lines_to_offset_from_begin(struct file_struct *f, unsigned int n_lines) +{ + char buf[BUFFER_SIZE]; + off_t offset = 0; + + /* tail everything vor 'inotail -n +0' */ + if (n_lines == 0) + return 0; + + memset(&buf, 0, sizeof(buf)); + + n_lines--; + + while (offset <= f->st_size && n_lines > 0) { + int i, rc; + int block_size = BUFFER_SIZE; + + lseek(f->fd, offset, SEEK_SET); + + rc = read(f->fd, &buf, block_size); + if (rc < 0) { + fprintf(stderr, "Error: Could not read from file '%s' (%s)\n", f->name, strerror(errno)); + return -1; + } + + for (i = 0; i < block_size; i++) { + if (buf[i] == '\n') { + n_lines--; + if (n_lines == 0) { + offset += i + 1; + return offset; + } + } + } + + offset += block_size; + } + + return offset; +} + static off_t lines_to_offset(struct file_struct *f, unsigned int n_lines) { char buf[BUFFER_SIZE]; off_t offset = f->st_size; - memset(&buf, 0, sizeof(buf)); + if (from_begin) + return lines_to_offset_from_begin(f, n_lines); + else + n_lines++; /* We also count the last \n */ - if (!from_begin) - n_lines += 1; /* We also count the last \n */ + memset(&buf, 0, sizeof(buf)); while (offset > 0 && n_lines > 0) { int i, rc; @@ -141,7 +184,11 @@ static off_t lines_to_offset(struct file_struct *f, unsigned int n_lines) static inline off_t bytes_to_offset(struct file_struct *f, unsigned int n_bytes) { - return from_begin ? ((off_t) n_bytes - 1) : (f->st_size - n_bytes); + /* tail everything vor 'inotail -c +0' */ + if (from_begin && n_bytes == 0) + return 0; + else + return (from_begin ? ((off_t) n_bytes - 1) : (f->st_size - (off_t) n_bytes)); } static int tail_pipe(struct file_struct *f) -- cgit v1.2.3-54-g00ecf