Files
2025-04-09 01:00:12 +01:00

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)
}