diff options
author | Tobias Klauser <tklauser@distanz.ch> | 2007-09-18 13:28:59 +0200 |
---|---|---|
committer | Tobias Klauser <tklauser@xenon.tklauser.home> | 2007-09-18 13:28:59 +0200 |
commit | 8787c5e9f422ae6a9d3e3f5445301f753c3fe02d (patch) | |
tree | 50fca56db6cc694df2522ba17e4024521c218b74 | |
parent | 21fc4aa4615803896f28bfc8e0009504effdd690 (diff) |
inotail.c: Implement tail_pipe_bytes()
For now more or less a copy from coreutils
-rw-r--r-- | inotail.c | 79 | ||||
-rw-r--r-- | inotail.h | 7 |
2 files changed, 77 insertions, 9 deletions
@@ -345,23 +345,84 @@ out: return rc; } -/* TODO: Implement me :) */ static ssize_t tail_pipe_bytes(struct file_struct *f, unsigned long n_bytes) { + struct char_buf *first, *last, *tmp; ssize_t rc; - char buf[BUFSIZ]; + unsigned long total_bytes = 0; + unsigned long i = 0; /* Index into buffer */ - /* We will just tail everything here */ - while ((rc = read(f->fd, buf, f->blksize)) > 0) { - if (write(STDOUT_FILENO, buf, (size_t) rc) <= 0) { - /* e.g. when writing to a pipe which gets closed */ + if (n_bytes == 0) + return 0; + + first = last = emalloc(sizeof(struct char_buf)); + first->n_bytes = 0; + first->next = NULL; + tmp = emalloc(sizeof(struct char_buf)); + + while(1) { + if ((rc = read(f->fd, tmp->buf, BUFSIZ)) <= 0) { + if (rc < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + else + break; + } + total_bytes += rc; + tmp->n_bytes = rc; + tmp->next = NULL; + + /* Try to append to the previous buffer if there's enough free + * space + */ + if (tmp->n_bytes + last->n_bytes < BUFSIZ) { + memcpy(&last->buf[last->n_bytes], tmp->buf, tmp->n_bytes); + last->n_bytes += tmp->n_bytes; + } else { + last = last->next = tmp; + if (total_bytes - first->n_bytes > n_bytes) { + tmp = first; + total_bytes -= first->n_bytes; + first = first->next; + } else + tmp = emalloc(sizeof(struct char_buf)); + } + } + + free(tmp); + + if (rc < 0) { + fprintf(stderr, "Error: Could not read from %s\n", pretty_name(f->name)); + goto out; + } + + /* Skip unneeded buffers */ + for (tmp = first; total_bytes - tmp->n_bytes > n_bytes; tmp = tmp->next) + total_bytes -= tmp->n_bytes; + + if (total_bytes > n_bytes) + i = total_bytes - n_bytes; + + if ((rc = write(STDOUT_FILENO, &tmp->buf[i], tmp->n_bytes - i)) <= 0) { + /* e.g. when writing to a pipe which gets closed */ + fprintf(stderr, "Error: Could not write to stdout (%s)\n", strerror(errno)); + goto out; + } + + for (tmp = tmp->next; tmp; tmp = tmp->next) + if ((rc = write(STDOUT_FILENO, tmp->buf, tmp->n_bytes)) <= 0) { fprintf(stderr, "Error: Could not write to stdout (%s)\n", strerror(errno)); - rc = -1; - break; + goto out; } + + + rc = 0; +out: + while (first) { + tmp = first->next; + free(first); + first = tmp; } - free(buf); return rc; } @@ -32,6 +32,13 @@ struct line_buf { struct line_buf *next; }; +/* struct for linked list of byte buffers in tail_pipe_bytes */ +struct char_buf { + char buf[BUFSIZ]; + size_t n_bytes; + struct char_buf *next; +}; + #define IS_PIPELIKE(mode) \ (S_ISFIFO(mode) || S_ISSOCK(mode)) |