#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[512]; ssize_t read_len; char *display_name; int buflen; strcpy(filename, file_names[event->wd + id_offset]); if(event->len) { strcat(filename, "/"); strcat(filename, event->name); } 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); } if(event_count && --event_count == 0) return 0; event_size = sizeof(*event) + event->len; res -= event_size; event_pos += event_size; } } return 0; }