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