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 <unistd.h>
      7 #include <sys/ioctl.h>
      8 #include <sys/inotify.h>
      9 #include <errno.h>
     10 
     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