| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 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 |  | 
 | 10 | int 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 | } |