Home | History | Annotate | Download | only in toolbox
      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 }
    145