aboutsummaryrefslogtreecommitdiff
path: root/lib/notify.c
blob: a7993e2aed372634ca60ca799097f13d548d8381 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "toys.h"

static char **paths;
static int *fds;
static int count;

#ifdef __APPLE__

#include <sys/event.h>

static int kq = -1;

void notify_init(int max)
{
  if ((kq = kqueue()) == -1) perror_exit("kqueue");
  paths = xmalloc(max * sizeof(char *));
  fds = xmalloc(max * sizeof(int));
}

int notify_add(int fd, char *path)
{
  struct kevent event;

  EV_SET(&event, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL);
  if (kevent(kq, &event, 1, NULL, 0, NULL) == -1 || event.flags & EV_ERROR)
    return -1;
  paths[count] = path;
  fds[count++] = fd;
  return 0;
}

int notify_wait(char **path)
{
  struct kevent event;
  int i;

  for (;;) {
    if (kevent(kq, NULL, 0, &event, 1, NULL) != -1) {
      // We get the fd for free, but still have to search for the path.
      for (i=0; i<count; i++) if (fds[i]==event.ident) {
        *path = paths[i];
        return event.ident;
      }
    }
  }
}

#else

#include <sys/inotify.h>

static int ffd = -1;
static int *ids;

void notify_init(int max)
{
  if ((ffd = inotify_init()) < 0) perror_exit("inotify_init");
  fds = xmalloc(max * sizeof(int));
  ids = xmalloc(max * sizeof(int));
  paths = xmalloc(max * sizeof(char *));
}

int notify_add(int fd, char *path)
{
  ids[count] = inotify_add_watch(ffd, path, IN_MODIFY);
  if (ids[count] == -1) return -1;
  paths[count] = path;
  fds[count++] = fd;
  return 0;
}

int notify_wait(char **path)
{
  struct inotify_event ev;
  int i;

  for (;;) {
    if (sizeof(ev)!=read(ffd, &ev, sizeof(ev))) perror_exit("inotify");

    for (i=0; i<count; i++) if (ev.wd==ids[i]) {
      *path = paths[i];
      return fds[i];
    }
  }
}

#endif