summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2014-11-28 15:17:16 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2014-11-28 15:17:16 -0500
commitd8c48a5aae8f3561cec14f7f08c35fc3619ef00a (patch)
treec0c11cefff91cb8d34deb1091d4d02a1bb71f3d0 /common
parentc9618dfe442305531ee6cab9660333f4a697e094 (diff)
foo
Diffstat (limited to 'common')
-rw-r--r--common/inotify_helpers.c92
-rw-r--r--common/inotify_helpers.h80
2 files changed, 172 insertions, 0 deletions
diff --git a/common/inotify_helpers.c b/common/inotify_helpers.c
new file mode 100644
index 0000000..0aac023
--- /dev/null
+++ b/common/inotify_helpers.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "inotify_helpers.h"
+
+static
+const char *in_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 */
+ "<invalid-12>", // 12
+ /* events sent by the kernel */
+ "IN_UNMOUNT", // 13
+ "IN_Q_OVERFLOW", // 14
+ "IN_IGNORED", // 15
+ /* gap */
+ "<invalid-16>", // 16
+ "<invalid-17>", // 17
+ "<invalid-18>", // 18
+ "<invalid-19>", // 19
+ "<invalid-20>", // 20
+ "<invalid-21>", // 21
+ "<invalid-22>", // 22
+ "<invalid-23>", // 23
+ /* special flags */
+ "IN_ONLYDIR", // 24
+ "IN_DONT_FOLLOW", // 25
+ "IN_EXCL_UNLINK", // 26
+ "<invalid-27>", // 27
+ "<invalid-28>", // 28
+ "IN_MASK_ADD", // 29
+ "IN_ISDIR", // 30
+ "IN_ONESHOT", // 31
+};
+
+char *inotify_mask2str(uint32 mask);
+int inotify_print_event(FILE *file, struct inotify_event *event);
+
+
+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;
+}
+
+
+char *inotify_mask2str(uint32_t mask) {
+ struct strbuf out = { NULL, 0, 0 };
+ for (size_t i = 0; i < sizeof(in_bits)/sizeof(in_bits[0]); i++) {
+ if (mask & (1 << i)) {
+ if (out.len > 0)
+ strbufcat(&out, ", ");
+ strbufcat(&out, in_bits[i]);
+ }
+ }
+ return out.str;
+}
+
+int inotify_print_event(struct inotify_event *event) {
+ return printf("wd:%d\n"
+ "\tmask:[%s]\n"
+ "\tcookie:%u\n"
+ "\tlen:%u\n"
+ "\tname:%s\n",
+ event->wd,
+ mask2str(event->mask),
+ event->cookie,
+ event->len,
+ event->len > 0 ? event->name : "");
+}
diff --git a/common/inotify_helpers.h b/common/inotify_helpers.h
new file mode 100644
index 0000000..5bb7647
--- /dev/null
+++ b/common/inotify_helpers.h
@@ -0,0 +1,80 @@
+/* inotify_helper.h - Simple iteration for inotify events
+ *
+ * Copyright (C) 2014 Luke Shumaker
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* The usage is pretty simple:
+ *
+ * int my_filedesc = inotify_init();
+ * ...
+ * struct inotify_event *my_event;
+ * for (INOTIFY_ITR(my_filedesc, my_event)) {
+ * ...
+ * }
+ *
+ * Easy, right?
+ */
+
+#ifndef _INOTIFY_HELPER_H
+#define _INOTIFY_HELPER_H
+
+#include <sys/inotify.h>
+#include <limits.h> /* for NAME_MAX */
+#include <string.h> /* for memset(3) */
+#include <unistd.h> /* for read(3) */
+
+struct _inotify_buffer {
+ ssize_t len;
+ ssize_t pos;
+ char dat[sizeof(struct inotify_event)+NAME_MAX+1];
+};
+
+#define _INOTIFY_ITR_EVENT(BUF) \
+ ((struct inotify_event *)&((BUF).dat[(BUF).pos]))
+#define _INOTIFY_ITR_EVENT_SIZE(BUF) \
+ (sizeof(struct inotify_event) + _INOTIFY_ITR_EVENT(BUF)->len)
+
+#define _INOTIFY_ITR_INIT(FD, BUF, EVENT) \
+ struct _inotify_buffer BUF = ({ \
+ struct _inotify_buffer tmp; \
+ memset(&tmp, 0, sizeof(tmp)); \
+ do { \
+ tmp.len = read(FD, tmp.dat, sizeof(tmp.dat)); \
+ } while (tmp.len == 0); \
+ EVENT = (struct inotify_event *)&BUF; \
+ tmp; \
+ })
+#define _INOTIFY_ITR_CHECK(FD, BUF, EVENT) \
+ BUF.len > -1
+#define _INOTIFY_ITR_UPDATE(FD, BUF, EVENT) \
+ EVENT = ({ \
+ if (BUF.len-(BUF.pos+_INOTIFY_ITR_EVENT_SIZE(BUF)) < 1) { \
+ do { \
+ BUF.len = read(FD, BUF.dat, sizeof(BUF.dat)); \
+ } while (BUF.len == 0); \
+ BUF.pos = 0; \
+ } else { \
+ BUF.pos += _INOTIFY_ITR_EVENT_SIZE(BUF); \
+ } \
+ _INOTIFY_ITR_EVENT(BUF); \
+ })
+
+#define INOTIFY_ITR(FD, EVENT) \
+ _INOTIFY_ITR_INIT(FD, _buf, EVENT); \
+ _INOTIFY_ITR_CHECK(FD, _buf, EVENT); \
+ _INOTIFY_ITR_UPDATE(FD, _buf, EVENT)
+
+#endif