diff options
-rw-r--r-- | inotail.c | 68 |
1 files changed, 37 insertions, 31 deletions
@@ -99,21 +99,23 @@ 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) +static off_t lines_to_offset_from_end(struct file_struct *f, unsigned int n_lines) { char buf[BUFFER_SIZE]; - off_t offset = 0; - - /* tail everything for 'inotail -n +0' */ - if (n_lines == 0) - return 0; + off_t offset = f->st_size; - n_lines--; + n_lines++; /* We also count the last \n */ memset(&buf, 0, sizeof(buf)); - while (offset <= f->st_size && n_lines > 0) { + while (offset > 0 && n_lines > 0) { int i, rc; - int block_size = BUFFER_SIZE; + 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; lseek(f->fd, offset, SEEK_SET); @@ -123,42 +125,37 @@ static off_t lines_to_offset_from_begin(struct file_struct *f, unsigned int n_li return -1; } - for (i = 0; i < block_size; i++) { + for (i = block_size; i > 0; i--) { if (buf[i] == '\n') { n_lines--; + if (n_lines == 0) { - offset += i + 1; - return offset; + offset += i + 1; /* We don't want the first \n */ + break; } } } - - offset += block_size; } return offset; + } -static off_t lines_to_offset(struct file_struct *f, unsigned int n_lines) +static off_t lines_to_offset_from_begin(struct file_struct *f, unsigned int n_lines) { char buf[BUFFER_SIZE]; - off_t offset = f->st_size; + off_t offset = 0; - if (from_begin) - return lines_to_offset_from_begin(f, n_lines); + /* tail everything for 'inotail -n +0' */ + if (n_lines == 0) + return 0; - n_lines++; /* We also count the last \n */ + n_lines--; memset(&buf, 0, sizeof(buf)); - while (offset > 0 && n_lines > 0) { + while (offset <= f->st_size && n_lines > 0) { int i, 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; + int block_size = BUFFER_SIZE; lseek(f->fd, offset, SEEK_SET); @@ -168,21 +165,30 @@ static off_t lines_to_offset(struct file_struct *f, unsigned int n_lines) return -1; } - for (i = block_size; i > 0; i--) { + for (i = 0; i < block_size; i++) { if (buf[i] == '\n') { n_lines--; - if (n_lines == 0) { - offset += i + 1; /* We don't want the first \n */ - break; + offset += i + 1; + return offset; } } } + + offset += block_size; } return offset; } +static off_t lines_to_offset(struct file_struct *f, unsigned int n_lines) +{ + if (from_begin) + return lines_to_offset_from_begin(f, n_lines); + else + return lines_to_offset_from_end(f, n_lines); +} + static inline off_t bytes_to_offset(struct file_struct *f, unsigned int n_bytes) { /* tail everything for 'inotail -c +0' */ |