diff options
author | Tobias Klauser <tklauser@distanz.ch> | 2006-10-26 20:31:43 +0200 |
---|---|---|
committer | Tobias Klauser <tklauser@xenon.tklauser.home> | 2006-10-26 20:31:43 +0200 |
commit | ee9871f1934910cd8e88f10d5958afdbf3f0b5ac (patch) | |
tree | 3e63e3b9e6f4eb1416aaf324aabfacdab33b67d1 | |
parent | f09e7bf71c2b64df952650623fcd0b870c596ca4 (diff) |
inotail.c: Support inotail -n +<num>
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.
-rw-r--r-- | inotail.c | 55 |
1 files changed, 51 insertions, 4 deletions
@@ -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) |