diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-12-18 15:51:39 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-12-18 15:51:39 -0500 |
commit | fc5d64a5fc886e0b8519e8c19d311ebfb0df59db (patch) | |
tree | 2fd417f1d24bd9d7956b705212037f1aad9854c5 /inotify | |
parent | 09db31c7264e370fbbafab81a0c30b1ac1b80514 (diff) |
add inotify.NewInotify
Diffstat (limited to 'inotify')
-rw-r--r-- | inotify/inotify.go | 26 | ||||
-rw-r--r-- | inotify/syscall.go | 21 |
2 files changed, 47 insertions, 0 deletions
diff --git a/inotify/inotify.go b/inotify/inotify.go index 2db414c..1c0c3c6 100644 --- a/inotify/inotify.go +++ b/inotify/inotify.go @@ -96,6 +96,32 @@ func newInotify(fd inFd, blocking bool) *Inotify { return in } +// NewInotify creates an Inotify object that wraps an inotify instance +// on an already open file descriptor, much like net.FileListener. +// +// Closing file does not affect the Inotify, and closing Inotify does +// not affect file. +func NewInotify(file *os.File) (*Inotify, error) { + dup, err := sys_dupfd_cloexec(inFd(file.Fd())) + if err != nil { + return nil, err + } + + nonblock, err := sys_getnonblock(dup) + if err != nil { + sys_close(dup) + return nil, err + } + + err = sys_setnonblock(dup, false) + if err != nil { + sys_close(dup) + return nil, err + } + + return newInotify(dup, !nonblock), nil +} + // InotifyInit creates an inotify instance. The variant // InotifyInit1() allows flags to access extra functionality. func InotifyInit() (*Inotify, error) { diff --git a/inotify/syscall.go b/inotify/syscall.go index 0a0c2f0..33a10e2 100644 --- a/inotify/syscall.go +++ b/inotify/syscall.go @@ -73,3 +73,24 @@ func sys_read(fd inFd, p []byte) (int, error) { n, err := syscall.Read(int(fd), p) return n, os.NewSyscallError("read", err) } + +func sys_dupfd_cloexec(fd inFd) (inFd, error) { + n, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) + if errno != 0 { + return -1, os.NewSyscallError("dupfd_cloexec", errno) + } + return inFd(n), nil +} + +func sys_setnonblock(fd inFd, nonblocking bool) error { + err := syscall.SetNonblock(int(fd), nonblocking) + return os.NewSyscallError("setnonblock", err) +} + +func sys_getnonblock(fd inFd) (bool, error) { + flag, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_GETFL, 0) + if errno != 0 { + return false, os.NewSyscallError("getnonblock", errno) + } + return flag & syscall.O_NONBLOCK != 0, nil +} |