summaryrefslogtreecommitdiff
path: root/src/inotify/inotify.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2015-08-28 20:42:46 -0600
committerLuke Shumaker <lukeshu@sbcglobal.net>2015-08-28 20:42:46 -0600
commit3c237531f5067340e34b01c7f7ea45fa55c39657 (patch)
treee6dd9be0682046ef755641a2cd49a0120ea0ea80 /src/inotify/inotify.go
parent4f16ef5707daf4acd74a07b665d1d67ab97c1f44 (diff)
switch to my own inotify bindings, the golang.org/x/exp bindings are crap
Diffstat (limited to 'src/inotify/inotify.go')
-rw-r--r--src/inotify/inotify.go94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/inotify/inotify.go b/src/inotify/inotify.go
new file mode 100644
index 0000000..976bdae
--- /dev/null
+++ b/src/inotify/inotify.go
@@ -0,0 +1,94 @@
+package inotify
+
+import (
+ "errors"
+ "syscall"
+ "unsafe"
+)
+
+var InotifyAlreadyClosedError error = errors.New("inotify instance already closed")
+
+type Inotify struct {
+ fd Cint
+ isClosed bool
+
+ fullbuff [4096]byte
+ buff []byte
+}
+
+type Event struct {
+ Wd Cint /* Watch descriptor */
+ Mask Mask /* Mask describing event */
+ Cookie uint32 /* Unique cookie associating related events (for rename(2)) */
+ Name *string /* Optional name */
+}
+
+func InotifyInit() (*Inotify, error) {
+ fd, err := inotify_init()
+ o := Inotify{
+ fd: Cint(fd),
+ isClosed: false,
+ }
+ o.buff = o.fullbuff[:]
+ return &o, err
+}
+
+func InotifyInit1(flags Cint) (*Inotify, error) {
+ fd, err := inotify_init1(flags)
+ o := Inotify{
+ fd: Cint(fd),
+ isClosed: false,
+ }
+ o.buff = o.fullbuff[:]
+ return &o, err
+}
+
+func (o *Inotify) AddWatch(path string, mask Mask) (Cint, error) {
+ if o.isClosed {
+ return -1, InotifyAlreadyClosedError
+ }
+ return inotify_add_watch(o.fd, path, uint32(mask))
+}
+
+func (o *Inotify) RmWatch(wd Cint) error {
+ if o.isClosed {
+ return InotifyAlreadyClosedError
+ }
+ return inotify_rm_watch(o.fd, wd)
+}
+
+func (o *Inotify) Close() error {
+ if o.isClosed {
+ return InotifyAlreadyClosedError
+ }
+ o.isClosed = true
+ return sysclose(o.fd)
+}
+
+func (o *Inotify) Read() (*Event, error) {
+ if len(o.buff) == 0 {
+ if o.isClosed {
+ return nil, InotifyAlreadyClosedError
+ }
+ len, err := sysread(o.fd, o.buff)
+ if len == 0 {
+ return nil, o.Close()
+ } else if len <= 0 {
+ return nil, err
+ }
+ o.buff = o.fullbuff[0:len]
+ }
+ raw := (*syscall.InotifyEvent)(unsafe.Pointer(&o.buff[0]))
+ var ret Event
+ ret.Wd = Cint(raw.Wd)
+ ret.Mask = Mask(raw.Mask)
+ ret.Cookie = raw.Cookie
+ ret.Name = nil
+ if raw.Len > 0 {
+ bytes := (*[syscall.NAME_MAX]byte)(unsafe.Pointer(&o.buff[syscall.SizeofInotifyEvent]))
+ name := string(bytes[:raw.Len-1])
+ ret.Name = &name
+ }
+ o.buff = o.buff[0 : syscall.SizeofInotifyEvent+raw.Len]
+ return &ret, nil
+}