diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-05-24 20:47:18 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-05-24 20:47:18 +0000 |
| commit | 8e2c9e1518d42320ebd4b3ff09220d79a199e8ff (patch) | |
| tree | ee565d0dbcbca18b33720aabc334d55ee39151da /miscutils | |
| parent | e94a87134d2c78d3a1df39605d1f30d928a592a5 (diff) | |
| download | busybox-w32-8e2c9e1518d42320ebd4b3ff09220d79a199e8ff.tar.gz busybox-w32-8e2c9e1518d42320ebd4b3ff09220d79a199e8ff.tar.bz2 busybox-w32-8e2c9e1518d42320ebd4b3ff09220d79a199e8ff.zip | |
inotify: new applet by Vladimir Dronnikov <dronnikov AT gmail.com>
function old new delta
inotifyd_main - 453 +453
packed_usage 24246 24450 +204
inotify_add_watch - 47 +47
inotify_init - 29 +29
mask_names - 13 +13
signal_handler 130 140 +10
applet_names 1859 1868 +9
applet_main 1132 1136 +4
applet_nameofs 566 568 +2
signalled 1 2 +1
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/Config.in | 6 | ||||
| -rw-r--r-- | miscutils/Kbuild | 1 | ||||
| -rw-r--r-- | miscutils/inotifyd.c | 152 |
3 files changed, 159 insertions, 0 deletions
diff --git a/miscutils/Config.in b/miscutils/Config.in index dffde34db..c7dbee899 100644 --- a/miscutils/Config.in +++ b/miscutils/Config.in | |||
| @@ -222,6 +222,12 @@ config FBSPLASH | |||
| 222 | "NN" (ASCII decimal number) - percentage to show on progress bar | 222 | "NN" (ASCII decimal number) - percentage to show on progress bar |
| 223 | "exit" - well you guessed it | 223 | "exit" - well you guessed it |
| 224 | 224 | ||
| 225 | config INOTIFYD | ||
| 226 | bool "inotifyd" | ||
| 227 | default n | ||
| 228 | help | ||
| 229 | Simple inotify daemon. Reports filesystem changes. Requires kernel >= 2.6.13 | ||
| 230 | |||
| 225 | config LAST | 231 | config LAST |
| 226 | bool "last" | 232 | bool "last" |
| 227 | default n | 233 | default n |
diff --git a/miscutils/Kbuild b/miscutils/Kbuild index 96e754e1b..c12b12d42 100644 --- a/miscutils/Kbuild +++ b/miscutils/Kbuild | |||
| @@ -16,6 +16,7 @@ lib-$(CONFIG_DEVFSD) += devfsd.o | |||
| 16 | lib-$(CONFIG_EJECT) += eject.o | 16 | lib-$(CONFIG_EJECT) += eject.o |
| 17 | lib-$(CONFIG_FBSPLASH) += fbsplash.o | 17 | lib-$(CONFIG_FBSPLASH) += fbsplash.o |
| 18 | lib-$(CONFIG_HDPARM) += hdparm.o | 18 | lib-$(CONFIG_HDPARM) += hdparm.o |
| 19 | lib-$(CONFIG_INOTIFYD) += inotifyd.o | ||
| 19 | lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o | 20 | lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o |
| 20 | lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o | 21 | lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o |
| 21 | lib-$(CONFIG_LESS) += less.o | 22 | lib-$(CONFIG_LESS) += less.o |
diff --git a/miscutils/inotifyd.c b/miscutils/inotifyd.c new file mode 100644 index 000000000..0d7ad2a9d --- /dev/null +++ b/miscutils/inotifyd.c | |||
| @@ -0,0 +1,152 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | ||
| 2 | /* | ||
| 3 | * simple inotify daemon | ||
| 4 | * reports filesystem changes via userspace agent | ||
| 5 | * | ||
| 6 | * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com> | ||
| 7 | * | ||
| 8 | * Licensed under GPLv2, see file LICENSE in this tarball for details. | ||
| 9 | */ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * Use as follows: | ||
| 13 | * # inotifyd /user/space/agent dir/or/file/being/watched[:mask] ... | ||
| 14 | * | ||
| 15 | * When a filesystem event matching the specified mask is occured on specified file (or directory) | ||
| 16 | * a userspace agent is spawned and given the following parameters: | ||
| 17 | * $1. actual event(s) | ||
| 18 | * $2. file (or directory) name | ||
| 19 | * $3. name of subfile (if any), in case of watching a directory | ||
| 20 | * | ||
| 21 | * E.g. inotifyd ./dev-watcher /dev:n | ||
| 22 | * | ||
| 23 | * ./dev-watcher can be, say: | ||
| 24 | * #!/bin/sh | ||
| 25 | * echo "We have new device in here! Hello, $3!" | ||
| 26 | * | ||
| 27 | * See below for mask names explanation. | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include "libbb.h" | ||
| 31 | #include <linux/inotify.h> | ||
| 32 | |||
| 33 | static volatile smallint signalled; | ||
| 34 | |||
| 35 | static void signal_handler(int signo) | ||
| 36 | { | ||
| 37 | signalled = signo; | ||
| 38 | } | ||
| 39 | |||
| 40 | static const char mask_names[] ALIGN1 = | ||
| 41 | "a" // 0x00000001 File was accessed | ||
| 42 | "c" // 0x00000002 File was modified | ||
| 43 | "e" // 0x00000004 Metadata changed | ||
| 44 | "w" // 0x00000008 Writtable file was closed | ||
| 45 | "0" // 0x00000010 Unwrittable file closed | ||
| 46 | "r" // 0x00000020 File was opened | ||
| 47 | "m" // 0x00000040 File was moved from X | ||
| 48 | "y" // 0x00000080 File was moved to Y | ||
| 49 | "n" // 0x00000100 Subfile was created | ||
| 50 | "d" // 0x00000200 Subfile was deleted | ||
| 51 | "D" // 0x00000400 Self was deleted | ||
| 52 | "M" // 0x00000800 Self was moved | ||
| 53 | ; | ||
| 54 | |||
| 55 | extern int inotify_init(void); | ||
| 56 | extern int inotify_add_watch(int fd, const char *path, uint32_t mask); | ||
| 57 | |||
| 58 | int inotifyd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
| 59 | int inotifyd_main(int argc ATTRIBUTE_UNUSED, char **argv) | ||
| 60 | { | ||
| 61 | unsigned mask = IN_ALL_EVENTS; // assume we want all events | ||
| 62 | struct pollfd pfd; | ||
| 63 | char **watched = ++argv; // watched name list | ||
| 64 | const char *args[] = { *argv, NULL, NULL, NULL, NULL }; | ||
| 65 | |||
| 66 | // sanity check: agent and at least one watch must be given | ||
| 67 | if (!argv[1]) | ||
| 68 | bb_show_usage(); | ||
| 69 | |||
| 70 | // open inotify | ||
| 71 | pfd.fd = inotify_init(); | ||
| 72 | if (pfd.fd < 0) | ||
| 73 | bb_perror_msg_and_die("no kernel support"); | ||
| 74 | |||
| 75 | // setup watched | ||
| 76 | while (*++argv) { | ||
| 77 | char *path = *argv; | ||
| 78 | char *masks = strchr(path, ':'); | ||
| 79 | int wd; // watch descriptor | ||
| 80 | // if mask is specified -> | ||
| 81 | if (masks) { | ||
| 82 | *masks = '\0'; // split path and mask | ||
| 83 | // convert mask names to mask bitset | ||
| 84 | mask = 0; | ||
| 85 | while (*++masks) { | ||
| 86 | int i = strchr(mask_names, *masks) - mask_names; | ||
| 87 | if (i >= 0) { | ||
| 88 | mask |= (1 << i); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | } | ||
| 92 | // add watch | ||
| 93 | wd = inotify_add_watch(pfd.fd, path, mask); | ||
| 94 | if (wd < 0) { | ||
| 95 | bb_perror_msg_and_die("add watch (%s) failed", path); | ||
| 96 | // } else { | ||
| 97 | // bb_error_msg("added %d [%s]:%4X", wd, path, mask); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | // setup signals | ||
| 102 | bb_signals(0 | ||
| 103 | + (1 << SIGHUP) | ||
| 104 | + (1 << SIGINT) | ||
| 105 | + (1 << SIGTERM) | ||
| 106 | + (1 << SIGPIPE) | ||
| 107 | , signal_handler); | ||
| 108 | |||
| 109 | // do watch | ||
| 110 | |||
| 111 | // pfd.fd = fd; | ||
| 112 | pfd.events = POLLIN; | ||
| 113 | |||
| 114 | while (!signalled && poll(&pfd, 1, -1) > 0) { | ||
| 115 | ssize_t len; | ||
| 116 | void *buf; | ||
| 117 | struct inotify_event *ie; | ||
| 118 | |||
| 119 | // read out all pending events | ||
| 120 | xioctl(pfd.fd, FIONREAD, &len); | ||
| 121 | #define eventbuf bb_common_bufsiz1 | ||
| 122 | ie = buf = (len <= sizeof(eventbuf)) ? eventbuf : xmalloc(len); | ||
| 123 | len = full_read(pfd.fd, buf, len); | ||
| 124 | // process events. N.B. events may vary in length | ||
| 125 | while (len > 0) { | ||
| 126 | int i; | ||
| 127 | char events[12]; | ||
| 128 | char *s = events; | ||
| 129 | unsigned m = ie->mask; | ||
| 130 | |||
| 131 | for (i = 0; i < 12; ++i, m >>= 1) { | ||
| 132 | if (m & 1) { | ||
| 133 | *s++ = mask_names[i]; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | *s = '\0'; | ||
| 137 | // bb_error_msg("exec %s %08X\t%s\t%s\t%s", agent, ie->mask, events, watched[ie->wd], ie->len ? ie->name : ""); | ||
| 138 | args[1] = events; | ||
| 139 | args[2] = watched[ie->wd]; | ||
| 140 | args[3] = ie->len ? ie->name : NULL; | ||
| 141 | xspawn((char **)args); | ||
| 142 | // next event | ||
| 143 | i = sizeof(struct inotify_event) + ie->len; | ||
| 144 | len -= i; | ||
| 145 | ie = (void*)((char*)ie + i); | ||
| 146 | } | ||
| 147 | if (eventbuf != buf) | ||
| 148 | free(buf); | ||
| 149 | } | ||
| 150 | |||
| 151 | return EXIT_SUCCESS; | ||
| 152 | } | ||
