139 lines
5.1 KiB
Go
139 lines
5.1 KiB
Go
//go:build linux
|
|
// +build linux
|
|
|
|
package gonotify
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"syscall"
|
|
)
|
|
|
|
const (
|
|
IN_ACCESS = uint32(syscall.IN_ACCESS) // File was accessed
|
|
IN_ATTRIB = uint32(syscall.IN_ATTRIB) // Metadata changed
|
|
IN_CLOSE_WRITE = uint32(syscall.IN_CLOSE_WRITE) // File opened for writing was closed.
|
|
IN_CLOSE_NOWRITE = uint32(syscall.IN_CLOSE_NOWRITE) // File or directory not opened for writing was closed.
|
|
IN_CREATE = uint32(syscall.IN_CREATE) // File/directory created in watched directory
|
|
IN_DELETE = uint32(syscall.IN_DELETE) // File/directory deleted from watched directory.
|
|
IN_DELETE_SELF = uint32(syscall.IN_DELETE_SELF) // Watched file/directory was itself deleted.
|
|
IN_MODIFY = uint32(syscall.IN_MODIFY) // File was modified
|
|
IN_MOVE_SELF = uint32(syscall.IN_MOVE_SELF) // Watched file/directory was itself moved.
|
|
IN_MOVED_FROM = uint32(syscall.IN_MOVED_FROM) // Generated for the directory containing the old filename when a file is renamed.
|
|
IN_MOVED_TO = uint32(syscall.IN_MOVED_TO) // Generated for the directory containing the new filename when a file is renamed.
|
|
IN_OPEN = uint32(syscall.IN_OPEN) // File or directory was opened.
|
|
|
|
IN_ALL_EVENTS = uint32(syscall.IN_ALL_EVENTS) // bit mask of all of the above events.
|
|
IN_MOVE = uint32(syscall.IN_MOVE) // Equates to IN_MOVED_FROM | IN_MOVED_TO.
|
|
IN_CLOSE = uint32(syscall.IN_CLOSE) // Equates to IN_CLOSE_WRITE | IN_CLOSE_NOWRITE.
|
|
|
|
/* The following further bits can be specified in mask when calling Inotify.AddWatch() */
|
|
|
|
IN_DONT_FOLLOW = uint32(syscall.IN_DONT_FOLLOW) // Don't dereference pathname if it is a symbolic link.
|
|
IN_EXCL_UNLINK = uint32(syscall.IN_EXCL_UNLINK) // Don't generate events for children if they have been unlinked from the directory.
|
|
IN_MASK_ADD = uint32(syscall.IN_MASK_ADD) // Add (OR) the events in mask to the watch mask
|
|
IN_ONESHOT = uint32(syscall.IN_ONESHOT) // Monitor the filesystem object corresponding to pathname for one event, then remove from watch list.
|
|
IN_ONLYDIR = uint32(syscall.IN_ONLYDIR) // Watch pathname only if it is a directory.
|
|
|
|
/* The following bits may be set in the mask field returned by Inotify.Read() */
|
|
|
|
IN_IGNORED = uint32(syscall.IN_IGNORED) // Watch was removed explicitly or automatically
|
|
IN_ISDIR = uint32(syscall.IN_ISDIR) // Subject of this event is a directory.
|
|
IN_Q_OVERFLOW = uint32(syscall.IN_Q_OVERFLOW) // Event queue overflowed (wd is -1 for this event).
|
|
|
|
IN_UNMOUNT = uint32(syscall.IN_UNMOUNT) // Filesystem containing watched object was unmounted.
|
|
)
|
|
|
|
var in_mapping = map[uint32]string{
|
|
IN_ACCESS: "IN_ACCESS",
|
|
IN_ATTRIB: "IN_ATTRIB",
|
|
IN_CLOSE_WRITE: "IN_CLOSE_WRITE",
|
|
IN_CLOSE_NOWRITE: "IN_CLOSE_NOWRITE",
|
|
IN_CREATE: "IN_CREATE",
|
|
IN_DELETE: "IN_DELETE",
|
|
IN_DELETE_SELF: "IN_DELETE_SELF",
|
|
IN_MODIFY: "IN_MODIFY",
|
|
IN_MOVE_SELF: "IN_MOVE_SELF",
|
|
IN_MOVED_FROM: "IN_MOVED_FROM",
|
|
IN_MOVED_TO: "IN_MOVED_TO",
|
|
IN_OPEN: "IN_OPEN",
|
|
IN_IGNORED: "IN_IGNORED",
|
|
IN_ISDIR: "IN_ISDIR",
|
|
IN_Q_OVERFLOW: "IN_Q_OVERFLOW",
|
|
IN_UNMOUNT: "IN_UNMOUNT",
|
|
}
|
|
|
|
func InMaskToString(in_mask uint32) string {
|
|
sb := &strings.Builder{}
|
|
divide := false
|
|
for mask, str := range in_mapping {
|
|
if in_mask&mask == mask {
|
|
if divide {
|
|
sb.WriteString("|")
|
|
}
|
|
sb.WriteString(str)
|
|
divide = true
|
|
}
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
// InotifyEvent is the go representation of inotify_event found in sys/inotify.h
|
|
type InotifyEvent struct {
|
|
// Watch descriptor
|
|
Wd int
|
|
// File or directory name
|
|
Name string
|
|
// Contains bits that describe the event that occurred
|
|
Mask uint32
|
|
// Usually 0, but if events (like IN_MOVED_FROM and IN_MOVED_TO) are linked then they will have equal cookie
|
|
Cookie uint32
|
|
}
|
|
|
|
func (i InotifyEvent) GoString() string {
|
|
return fmt.Sprintf("gonotify.InotifyEvent{Wd=%#v, Name=%s, Cookie=%#v, Mask=%#v=%s}", i.Wd, i.Name, i.Cookie, i.Mask, InMaskToString(i.Mask))
|
|
}
|
|
|
|
func (i InotifyEvent) String() string {
|
|
return fmt.Sprintf("{Wd=%d, Name=%s, Cookie=%d, Mask=%s}", i.Wd, i.Name, i.Cookie, InMaskToString(i.Mask))
|
|
}
|
|
|
|
// IsAny returns true if any of the in_mask is set in the event
|
|
func (i InotifyEvent) IsAny(in_mask ...uint32) bool {
|
|
for _, mask := range in_mask {
|
|
if i.Mask&mask == mask {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsAll returns true if all the in_masks is set in the event
|
|
func (i InotifyEvent) IsAll(in_mask ...uint32) bool {
|
|
for _, mask := range in_mask {
|
|
if i.Mask&mask != mask {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (i InotifyEvent) Is(in_mask uint32) bool {
|
|
return i.Mask&in_mask == in_mask
|
|
}
|
|
|
|
// FileEvent is the wrapper around InotifyEvent with additional Eof marker. Reading from
|
|
// FileEvents from DirWatcher.C or FileWatcher.C may end with Eof when underlying inotify is closed
|
|
type FileEvent struct {
|
|
InotifyEvent
|
|
Eof bool
|
|
}
|
|
|
|
func (f FileEvent) GoString() string {
|
|
return fmt.Sprintf("gonotify.FileEvent{InotifyEvent=%#v, Eof=%#v}", f.InotifyEvent, f.Eof)
|
|
}
|
|
|
|
func (f FileEvent) String() string {
|
|
return fmt.Sprintf("{InotifyEvent=%s, Eof=%v}", f.InotifyEvent, f.Eof)
|
|
}
|