summaryrefslogtreecommitdiff
path: root/inotify/inotify.go
diff options
context:
space:
mode:
Diffstat (limited to 'inotify/inotify.go')
-rw-r--r--inotify/inotify.go94
1 files changed, 94 insertions, 0 deletions
diff --git a/inotify/inotify.go b/inotify/inotify.go
new file mode 100644
index 0000000..976bdae
--- /dev/null
+++ b/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
+}