#include /* for strlen(3), memcpy(3) */ #include /* for printf(3) */ #include /* for realloc(3) */ #include /* for read(2) */ #include "inotify_helpers.h" struct strbuf { char *str; size_t len; size_t cap; }; static void strbufcat(struct strbuf *a, const char *b) { size_t blen = strlen(b); while (a->cap <= (a->len + blen)) { a->cap += 256; a->str = realloc(a->str, a->cap); } memcpy(&(a->str[a->len]), b, blen+1); a->len += blen; } static const char *in_mask_bits[] = { /* main */ "IN_ACCESS", // 0 "IN_MODIFY", // 1 "IN_ATTRIB", // 2 "IN_CLOSE_WRITE", // 3 "IN_CLOSE_NOWRITE", // 4 "IN_OPEN", // 5 "IN_MOVED_FROM", // 6 "IN_MOVED_TO", // 7 "IN_CREATE", // 8 "IN_DELETE", // 9 "IN_DELETE_SELF", // 10 "IN_MOVE_SELF", // 11 /* gap */ "", // 12 /* events sent by the kernel */ "IN_UNMOUNT", // 13 "IN_Q_OVERFLOW", // 14 "IN_IGNORED", // 15 /* gap */ "", // 16 "", // 17 "", // 18 "", // 19 "", // 20 "", // 21 "", // 22 "", // 23 /* special flags */ "IN_ONLYDIR", // 24 "IN_DONT_FOLLOW", // 25 "IN_EXCL_UNLINK", // 26 "", // 27 "", // 28 "IN_MASK_ADD", // 29 "IN_ISDIR", // 30 "IN_ONESHOT", // 31 }; char * inotify_mask2str(uint32_t mask) { struct strbuf out = { 0 }; for (size_t i = 0; i < sizeof(in_mask_bits)/sizeof(in_mask_bits[0]); i++) { if (mask & (1 << i)) { if (out.len > 0) strbufcat(&out, " | "); strbufcat(&out, in_mask_bits[i]); } } return out.str; } int inotify_print_event(struct inotify_event *event) { char *mask = inotify_mask2str(event->mask); int ret = printf("{\t.wd=%d;\n" "\t.mask=%s;\n" "\t.cookie=%u;\n" "\t.len=%u;\n" "\t.name=\"%s\"; }\n", event->wd, mask, event->cookie, event->len, event->len > 0 ? event->name : ""); free(mask); return ret; } #define EVENT_PTR(BUF) ((struct inotify_event *)&((BUF)->dat[(BUF)->pos])) #define EVENT_SIZE(BUF) (sizeof(struct inotify_event) + EVENT_PTR(BUF)->len) struct inotify_event * inotify_next_event_r(int fd, struct inotify_buffer *buf) { if (((ssize_t)(buf->len - buf->pos - sizeof(struct inotify_event)) > 0) && ((ssize_t)(buf->len - buf->pos - EVENT_SIZE(buf)) > 0)) { buf->pos += EVENT_SIZE(buf); } else { do { buf->len = read(fd, buf->dat, sizeof(buf->dat)); } while (buf->len == 0); buf->pos = 0; if (buf->len < 0) { return NULL; } } return EVENT_PTR(buf); } struct inotify_event * inotify_next_event(int fd) { static struct inotify_buffer buf = { 0 }; return inotify_next_event_r(fd, &buf); }