notify.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <stdint.h>
5#include <fcntl.h>
6#include <sys/ioctl.h>
7#include <sys/inotify.h>
8#include <errno.h>
9
10int notify_main(int argc, char *argv[])
11{
12    int c;
13    int nfd, ffd;
14    int res;
15	char event_buf[512];
16    struct inotify_event *event;
17	int event_mask = IN_ALL_EVENTS;
18    int event_count = 1;
19	int print_files = 0;
20	int verbose = 2;
21	int width = 80;
22	char **file_names;
23	int file_count;
24	int id_offset = 0;
25	int i;
26	char *buf;
27
28    do {
29        c = getopt(argc, argv, "m:c:pv:w:");
30        if (c == EOF)
31            break;
32        switch (c) {
33        case 'm':
34            event_mask = strtol(optarg, NULL, 0);
35            break;
36        case 'c':
37            event_count = atoi(optarg);
38            break;
39		case 'p':
40			print_files = 1;
41			break;
42        case 'v':
43            verbose = atoi(optarg);
44            break;
45        case 'w':
46            width = atoi(optarg);
47            break;
48        case '?':
49            fprintf(stderr, "%s: invalid option -%c\n",
50                argv[0], optopt);
51            exit(1);
52        }
53    } while (1);
54
55    if (argc <= optind) {
56        fprintf(stderr, "Usage: %s [-m eventmask] [-c count] [-p] [-v verbosity] path [path ...]\n", argv[0]);
57		return 1;
58    }
59
60    nfd = inotify_init();
61    if(nfd < 0) {
62        fprintf(stderr, "inotify_init failed, %s\n", strerror(errno));
63        return 1;
64    }
65	file_names = argv + optind;
66	file_count = argc - optind;
67	for(i = 0; i < file_count; i++) {
68		res = inotify_add_watch(nfd, file_names[i], event_mask);
69		if(res < 0) {
70	        fprintf(stderr, "inotify_add_watch failed for %s, %s\n", file_names[i], strerror(errno));
71			return 1;
72		}
73		if(i == 0)
74			id_offset = -res;
75		if(res + id_offset != i) {
76			fprintf(stderr, "%s got unexpected id %d instead of %d\n", file_names[i], res, i);
77			return 1;
78		}
79	}
80
81	buf = malloc(width + 2);
82
83    while(1) {
84		int event_pos = 0;
85        res = read(nfd, event_buf, sizeof(event_buf));
86        if(res < (int)sizeof(*event)) {
87			if(errno == EINTR)
88				continue;
89            fprintf(stderr, "could not get event, %s\n", strerror(errno));
90            return 1;
91        }
92		//printf("got %d bytes of event information\n", res);
93		while(res >= (int)sizeof(*event)) {
94			int event_size;
95			event = (struct inotify_event *)(event_buf + event_pos);
96			if(verbose >= 2)
97		        printf("%s: %08x %08x \"%s\"\n", file_names[event->wd + id_offset], event->mask, event->cookie, event->len ? event->name : "");
98			else if(verbose >= 2)
99		        printf("%s: %08x \"%s\"\n", file_names[event->wd + id_offset], event->mask, event->len ? event->name : "");
100			else if(verbose >= 1)
101		        printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
102			if(print_files && (event->mask & IN_MODIFY)) {
103				char filename[512];
104				ssize_t read_len;
105				char *display_name;
106				int buflen;
107				strcpy(filename, file_names[event->wd + id_offset]);
108				if(event->len) {
109					strcat(filename, "/");
110					strcat(filename, event->name);
111				}
112				ffd = open(filename, O_RDONLY);
113				display_name = (verbose >= 2 || event->len == 0) ? filename : event->name;
114				buflen = width - strlen(display_name);
115				read_len = read(ffd, buf, buflen);
116				if(read_len > 0) {
117					if(read_len < buflen && buf[read_len-1] != '\n') {
118						buf[read_len] = '\n';
119						read_len++;
120					}
121					if(read_len == buflen) {
122						buf[--read_len] = '\0';
123						buf[--read_len] = '\n';
124						buf[--read_len] = '.';
125						buf[--read_len] = '.';
126						buf[--read_len] = '.';
127					}
128					else {
129						buf[read_len] = '\0';
130					}
131					printf("%s: %s", display_name, buf);
132				}
133				close(ffd);
134			}
135	        if(event_count && --event_count == 0)
136	            return 0;
137			event_size = sizeof(*event) + event->len;
138			res -= event_size;
139			event_pos += event_size;
140		}
141    }
142
143    return 0;
144}
145