1// +build freebsd netbsd openbsd darwin
2// +build arm
3
4package immortal
5
6import "syscall"
7
8// WatchDir check for changes on a directory via Kqueue EVFILT_VNODE
9func WatchDir(dir string, ch chan<- string) error {
10	watchfd, err := syscall.Open(dir, openModeDir, 0700)
11	if err != nil {
12		return err
13	}
14
15	kq, err := syscall.Kqueue()
16	if err != nil {
17		syscall.Close(watchfd)
18		return err
19	}
20
21	ev1 := syscall.Kevent_t{
22		Ident:  uint32(watchfd),
23		Filter: syscall.EVFILT_VNODE,
24		Flags:  syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT,
25		Fflags: syscall.NOTE_WRITE | syscall.NOTE_ATTRIB,
26		Data:   0,
27	}
28
29	for {
30		// create kevent
31		kevents := []syscall.Kevent_t{ev1}
32		n, err := syscall.Kevent(kq, kevents, kevents, nil)
33		if err != nil {
34			syscall.Close(watchfd)
35			return err
36		}
37
38		// wait for an event
39		for len(kevents) > 0 {
40			if n > 0 {
41				ch <- dir
42			}
43			// Move to next event
44			kevents = kevents[1:]
45		}
46	}
47}
48
49// WatchFile check for changes on a file via kqueue EVFILT_VNODE
50func WatchFile(f string, ch chan<- string) error {
51	watchfd, err := syscall.Open(f, openModeFile, 0700)
52	if err != nil {
53		return err
54	}
55
56	kq, err := syscall.Kqueue()
57	if err != nil {
58		syscall.Close(watchfd)
59		return err
60	}
61
62	// NOTE_WRITE and NOTE_ATTRIB returns twice, if removing NOTE_ATTRIB (touch) will not work
63	ev1 := syscall.Kevent_t{
64		Ident:  uint32(watchfd),
65		Filter: syscall.EVFILT_VNODE,
66		Flags:  syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT,
67		Fflags: syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_ATTRIB | syscall.NOTE_LINK | syscall.NOTE_RENAME | syscall.NOTE_REVOKE,
68		Data:   0,
69	}
70
71	// create kevent
72	kevents := []syscall.Kevent_t{ev1}
73	n, err := syscall.Kevent(kq, kevents, kevents, nil)
74	if err != nil {
75		syscall.Close(watchfd)
76		return err
77	}
78
79	// wait for an event
80	for len(kevents) > 0 {
81		if n > 0 {
82			// do something
83		}
84		// Move to next event
85		kevents = kevents[1:]
86	}
87	syscall.Close(watchfd)
88	ch <- f
89	return nil
90}
91