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