inotifyd.c revision e70eea41eeed05e0ac938a6aceab27c918090fde
16958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma/* inotifyd.c - inotify daemon. 26958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma * 36958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma * Copyright 2013 Ashwini Kumar <ak.ashwini1981@gmail.com> 46958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma * Copyright 2013 Kyungwan Han <asura321@gmail.com> 56958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma * 66958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma * No Standard. 76958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 86958429d84cff06fefdc898d837a71c239f1e214Ashwini SharmaUSE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN)) 96958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 106958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharmaconfig INOTIFYD 116958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma bool "inotifyd" 12e70eea41eeed05e0ac938a6aceab27c918090fdeRob Landley default y 136958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma help 1401a806ff123aa091e0d41023432dfe2c0173a62dRob Landley usage: inotifyd PROG FILE[:MASK] ... 156958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 1601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley When a filesystem event matching MASK occurs to a FILE, run PROG as: 1701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 1801a806ff123aa091e0d41023432dfe2c0173a62dRob Landley PROG EVENTS FILE [DIRFILE] 1901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 20eeb3541652110c35e9c434565a2c509687bb6697Rob Landley If PROG is "-" events are sent to stdout. 21eeb3541652110c35e9c434565a2c509687bb6697Rob Landley 2201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley This file is: 2301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley a accessed c modified e metadata change w closed (writable) 2401a806ff123aa091e0d41023432dfe2c0173a62dRob Landley r opened D deleted M moved 0 closed (unwritable) 2501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley u unmounted o overflow x unwatchable 2601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 2701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley A file in this directory is: 2801a806ff123aa091e0d41023432dfe2c0173a62dRob Landley m moved in y moved out n created d deleted 296958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 3001a806ff123aa091e0d41023432dfe2c0173a62dRob Landley When x event happens for all FILEs, inotifyd exits (after waiting for PROG). 316958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma*/ 3201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 336958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma#define FOR_inotifyd 346958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma#include "toys.h" 356958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma#include <sys/inotify.h> 366958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 3701a806ff123aa091e0d41023432dfe2c0173a62dRob Landleyvoid inotifyd_main(void) 386958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma{ 3901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley struct pollfd fds; 4001a806ff123aa091e0d41023432dfe2c0173a62dRob Landley char *prog_args[5], **ss = toys.optargs; 4101a806ff123aa091e0d41023432dfe2c0173a62dRob Landley char *masklist ="acew0rmyndDM uox"; 426958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 4301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley fds.events = POLLIN; 446958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 4501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley *prog_args = *toys.optargs; 4601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley prog_args[4] = 0; 4701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if ((fds.fd = inotify_init()) == -1) perror_exit(0); 486958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 4901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley // Track number of watched files. First one was program to run. 5001a806ff123aa091e0d41023432dfe2c0173a62dRob Landley toys.optc--; 5101a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 5201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley while (*++ss) { 5301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley char *path = *ss, *masks = strchr(*ss, ':'); 5401a806ff123aa091e0d41023432dfe2c0173a62dRob Landley int i, mask = 0; 5501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 5601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (!masks) mask = 0xfff; // default to all 5701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley else{ 5801a806ff123aa091e0d41023432dfe2c0173a62dRob Landley *masks++ = 0; 5901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley for (*masks++ = 0; *masks; masks++) { 6001a806ff123aa091e0d41023432dfe2c0173a62dRob Landley i = stridx(masklist, *masks);; 6101a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (i == -1) error_exit("bad mask '%c'", *masks); 6201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley mask |= 1<<i; 636958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 646958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 6501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 6601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley // This returns increasing numbers starting from 1, which coincidentally 6701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley // is the toys.optargs position of the file. (0 is program to run.) 6801a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (inotify_add_watch(fds.fd, path, mask) < 0) perror_exit("%s", path); 696958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 706958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 7101a806ff123aa091e0d41023432dfe2c0173a62dRob Landley for (;;) { 7201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley int ret = 0, len; 7301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley void *buf = 0; 746958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma struct inotify_event *event; 756958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma 7601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley // Read next event(s) 776958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma ret = poll(&fds, 1, -1); 7801a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (ret < 0 && errno == EINTR) continue; 796958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma if (ret <= 0) break; 8001a806ff123aa091e0d41023432dfe2c0173a62dRob Landley xioctl(fds.fd, FIONREAD, &len); 8101a806ff123aa091e0d41023432dfe2c0173a62dRob Landley event = buf = xmalloc(len); 8201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley len = readall(fds.fd, buf, len); 8301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 8401a806ff123aa091e0d41023432dfe2c0173a62dRob Landley // Loop through set of events. 8501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley for (;;) { 8601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley int left = len - (((char *)event)-(char *)buf), 8701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley size = sizeof(struct inotify_event); 8801a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 8901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley // Don't dereference event if ->len is off end of bufer 9001a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (left >= size) size += event->len; 9101a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (left < size) break; 9201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 9301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (event->mask) { 9401a806ff123aa091e0d41023432dfe2c0173a62dRob Landley char *s = toybuf, *m; 9501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 9601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley for (m = masklist; *m; m++) 9701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (event->mask & (1<<(m-masklist))) *s++ = *m; 9801a806ff123aa091e0d41023432dfe2c0173a62dRob Landley *s = 0; 9901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 10001a806ff123aa091e0d41023432dfe2c0173a62dRob Landley if (**prog_args == '-' && !prog_args[0][1]) { 10101a806ff123aa091e0d41023432dfe2c0173a62dRob Landley xprintf("%s\t%s\t%s\n" + 3*!event->len, toybuf, 10201a806ff123aa091e0d41023432dfe2c0173a62dRob Landley toys.optargs[event->wd], event->name); 1036958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } else { 10401a806ff123aa091e0d41023432dfe2c0173a62dRob Landley prog_args[1] = toybuf; 10501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley prog_args[2] = toys.optargs[event->wd]; 10601a806ff123aa091e0d41023432dfe2c0173a62dRob Landley prog_args[3] = event->len ? event->name : 0; 10701a806ff123aa091e0d41023432dfe2c0173a62dRob Landley xpclose(xpopen(prog_args, 0), 0); 1086958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 10901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 1106958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma if (event->mask & IN_IGNORED) { 1116958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma if (--toys.optc <= 0) { 1126958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma free(buf); 11301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 1146958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma goto done; 1156958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 1166958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma inotify_rm_watch(fds.fd, event->wd); 1176958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 1186958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 11901a806ff123aa091e0d41023432dfe2c0173a62dRob Landley event = (void*)(size + (char*)event); 1206958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 1216958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma free(buf); 1226958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma } 12301a806ff123aa091e0d41023432dfe2c0173a62dRob Landley 1246958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharmadone: 12501a806ff123aa091e0d41023432dfe2c0173a62dRob Landley toys.exitval = !!toys.signal; 1266958429d84cff06fefdc898d837a71c239f1e214Ashwini Sharma} 127