summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@xenon.tklauser.home>2006-08-12 21:27:09 +0200
committerTobias Klauser <tklauser@xenon.tklauser.home>2006-08-12 21:27:09 +0200
commit3c9d7963eec4c1a78583f70ba3a45b95e86064c9 (patch)
treeafa2629da176806e3f00cc5d564cecc73862419a
parent10f6e1b387eaea5f373b088c4d880e9c938a5871 (diff)
Introduce handling of ignored files
Files which are no longer available (e.g. moved, deleted) are marked as "ignore" and do no longer influence the tailing of other files.
-rw-r--r--inotail.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/inotail.c b/inotail.c
index 7b8c716..4baaa9e 100644
--- a/inotail.c
+++ b/inotail.c
@@ -57,6 +57,14 @@ static void usage(int status)
exit(status);
}
+static void setup_file(struct file_struct *f)
+{
+ f->fd = -1;
+ f->st_size = 0;
+ f->ignore = 0;
+ f->i_watch = -1;
+}
+
static void write_header(const char *filename)
{
static unsigned short first_file = 1;
@@ -159,7 +167,7 @@ static int tail_file(struct file_struct *f, int n_lines, char mode)
static int watch_files(struct file_struct *f, int n_files)
{
- int ifd, i;
+ int ifd, i, n_ignored = 0;
off_t offset;
struct inotify_event *inev;
char buf[sizeof(struct inotify_event) * 32]; /* Let's hope we don't get more than 32 events at a time */
@@ -171,14 +179,16 @@ static int watch_files(struct file_struct *f, int n_files)
}
for (i = 0; i < n_files; i++) {
- f[i].i_watch = inotify_add_watch(ifd, f[i].name,
+ if (!f[i].ignore)
+ f[i].i_watch = inotify_add_watch(ifd, f[i].name,
IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT);
- dprintf(" Watch (%d) added to '%s' (%d)\n", f[i].i_watch, f[i].name, i);
+ else
+ n_ignored++;
}
memset(&buf, 0, sizeof(buf));
- while (1) {
+ while (n_ignored < n_files) {
int len;
len = read(ifd, buf, sizeof(buf));
@@ -189,12 +199,14 @@ static int watch_files(struct file_struct *f, int n_files)
/* Which file has produced the event? */
for (i = 0; i < n_files; i++) {
- if (f[i].i_watch == inev->wd) {
+ if (!f[i].ignore && f[i].i_watch == inev->wd) {
fil = &f[i];
break;
}
}
+ /* XXX: Is it possible that no file in the list produced the event? */
+
if (inev->mask & IN_MODIFY) {
int block_size;
char fbuf[BUFFER_SIZE];
@@ -207,13 +219,15 @@ static int watch_files(struct file_struct *f, int n_files)
fil->fd = open(fil->name, O_RDONLY);
if (fil->fd < 0) {
+ fil->ignore = 1;
+ n_ignored++;
fprintf(stderr, "Error: Could not open file '%s' (%s)\n", f->name, strerror(errno));
- return -1;
}
if (fstat(fil->fd, &finfo) < 0) {
+ fil->ignore = 1;
+ n_ignored++;
fprintf(stderr, "Error: Could not stat file '%s' (%s)\n", f->name, strerror(errno));
- return -1;
}
fil->st_size = finfo.st_size;
@@ -242,23 +256,28 @@ static int watch_files(struct file_struct *f, int n_files)
}
if (inev->mask & IN_DELETE_SELF) {
+ fil->ignore = 1;
+ n_ignored++;
fprintf(stderr, "File '%s' deleted.\n", fil->name);
- return -1;
}
if (inev->mask & IN_MOVE_SELF) {
+ fil->ignore = 1;
+ n_ignored++;
fprintf(stderr, "File '%s' moved.\n", fil->name);
/* TODO: Try to follow file/fd */
- return -1;
}
if (inev->mask & IN_UNMOUNT) {
+ fil->ignore = 1;
+ n_ignored++;
fprintf(stderr, "Device containing file '%s' unmounted.\n", fil->name);
- return -1;
}
len -= sizeof(struct inotify_event) + inev->len;
inev = (struct inotify_event *) ((char *) inev + sizeof(struct inotify_event) + inev->len);
}
}
+
+ return -1;
}
int main(int argc, char **argv)
@@ -312,6 +331,7 @@ int main(int argc, char **argv)
files = malloc(n_files * sizeof(struct file_struct));
for (i = 0; i < n_files; i++) {
files[i].name = filenames[i];
+ setup_file(&files[i]);
ret = tail_file(&files[i], n_lines, mode);
if (ret < 0)
files[i].ignore = 1;