blob: 8ce346c56d1ad11fc8c8f21224967ff89d213f07 [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/inotify.h>
#include <errno.h>
int notify_main(int argc, char *argv[])
{
int c;
int nfd, ffd;
int res;
char event_buf[512];
struct inotify_event *event;
int event_mask = IN_ALL_EVENTS;
int event_count = 1;
int print_files = 0;
int verbose = 2;
int width = 80;
char **file_names;
int file_count;
int id_offset = 0;
int i;
char *buf;
do {
c = getopt(argc, argv, "m:c:pv:w:");
if (c == EOF)
break;
switch (c) {
case 'm':
event_mask = strtol(optarg, NULL, 0);
break;
case 'c':
event_count = atoi(optarg);
break;
case 'p':
print_files = 1;
break;
case 'v':
verbose = atoi(optarg);
break;
case 'w':
width = atoi(optarg);
break;
case '?':
fprintf(stderr, "%s: invalid option -%c\n",
argv[0], optopt);
exit(1);
}
} while (1);
if (argc <= optind) {
fprintf(stderr, "Usage: %s [-m eventmask] [-c count] [-p] [-v verbosity] path [path ...]\n", argv[0]);
return 1;
}
nfd = inotify_init();
if(nfd < 0) {
fprintf(stderr, "inotify_init failed, %s\n", strerror(errno));
return 1;
}
file_names = argv + optind;
file_count = argc - optind;
for(i = 0; i < file_count; i++) {
res = inotify_add_watch(nfd, file_names[i], event_mask);
if(res < 0) {
fprintf(stderr, "inotify_add_watch failed for %s, %s\n", file_names[i], strerror(errno));
return 1;
}
if(i == 0)
id_offset = -res;
if(res + id_offset != i) {
fprintf(stderr, "%s got unexpected id %d instead of %d\n", file_names[i], res, i);
return 1;
}
}
buf = malloc(width + 2);
while(1) {
int event_pos = 0;
res = read(nfd, event_buf, sizeof(event_buf));
if(res < (int)sizeof(*event)) {
if(errno == EINTR)
continue;
fprintf(stderr, "could not get event, %s\n", strerror(errno));
return 1;
}
//printf("got %d bytes of event information\n", res);
while(res >= (int)sizeof(*event)) {
int event_size;
event = (struct inotify_event *)(event_buf + event_pos);
if(verbose >= 2)
printf("%s: %08x %08x \"%s\"\n", file_names[event->wd + id_offset], event->mask, event->cookie, event->len ? event->name : "");
else if(verbose >= 2)
printf("%s: %08x \"%s\"\n", file_names[event->wd + id_offset], event->mask, event->len ? event->name : "");
else if(verbose >= 1)
printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
if(print_files && (event->mask & IN_MODIFY)) {
char* filename = file_names[event->wd + id_offset];
char* alloc_buf = NULL;
ssize_t read_len;
char *display_name;
int buflen;
if(event->len) {
if(asprintf(&alloc_buf, "%s/%s", filename, event->name) < 0) {
fprintf(stderr, "asprintf failed, %s\n", strerror(errno));
return 1;
}
filename = alloc_buf;
}
ffd = open(filename, O_RDONLY);
display_name = (verbose >= 2 || event->len == 0) ? filename : event->name;
buflen = width - strlen(display_name);
read_len = read(ffd, buf, buflen);
if(read_len > 0) {
if(read_len < buflen && buf[read_len-1] != '\n') {
buf[read_len] = '\n';
read_len++;
}
if(read_len == buflen) {
buf[--read_len] = '\0';
buf[--read_len] = '\n';
buf[--read_len] = '.';
buf[--read_len] = '.';
buf[--read_len] = '.';
}
else {
buf[read_len] = '\0';
}
printf("%s: %s", display_name, buf);
}
close(ffd);
free(alloc_buf);
}
if(event_count && --event_count == 0)
return 0;
event_size = sizeof(*event) + event->len;
res -= event_size;
event_pos += event_size;
}
}
return 0;
}