Inotify file system watching for linux.
This commit is contained in:
parent
6a8da44ee5
commit
04dedc5f5c
79
pkg/watcher/linux.go
Normal file
79
pkg/watcher/linux.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package watcher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CrDelMask uint32 = syscall.IN_CREATE | syscall.IN_DELETE
|
||||||
|
|
||||||
|
type FSWatcher struct {
|
||||||
|
fd int
|
||||||
|
wds []int
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFSWatcher() (fsw *FSWatcher, err error) {
|
||||||
|
fsw = &FSWatcher{closed: false}
|
||||||
|
|
||||||
|
fsw.fd, err = syscall.InotifyInit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to initialise inotify watcher")
|
||||||
|
}
|
||||||
|
|
||||||
|
fsw.wds = make([]int, 0)
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsw *FSWatcher) AddWatch(path string, mask uint32) error {
|
||||||
|
wd, err := syscall.InotifyAddWatch(fsw.fd, path, mask)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to set %s on watch", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fsw.wds = append(fsw.wds, wd)
|
||||||
|
syscall.Read(fsw.fd, nil)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchForMask checking for events from mask and returns inotify mask to channel.
|
||||||
|
func (fsw *FSWatcher) WatchForMask(fired chan uint32, mask uint32) {
|
||||||
|
buffer := make([]byte, syscall.SizeofInotifyEvent)
|
||||||
|
go func() {
|
||||||
|
for !fsw.closed {
|
||||||
|
n, err := syscall.Read(fsw.fd, buffer)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if n < syscall.SizeofInotifyEvent {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
event := (*syscall.InotifyEvent)(unsafe.Pointer(&buffer[0]))
|
||||||
|
if event.Mask&mask > 0 {
|
||||||
|
fired <- event.Mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsw *FSWatcher) Close() error {
|
||||||
|
for _, wd := range fsw.wds {
|
||||||
|
if _, err := syscall.InotifyRmWatch(fsw.fd, uint32(wd)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syscall.Close(fsw.fd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fsw.closed = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user