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