From 46bf936df28606e7362cfcf2382ad630b819c949 Mon Sep 17 00:00:00 2001 From: nbari Date: Tue, 11 Apr 2017 10:57:16 +0200 Subject: [PATCH] moved watchDir/watchFile to kqueue --- watchfile.go => kqueue.go | 38 +++++++++++++++++ kqueue_386.go | 86 +++++++++++++++++++++++++++++++++++++++ kqueue_arm.go | 86 +++++++++++++++++++++++++++++++++++++++ watchdir.go | 47 --------------------- 4 files changed, 210 insertions(+), 47 deletions(-) rename watchfile.go => kqueue.go (54%) create mode 100644 kqueue_386.go create mode 100644 kqueue_arm.go delete mode 100644 watchdir.go diff --git a/watchfile.go b/kqueue.go similarity index 54% rename from watchfile.go rename to kqueue.go index 8fde520..b731e57 100644 --- a/watchfile.go +++ b/kqueue.go @@ -8,6 +8,44 @@ import ( "syscall" ) +// WatchDir check for changes on a directory via Kqueue EVFILT_VNODE +func WatchDir(dir string, ch chan<- struct{}) error { + file, err := os.Open(dir) + if err != nil { + return err + } + + kq, err := syscall.Kqueue() + if err != nil { + return err + } + + ev1 := syscall.Kevent_t{ + Ident: uint64(file.Fd()), + Filter: syscall.EVFILT_VNODE, + Flags: syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT, + Fflags: syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_ATTRIB | syscall.NOTE_LINK | syscall.NOTE_RENAME | syscall.NOTE_REVOKE, + Data: 0, + Udata: nil, + } + + // create kevent + events := []syscall.Kevent_t{ev1} + n, err := syscall.Kevent(kq, events, events, nil) + if err != nil { + return err + } + + // wait for an event + for { + if n > 0 { + file.Close() + ch <- struct{}{} + return nil + } + } +} + // WatchFile check for changes on a file via kqueue EVFILT_VNODE func WatchFile(f string, ch chan<- string) error { file, err := os.Open(f) diff --git a/kqueue_386.go b/kqueue_386.go new file mode 100644 index 0000000..63a7b2a --- /dev/null +++ b/kqueue_386.go @@ -0,0 +1,86 @@ +// +build freebsd netbsd openbsd darwin +// +build 386 + +package immortal + +import ( + "os" + "syscall" +) + +// WatchDir check for changes on a directory via Kqueue EVFILT_VNODE +func WatchDir(dir string, ch chan<- struct{}) error { + file, err := os.Open(dir) + if err != nil { + return err + } + + kq, err := syscall.Kqueue() + if err != nil { + return err + } + + ev1 := syscall.Kevent_t{ + Ident: uint32(file.Fd()), + Filter: syscall.EVFILT_VNODE, + Flags: syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT, + Fflags: syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_ATTRIB | syscall.NOTE_LINK | syscall.NOTE_RENAME | syscall.NOTE_REVOKE, + Data: 0, + Udata: nil, + } + + // create kevent + events := []syscall.Kevent_t{ev1} + n, err := syscall.Kevent(kq, events, events, nil) + if err != nil { + return err + } + + // wait for an event + for { + if n > 0 { + file.Close() + ch <- struct{}{} + return nil + } + } +} + +// WatchFile check for changes on a file via kqueue EVFILT_VNODE +func WatchFile(f string, ch chan<- string) error { + file, err := os.Open(f) + if err != nil { + return err + } + + kq, err := syscall.Kqueue() + if err != nil { + return err + } + + // NOTE_WRITE and NOTE_ATTRIB returns twice, removing NOTE_ATTRIB (touch) will not work + ev1 := syscall.Kevent_t{ + Ident: uint32(file.Fd()), + Filter: syscall.EVFILT_VNODE, + Flags: syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT, + Fflags: syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_LINK | syscall.NOTE_RENAME | syscall.NOTE_REVOKE, + Data: 0, + Udata: nil, + } + + // create kevent + events := []syscall.Kevent_t{ev1} + n, err := syscall.Kevent(kq, events, events, nil) + if err != nil { + return err + } + + // wait for an event + for { + if n > 0 { + file.Close() + ch <- f + return nil + } + } +} diff --git a/kqueue_arm.go b/kqueue_arm.go new file mode 100644 index 0000000..ecc0c42 --- /dev/null +++ b/kqueue_arm.go @@ -0,0 +1,86 @@ +// +build freebsd netbsd openbsd darwin +// +build arm + +package immortal + +import ( + "os" + "syscall" +) + +// WatchDir check for changes on a directory via Kqueue EVFILT_VNODE +func WatchDir(dir string, ch chan<- struct{}) error { + file, err := os.Open(dir) + if err != nil { + return err + } + + kq, err := syscall.Kqueue() + if err != nil { + return err + } + + ev1 := syscall.Kevent_t{ + Ident: uint32(file.Fd()), + Filter: syscall.EVFILT_VNODE, + Flags: syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT, + Fflags: syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_ATTRIB | syscall.NOTE_LINK | syscall.NOTE_RENAME | syscall.NOTE_REVOKE, + Data: 0, + Udata: nil, + } + + // create kevent + events := []syscall.Kevent_t{ev1} + n, err := syscall.Kevent(kq, events, events, nil) + if err != nil { + return err + } + + // wait for an event + for { + if n > 0 { + file.Close() + ch <- struct{}{} + return nil + } + } +} + +// WatchFile check for changes on a file via kqueue EVFILT_VNODE +func WatchFile(f string, ch chan<- string) error { + file, err := os.Open(f) + if err != nil { + return err + } + + kq, err := syscall.Kqueue() + if err != nil { + return err + } + + // NOTE_WRITE and NOTE_ATTRIB returns twice, removing NOTE_ATTRIB (touch) will not work + ev1 := syscall.Kevent_t{ + Ident: uint32(file.Fd()), + Filter: syscall.EVFILT_VNODE, + Flags: syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT, + Fflags: syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_LINK | syscall.NOTE_RENAME | syscall.NOTE_REVOKE, + Data: 0, + Udata: nil, + } + + // create kevent + events := []syscall.Kevent_t{ev1} + n, err := syscall.Kevent(kq, events, events, nil) + if err != nil { + return err + } + + // wait for an event + for { + if n > 0 { + file.Close() + ch <- f + return nil + } + } +} diff --git a/watchdir.go b/watchdir.go deleted file mode 100644 index 940ad3e..0000000 --- a/watchdir.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build freebsd netbsd openbsd dragonfly darwin -// +build amd64 - -package immortal - -import ( - "os" - "syscall" -) - -// WatchDir check for changes on a directory via Kqueue EVFILT_VNODE -func WatchDir(dir string, ch chan<- struct{}) error { - file, err := os.Open(dir) - if err != nil { - return err - } - - kq, err := syscall.Kqueue() - if err != nil { - return err - } - - ev1 := syscall.Kevent_t{ - Ident: uint64(file.Fd()), - Filter: syscall.EVFILT_VNODE, - Flags: syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_ONESHOT, - Fflags: syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_ATTRIB | syscall.NOTE_LINK | syscall.NOTE_RENAME | syscall.NOTE_REVOKE, - Data: 0, - Udata: nil, - } - - // create kevent - events := []syscall.Kevent_t{ev1} - n, err := syscall.Kevent(kq, events, events, nil) - if err != nil { - return err - } - - // wait for an event - for { - if n > 0 { - file.Close() - ch <- struct{}{} - return nil - } - } -}