diff options
Diffstat (limited to 'src/inotify')
-rw-r--r-- | src/inotify/bits.go | 120 | ||||
-rw-r--r-- | src/inotify/inotify.go | 128 | ||||
-rw-r--r-- | src/inotify/inutil/inotify_util.go | 96 | ||||
-rw-r--r-- | src/inotify/syscall.go | 75 |
4 files changed, 0 insertions, 419 deletions
diff --git a/src/inotify/bits.go b/src/inotify/bits.go deleted file mode 100644 index 18d8566..0000000 --- a/src/inotify/bits.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (C) 2015 Luke Shumaker -// -// Many of the comments in this file are taken from the GNU libc -// header file <sys/inotify.h> -// -// Copyright (C) 2005-2015 Free Software Foundation, Inc. -// -// The GNU C Library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// The GNU C Library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with the GNU C Library; if not, see -// <http://www.gnu.org/licenses/>. - -package inotify - -const ( - // Flags for the parameter of InotifyInit1(). - // These, oddly, appear to be 24-bit numbers. - IN_CLOEXEC int = 02000000 - IN_NONBLOCK int = 00004000 -) - -type file int // File Descriptor -type Wd int // Watch Descriptor - -type Mask uint32 - -const ( - // Supported events suitable for the `mask` parameter of Inotify.AddWatch(). - IN_ACCESS Mask = (1 << 0) // File was accessed. - IN_MODIFY Mask = (1 << 1) // File was modified. - IN_ATTRIB Mask = (1 << 2) // Metadata changed. - IN_CLOSE_WRITE Mask = (1 << 3) // Writtable file was closed. - IN_CLOSE_NOWRITE Mask = (1 << 4) // Unwrittable file closed. - IN_OPEN Mask = (1 << 5) // File was opened. - IN_MOVED_FROM Mask = (1 << 6) // File was moved from X. - IN_MOVED_TO Mask = (1 << 7) // File was moved to Y. - IN_CREATE Mask = (1 << 8) // Subfile was created. - IN_DELETE Mask = (1 << 9) // Subfile was deleted. - IN_DELETE_SELF Mask = (1 << 10) // Self was deleted. - IN_MOVE_SELF Mask = (1 << 11) // Self was moved. - - // Events that appear in output without subscribing to them. - IN_UNMOUNT Mask = (1 << 13) // Backing fs was unmounted. - IN_Q_OVERFLOW Mask = (1 << 14) // Event queued overflowed. - IN_IGNORED Mask = (1 << 15) // File was ignored (expect no more events). - - // Special flags that you may pass to Inotify.AddWatch()... - // except for IN_ISDIR, which is a flag that is set on output events. - IN_ONLYDIR Mask = (1 << 24) // Only watch the path if it is a directory. - IN_DONT_FOLLOW Mask = (1 << 25) // Do not follow a sym link. - IN_EXCL_UNLINK Mask = (1 << 26) // Exclude events on unlinked objects. - IN_MASK_ADD Mask = (1 << 29) // Add to the mask of an already existing watch. - IN_ISDIR Mask = (1 << 30) // Event occurred against dir. - IN_ONESHOT Mask = (1 << 31) // Only send event once. - - // Convenience macros */ - IN_CLOSE Mask = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) // Close. - IN_MOVE Mask = (IN_MOVED_FROM | IN_MOVED_TO) // Moves. - IN_ALL_EVENTS Mask = 0x00000FFF // All events which a program can wait on. -) - -var in_bits [32]string = [32]string{ - // mask - /* 0 */ "IN_ACCESS", - /* 1 */ "IN_MODIFY", - /* 2 */ "IN_ATTRIB", - /* 3 */ "IN_CLOSE_WRITE", - /* 4 */ "IN_CLOSE_NOWRITE", - /* 5 */ "IN_OPEN", - /* 6 */ "IN_MOVED_FROM", - /* 7 */ "IN_MOVED_TO", - /* 8 */ "IN_CREATE", - /* 9 */ "IN_DELETE", - /* 10 */ "IN_DELETE_SELF", - /* 11 */ "IN_MOVE_SELF", - /* 12 */ "(1<<12)", - // events sent by the kernel - /* 13 */ "IN_UNMOUNT", - /* 14 */ "IN_Q_OVERFLOW", - /* 15 */ "IN_IGNORED", - /* 16 */ "(1<<16)", - /* 17 */ "(1<<17)", - /* 18 */ "(1<<18)", - /* 19 */ "(1<<19)", - /* 20 */ "(1<<20)", - /* 21 */ "(1<<21)", - /* 22 */ "(1<<22)", - /* 23 */ "(1<<23)", - // special flags - /* 24 */ "IN_ONLYDIR", - /* 25 */ "IN_DONT_FOLLOW", - /* 26 */ "IN_EXCL_UNLINK", - /* 27 */ "(1<<27)", - /* 28 */ "(1<<28)", - /* 29 */ "IN_MASK_ADD", - /* 30 */ "IN_ISDIR", - /* 31 */ "IN_ONESHOT", -} - -func (mask Mask) String() string { - out := "" - for i, name := range in_bits { - if mask&(Mask(1)<<uint(i)) != 0 { - if len(out) > 0 { - out += "|" - } - out += name - } - } - return out -} diff --git a/src/inotify/inotify.go b/src/inotify/inotify.go deleted file mode 100644 index 2fd3a83..0000000 --- a/src/inotify/inotify.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2015 Luke Shumaker <lukeshu@sbcglobal.net>. -// -// This is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of the -// License, or (at your option) any later version. -// -// This software is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this manual; if not, see -// <http://www.gnu.org/licenses/>. - -// Package inotify provides an interface to the Linux inotify system. -// The inotify system is a mechanism for monitoring filesystem events. -package inotify - -import ( - "sync" - "syscall" - "unsafe" -) - -type Inotify struct { - fd file - fdLock sync.RWMutex - buffFull [4096]byte - buff []byte - buffLock sync.Mutex -} - -type Event struct { - Wd Wd // Watch descriptor - Mask Mask // Mask describing event - Cookie uint32 // Unique cookie associating related events (for rename(2)) - Name *string // Optional name -} - -// Create an inotify instance. The variant InotifyInit1() allows -// flags to access extra functionality. -func InotifyInit() (*Inotify, error) { - fd, err := inotify_init() - o := Inotify{ - fd: fd, - } - o.buff = o.buffFull[:0] - return &o, err -} - -// Create an inotify instance, with flags specifying extra -// functionality. -func InotifyInit1(flags int) (*Inotify, error) { - fd, err := inotify_init1(flags) - o := Inotify{ - fd: fd, - } - o.buff = o.buffFull[:0] - return &o, err -} - -// Add a watch to the inotify instance, or modifies an existing watch -// item. -func (o *Inotify) AddWatch(path string, mask Mask) (Wd, error) { - o.fdLock.RLock() - defer o.fdLock.RUnlock() - return inotify_add_watch(o.fd, path, mask) -} - -// Remove a watch from the inotify instance. -func (o *Inotify) RmWatch(wd Wd) error { - o.fdLock.RLock() - defer o.fdLock.RUnlock() - return inotify_rm_watch(o.fd, wd) -} - -// Close the inotify instance; further calls to this object will -// error. -// -// Events recieved before Close() is called may still be Read() after -// the call to Close(). -// -// Beware that if Close() is called while waiting on Read(), it will -// block until events are read. -func (o *Inotify) Close() error { - o.fdLock.Lock() - defer o.fdLock.Unlock() - defer func() { o.fd = -1 }() - return sysclose(o.fd) -} - -// Read an event from the inotify instance. -// -// Events recieved before Close() is called may still be Read() after -// the call to Close(). -func (o *Inotify) Read() (Event, error) { - o.buffLock.Lock() - defer o.buffLock.Unlock() - - if len(o.buff) == 0 { - o.fdLock.RLock() - len, err := sysread(o.fd, o.buffFull[:]) - o.fdLock.RUnlock() - if len == 0 { - return Event{Wd: -1}, o.Close() - } else if len < 0 { - return Event{Wd: -1}, err - } - o.buff = o.buffFull[0:len] - } - - raw := (*syscall.InotifyEvent)(unsafe.Pointer(&o.buff[0])) - ret := Event{ - Wd: Wd(raw.Wd), - Mask: Mask(raw.Mask), - Cookie: raw.Cookie, - 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 -} diff --git a/src/inotify/inutil/inotify_util.go b/src/inotify/inutil/inotify_util.go deleted file mode 100644 index c643e59..0000000 --- a/src/inotify/inutil/inotify_util.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2015 Luke Shumaker <lukeshu@sbcglobal.net>. -// -// This is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of -// the License, or (at your option) any later version. -// -// This software is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this manual; if not, see -// <http://www.gnu.org/licenses/>. - -// Package inutil provides a channel-based interface to inotify. -package inutil - -import ( - "inotify" - "os" - "syscall" -) - -type Watcher struct { - Events <-chan inotify.Event - Errors <-chan error - events chan<- inotify.Event - errors chan<- error - in *inotify.Inotify -} - -// Wraps inotify.InotifyInit() -func WatcherInit() (*Watcher, error) { - in, err := inotify.InotifyInit() - return newWatcher(in, err) -} - -// Wraps inotify.InotifyInit1() -func WatcherInit1(flags int) (*Watcher, error) { - in, err := inotify.InotifyInit1(flags &^ inotify.IN_NONBLOCK) - return newWatcher(in, err) -} - -func newWatcher(in *inotify.Inotify, err error) (*Watcher, error) { - events := make(chan inotify.Event) - errors := make(chan error) - o := &Watcher{ - Events: events, - events: events, - Errors: errors, - errors: errors, - in: in, - } - go o.worker() - return o, err -} - -// Wraps inotify.Inotify.AddWatch(); adds or modifies a watch. -func (o *Watcher) AddWatch(path string, mask inotify.Mask) (inotify.Wd, error) { - return o.in.AddWatch(path, mask) -} - -// Wraps inotify.Inotify.RmWatch(); removes a watch. -func (o *Watcher) RmWatch(wd inotify.Wd) error { - return o.in.RmWatch(wd) -} - -// Wraps inotify.Inotify.Close(). Unlike inotify.Inotify.Close(), -// this cannot block. Also unlike inotify.Inotify.Close(), nothing -// may be received from the channel after this is called. -func (o *Watcher) Close() { - func() { - defer recover() - close(o.events) - close(o.errors) - }() - go o.in.Close() -} - -func (o *Watcher) worker() { - defer recover() - for { - ev, err := o.in.Read() - if ev.Wd >= 0 { - o.events <- ev - } - if err != nil { - if err.(*os.SyscallError).Err == syscall.EBADF { - o.Close() - } - o.errors <- err - } - } -} diff --git a/src/inotify/syscall.go b/src/inotify/syscall.go deleted file mode 100644 index d1b5140..0000000 --- a/src/inotify/syscall.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2015 Luke Shumaker <lukeshu@sbcglobal.net>. -// -// This is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of -// the License, or (at your option) any later version. -// -// This software is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this manual; if not, see -// <http://www.gnu.org/licenses/>. - -package inotify - -import ( - "os" - "syscall" -) - -func newPathError(op string, path string, err error) error { - if err == nil { - return nil - } - return &os.PathError{Op: op, Path: path, Err: err} -} - -// Create and initialize inotify instance. -func inotify_init() (file, error) { - fd, errno := syscall.InotifyInit() - return file(fd), os.NewSyscallError("inotify_init", errno) -} - -// Create and initialize inotify instance. -func inotify_init1(flags int) (file, error) { - fd, errno := syscall.InotifyInit1(flags) - return file(fd), os.NewSyscallError("inotify_init1", errno) -} - -// Add watch of object NAME to inotify instance FD. Notify about -// events specified by MASK. -func inotify_add_watch(fd file, name string, mask Mask) (Wd, error) { - wd, errno := syscall.InotifyAddWatch(int(fd), name, uint32(mask)) - return Wd(wd), newPathError("inotify_add_watch", name, errno) -} - -// Remove the watch specified by WD from the inotify instance FD. -func inotify_rm_watch(fd file, wd Wd) error { - success, errno := syscall.InotifyRmWatch(int(fd), uint32(wd)) - switch success { - case -1: - if errno == nil { - panic("should never happen") - } - os.NewSyscallError("inotify_rm_watch", errno) - case 0: - if errno != nil { - panic("should never happen") - } - return nil - } - panic("should never happen") -} - -func sysclose(fd file) error { - return os.NewSyscallError("close", syscall.Close(int(fd))) -} - -func sysread(fd file, p []byte) (int, error) { - n, err := syscall.Read(int(fd), p) - return n, os.NewSyscallError("read", err) -} |