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