127 lines
3.2 KiB
C
127 lines
3.2 KiB
C
/* inotifyd.c - inotify daemon.
|
|
*
|
|
* Copyright 2013 Ashwini Kumar <ak.ashwini1981@gmail.com>
|
|
* Copyright 2013 Kyungwan Han <asura321@gmail.com>
|
|
*
|
|
* No Standard.
|
|
|
|
USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
|
config INOTIFYD
|
|
bool "inotifyd"
|
|
default y
|
|
help
|
|
usage: inotifyd PROG FILE[:MASK] ...
|
|
|
|
When a filesystem event matching MASK occurs to a FILE, run PROG as:
|
|
|
|
PROG EVENTS FILE [DIRFILE]
|
|
|
|
If PROG is "-" events are sent to stdout.
|
|
|
|
This file is:
|
|
a accessed c modified e metadata change w closed (writable)
|
|
r opened D deleted M moved 0 closed (unwritable)
|
|
u unmounted o overflow x unwatchable
|
|
|
|
A file in this directory is:
|
|
m moved in y moved out n created d deleted
|
|
|
|
When x event happens for all FILEs, inotifyd exits (after waiting for PROG).
|
|
*/
|
|
|
|
#define FOR_inotifyd
|
|
#include "toys.h"
|
|
#include <sys/inotify.h>
|
|
|
|
void inotifyd_main(void)
|
|
{
|
|
struct pollfd fds;
|
|
char *prog_args[5], **ss = toys.optargs;
|
|
char *masklist ="acew0rmyndDM uox";
|
|
|
|
fds.events = POLLIN;
|
|
|
|
*prog_args = *toys.optargs;
|
|
prog_args[4] = 0;
|
|
if ((fds.fd = inotify_init()) == -1) perror_exit(0);
|
|
|
|
// Track number of watched files. First one was program to run.
|
|
toys.optc--;
|
|
|
|
while (*++ss) {
|
|
char *path = *ss, *masks = strchr(*ss, ':');
|
|
int i, mask = 0;
|
|
|
|
if (!masks) mask = 0xfff; // default to all
|
|
else{
|
|
*masks++ = 0;
|
|
for (*masks++ = 0; *masks; masks++) {
|
|
i = stridx(masklist, *masks);;
|
|
if (i == -1) error_exit("bad mask '%c'", *masks);
|
|
mask |= 1<<i;
|
|
}
|
|
}
|
|
|
|
// This returns increasing numbers starting from 1, which coincidentally
|
|
// is the toys.optargs position of the file. (0 is program to run.)
|
|
if (inotify_add_watch(fds.fd, path, mask) < 0) perror_exit_raw(path);
|
|
}
|
|
|
|
for (;;) {
|
|
int ret = 0, len;
|
|
void *buf = 0;
|
|
struct inotify_event *event;
|
|
|
|
// Read next event(s)
|
|
ret = poll(&fds, 1, -1);
|
|
if (ret < 0 && errno == EINTR) continue;
|
|
if (ret <= 0) break;
|
|
xioctl(fds.fd, FIONREAD, &len);
|
|
event = buf = xmalloc(len);
|
|
len = readall(fds.fd, buf, len);
|
|
|
|
// Loop through set of events.
|
|
for (;;) {
|
|
int left = len - (((char *)event)-(char *)buf),
|
|
size = sizeof(struct inotify_event);
|
|
|
|
// Don't dereference event if ->len is off end of bufer
|
|
if (left >= size) size += event->len;
|
|
if (left < size) break;
|
|
|
|
if (event->mask) {
|
|
char *s = toybuf, *m;
|
|
|
|
for (m = masklist; *m; m++)
|
|
if (event->mask & (1<<(m-masklist))) *s++ = *m;
|
|
*s = 0;
|
|
|
|
if (**prog_args == '-' && !prog_args[0][1]) {
|
|
xprintf("%s\t%s\t%s\n" + 3*!event->len, toybuf,
|
|
toys.optargs[event->wd], event->name);
|
|
} else {
|
|
prog_args[1] = toybuf;
|
|
prog_args[2] = toys.optargs[event->wd];
|
|
prog_args[3] = event->len ? event->name : 0;
|
|
xrun(prog_args);
|
|
}
|
|
|
|
if (event->mask & IN_IGNORED) {
|
|
if (--toys.optc <= 0) {
|
|
free(buf);
|
|
|
|
goto done;
|
|
}
|
|
inotify_rm_watch(fds.fd, event->wd);
|
|
}
|
|
}
|
|
event = (void*)(size + (char*)event);
|
|
}
|
|
free(buf);
|
|
}
|
|
|
|
done:
|
|
toys.exitval = !!toys.signal;
|
|
}
|