+static void
+without_inotify_wait(int timeout)
+{
+ timeout *= 10;
+ halfdelay((timeout > 255) ? 255 : timeout);
+}
+#ifdef CONFIG_INOTIFY
+
+#include <sys/inotify.h>
+
+static void
+inotify_cm_init(void)
+{
+ if (!inotify_active) return;
+ inotify_fd = inotify_init();
+ if (inotify_fd < 0)
+ die("Inotify init faild.\n");
+}
+
+static void
+inotify_add_mbox(struct mbox * b)
+{
+ if (!inotify_active) return;
+ b->inotify_status = INOTIFY_ON;
+ char *path = xmalloc(strlen(b->path)+100);
+ struct stat st;
+ if (stat(b->path, &st) < 0)
+ {
+ debug("Get stat of %s faild\n", b->path);
+ return;
+ }
+ if (S_ISREG(st.st_mode))
+ {
+ // Regular mailbox
+ sprintf(path, "%s", b->path);
+ if (inotify_add_watch(inotify_fd, path, IN_MOVED_TO | IN_MOVED_FROM | IN_DELETE | IN_CLOSE_WRITE ) < 0)
+ {
+ debug("Inotify add %s faild\n", path);
+ b->inotify_status = INOTIFY_ERROR;
+ }
+ else
+ debug("Inotify add %s OK\n", path);
+ }
+ else if (S_ISDIR(st.st_mode))
+ {
+ // Maildir
+ char *watch_dir[] = {"cur", "new"};
+ for (int i=0; i < (int)(sizeof(watch_dir)/sizeof(*watch_dir)); i++)
+ {
+ sprintf(path, "%s/%s", b->path, watch_dir[i]);
+ if (inotify_add_watch(inotify_fd, path, IN_MOVED_TO | IN_MOVED_FROM | IN_DELETE | IN_CLOSE_WRITE ) < 0)
+ {
+ debug("Inotify add %s faild\n", path);
+ b->inotify_status = INOTIFY_ERROR;
+ }
+ }
+ }
+ else
+ {
+ debug("neither file nor directory\n");
+ b->inotify_status = INOTIFY_ERROR;
+ return;
+ }
+ free(path);
+}
+
+static void
+inotify_delete_mbox(struct mbox * b)
+{
+ (void)b;
+ // TODO
+}
+
+static bool // true if inotify change detected
+inotify_wait(int timeout)
+{
+ if(!inotify_active)
+ {
+ without_inotify_wait(timeout);
+ return 0;
+ }
+
+ bool inotify_change = 0;
+
+ struct timeval tv;
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ while (true)
+ {
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(0, &rfds);
+ FD_SET(inotify_fd, &rfds);
+
+ debug("Select begin (timeout %d %d)\n", tv.tv_sec, tv.tv_usec);
+ int ret = select(1+inotify_fd, &rfds, NULL, NULL, &tv);
+ debug("Select end\n");
+ if (ret>0 && FD_ISSET(0, &rfds))
+ return inotify_change;
+ if (ret>0 && FD_ISSET(inotify_fd, &rfds))
+ {
+ debug("Read notify begin\n");
+ char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ ssize_t len = read(inotify_fd, buf, sizeof(buf));
+ if (len == -1 && errno != EAGAIN)
+ perror ("read inotify faild");
+ inotify_change = 1;
+ debug("Read notify end\n");
+ }
+ else
+ return inotify_change;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ }
+}
+
+#else
+
+static void
+inotify_cm_init(void){}
+
+static void
+inotify_add_mbox(struct mbox *){}
+
+static void
+inotify_delete_mbox(struct mbox *){}
+
+static bool
+inotify_wait(int timeout)
+{
+ without_inotify_wait(timeout);
+ return 0;
+}
+
+#endif
+