Skip to content

Commit

Permalink
Refactor: rename Action -> EventType
Browse files Browse the repository at this point in the history
  • Loading branch information
opcoder0 committed Dec 9, 2022
1 parent 1fcf735 commit e1329dc
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 124 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func main() {
os.Exit(1)
}
fmt.Println("Listening to events for:", listenPath)
var actions Action
actions =
var eventTypes EventType
eventTypes =
fanotify.FileAccessed |
fanotify.FileOrDirectoryAccessed |
fanotify.FileModified |
Expand All @@ -61,7 +61,7 @@ func main() {
fanotify.FileOrDirectoryMovedTo |
fanotify.WatchedFileMoved |
fanotify.WatchedFileOrDirectoryMoved
listener.AddWatch(listenPath, actions)
listener.AddWatch(listenPath, eventTypes)
go listener.Start()
i := 1
for event := range listener.Events {
Expand All @@ -78,13 +78,13 @@ func main() {

## Known Issues

Certain flag combinations / actions cause issues with event reporting.
Certain flag combinations / event types cause issues with event reporting.

- `fanotify.FileCreated` (`unix.FAN_CREATE`) cannot be or-ed / combined with `fanotify.FileClosed` (`unix.FAN_CLOSE_WRITE` or `unix.FAN_CLOSE_NOWRITE`). The `fanotify` event notification group does not generate any event for this combination.

- Using `fanotify.FileOpened` with any of the actions containing `OrDirectory` (`unix.FAN_ONDIR`) causes an event flood for the directory and then stopping raising any events at all.
- Using `fanotify.FileOpened` with any of the event types containing `OrDirectory` (`unix.FAN_ONDIR`) causes an event flood for the directory and then stopping raising any events at all.

- `fanotifyFileOrDirectoryOpened` with any of the other actions causes an event flood for the directory and then stopping raising any events at all.
- `fanotifyFileOrDirectoryOpened` with any of the other event types causes an event flood for the directory and then stopping raising any events at all.

## Tests

Expand Down
6 changes: 3 additions & 3 deletions doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ func ExampleListener_AddWatch() {

func ExampleListener_AddWatch_all() {
var listener *fanotify.Listener
var actions fanotify.Action
var eventTypes fanotify.EventType

listener, err := fanotify.NewListener("/", false)
if err != nil {
log.Fatal("Cannot create listener for path /", err)
}
actions = fanotify.FileAccessed |
eventTypes = fanotify.FileAccessed |
fanotify.FileOrDirectoryAccessed |
fanotify.FileModified |
fanotify.FileOpenedForExec |
Expand All @@ -47,5 +47,5 @@ func ExampleListener_AddWatch_all() {
fanotify.FileOrDirectoryMovedTo |
fanotify.WatchedFileMoved |
fanotify.WatchedFileOrDirectoryMoved
listener.AddWatch("/home/user", actions)
listener.AddWatch("/home/user", eventTypes)
}
66 changes: 35 additions & 31 deletions fanotify_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ var (
ErrWatchPath = errors.New("missing watch path")
)

// Action represents an event / operation on a particular file/directory
type Action uint64
// EventType represents an event / operation on a particular file/directory
type EventType uint64

// Event represents a notification from the kernel for the file, directory
// or a filesystem marked for watching.
Expand All @@ -39,8 +39,8 @@ type Event struct {
// when NewListener is created by passing `true` with `withName` argument. The feature is available
// only with kernels 5.9 or higher.
FileName string
// Actions holds bit mask representing the operations
Actions Action
// EventTypes holds bit mask representing the operations
EventTypes EventType
// Pid Process ID of the process that caused the event
Pid int
}
Expand Down Expand Up @@ -146,25 +146,29 @@ func (l *Listener) Stop() {
close(l.Events)
}

// MarkMount adds, modifies or removes the fanotify mark (passed in as action) for the entire
// MarkMount adds, modifies or removes the fanotify mark (passed in as eventTypes) for the entire
// mountpoint. Passing true to remove, removes the mark from the mountpoint.
// This method returns an [ErrWatchPath] if the listener was not initialized to monitor
// the entire mountpoint. To mark specific files or directories use [AddWatch] method.
// The entire mount cannot be monitored for the following events:
// [FileCreated], [FileAttribChanged], [FileMovedFrom],
// [FileMovedTo], [WatchedFileDeleted]
// Passing any of these flags in action will return [ErrInvalidFlagCombination] error
func (l *Listener) MarkMount(action Action, remove bool) error {
// Passing any of these flags in eventTypes will return [ErrInvalidFlagCombination] error
func (l *Listener) MarkMount(eventTypes EventType, remove bool) error {
if l.entireMount == false {
return ErrWatchPath
}
if action.Has(FileCreated) || action.Has(FileAttribChanged) || action.Has(FileMovedFrom) || action.Has(FileMovedTo) || action.Has(WatchedFileDeleted) {
if eventTypes.Has(FileCreated) ||
eventTypes.Has(FileAttribChanged) ||
eventTypes.Has(FileMovedFrom) ||
eventTypes.Has(FileMovedTo) ||
eventTypes.Has(WatchedFileDeleted) {
return ErrInvalidFlagCombination
}
if remove {
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_REMOVE|unix.FAN_MARK_MOUNT, uint64(action), false)
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_REMOVE|unix.FAN_MARK_MOUNT, uint64(eventTypes), false)
}
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_ADD|unix.FAN_MARK_MOUNT, uint64(action), false)
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_ADD|unix.FAN_MARK_MOUNT, uint64(eventTypes), false)
}

// AddWatch adds or modifies the fanotify mark for the specified path.
Expand All @@ -173,26 +177,26 @@ func (l *Listener) MarkMount(action Action, remove bool) error {
// [os.ErrInvalid]. To mark the entire mountpoint use [MarkMount] method.
// Certain flag combinations are known to cause issues.
// - [FileCreated] cannot be or-ed / combined with FileClosed. The fanotify system does not generate any event for this combination.
// - [FileOpened] with any of the actions containing OrDirectory causes an event flood for the directory and then stopping raising any events at all.
// - [FileOrDirectoryOpened] with any of the other actions causes an event flood for the directory and then stopping raising any events at all.
func (l *Listener) AddWatch(path string, action Action) error {
// - [FileOpened] with any of the event types containing OrDirectory causes an event flood for the directory and then stopping raising any events at all.
// - [FileOrDirectoryOpened] with any of the other event types causes an event flood for the directory and then stopping raising any events at all.
func (l *Listener) AddWatch(path string, eventTypes EventType) error {
if l.entireMount {
return os.ErrInvalid
}
return l.fanotifyMark(path, unix.FAN_MARK_ADD, uint64(action|unix.FAN_EVENT_ON_CHILD), false)
return l.fanotifyMark(path, unix.FAN_MARK_ADD, uint64(eventTypes|unix.FAN_EVENT_ON_CHILD), false)
}

// DeleteWatch removes or modifies the fanotify mark for the specified path.
// Calling DeleteWatch on the listener initialized to monitor the entire mountpoint
// results in [os.ErrInvalid]. To modify the mark for the entire mountpoint use [MarkMount] method.
func (l *Listener) DeleteWatch(parentDir string, action Action) error {
func (l *Listener) DeleteWatch(parentDir string, eventTypes EventType) error {
if l.entireMount {
return os.ErrInvalid
}
return l.fanotifyMark(parentDir, unix.FAN_MARK_REMOVE, uint64(action|unix.FAN_EVENT_ON_CHILD), false)
return l.fanotifyMark(parentDir, unix.FAN_MARK_REMOVE, uint64(eventTypes|unix.FAN_EVENT_ON_CHILD), false)
}

// ClearWatch stops watching for all actions
// ClearWatch stops watching for all event types
func (l *Listener) ClearWatch() error {
if l == nil {
return ErrNilListener
Expand All @@ -204,19 +208,19 @@ func (l *Listener) ClearWatch() error {
return nil
}

// Has returns true if actions contains the passed in action (a).
func (actions Action) Has(a Action) bool {
return actions&a == a
// Has returns true if event types contains the passed in event type (et).
func (eventTypes EventType) Has(et EventType) bool {
return eventTypes&et == et
}

// Or appends the specified action to the set of actions to watch for
func (actions Action) Or(a Action) Action {
return actions | a
// Or appends the specified event types to the set of event types to watch for
func (eventTypes EventType) Or(et EventType) EventType {
return eventTypes | et
}

// String prints action
func (a Action) String() string {
var actions = map[Action]string{
// String prints event types
func (a EventType) String() string {
var eventTypes = map[EventType]string{
unix.FAN_ACCESS: "Access",
unix.FAN_MODIFY: "Modify",
unix.FAN_CLOSE_WRITE: "CloseWrite",
Expand All @@ -231,15 +235,15 @@ func (a Action) String() string {
unix.FAN_MOVED_TO: "MovedTo",
unix.FAN_MOVE_SELF: "SelfMove",
}
var actionList []string
for k, v := range actions {
var eventTypeList []string
for k, v := range eventTypes {
if a.Has(k) {
actionList = append(actionList, v)
eventTypeList = append(eventTypeList, v)
}
}
return strings.Join(actionList, ",")
return strings.Join(eventTypeList, ",")
}

func (e Event) String() string {
return fmt.Sprintf("Fd:(%d), Pid:(%d), Action:(%s), Path:(%s), Filename:(%s)", e.Fd, e.Pid, e.Actions, e.Path, e.FileName)
return fmt.Sprintf("Fd:(%d), Pid:(%d), EventType:(%s), Path:(%s), Filename:(%s)", e.Fd, e.Pid, e.EventTypes, e.Path, e.FileName)
}
20 changes: 10 additions & 10 deletions fanotify_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func fanotifyMarkMaskValid(mask uint64) error {
return n&k == k
}
if isSet(mask, unix.FAN_MARK_MOUNT) && (isSet(mask, unix.FAN_CREATE) || isSet(mask, unix.FAN_ATTRIB) || isSet(mask, unix.FAN_MOVE) || isSet(mask, unix.FAN_DELETE_SELF)) {
return errors.New("mountpoint cannot be watched for create, attrib, move or delete self actions")
return errors.New("mountpoint cannot be watched for create, attrib, move or delete self event types")
}
return nil
}
Expand Down Expand Up @@ -379,10 +379,10 @@ func (l *Listener) readEvents() error {
mask = mask ^ unix.FAN_ONDIR
}
event := Event{
Fd: int(metadata.Fd),
Path: string(name[:n1]),
Actions: Action(mask),
Pid: int(metadata.Pid),
Fd: int(metadata.Fd),
Path: string(name[:n1]),
EventTypes: EventType(mask),
Pid: int(metadata.Pid),
}
l.Events <- event
} else {
Expand Down Expand Up @@ -424,11 +424,11 @@ func (l *Listener) readEvents() error {
mask = mask ^ unix.FAN_ONDIR
}
event := Event{
Fd: fd,
Path: pathName,
FileName: fileName,
Actions: Action(mask),
Pid: int(metadata.Pid),
Fd: fd,
Path: pathName,
FileName: fileName,
EventTypes: EventType(mask),
Pid: int(metadata.Pid),
}
l.Events <- event
i += int(metadata.Event_len)
Expand Down
48 changes: 24 additions & 24 deletions fanotify_event_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,93 +4,93 @@ import "golang.org/x/sys/unix"

const (
// FileAccessed event when a file is accessed
FileAccessed Action = unix.FAN_ACCESS
FileAccessed EventType = unix.FAN_ACCESS

// FileOrDirectoryAccessed event when a file or directory is accessed
FileOrDirectoryAccessed Action = unix.FAN_ACCESS | unix.FAN_ONDIR
FileOrDirectoryAccessed EventType = unix.FAN_ACCESS | unix.FAN_ONDIR

// FileModified event when a file is modified
FileModified Action = unix.FAN_MODIFY
FileModified EventType = unix.FAN_MODIFY

// FileClosedAfterWrite event when a file is closed
FileClosedAfterWrite Action = unix.FAN_CLOSE_WRITE
FileClosedAfterWrite EventType = unix.FAN_CLOSE_WRITE

// FileClosedWithNoWrite event when a file is closed without writing
FileClosedWithNoWrite Action = unix.FAN_CLOSE_NOWRITE
FileClosedWithNoWrite EventType = unix.FAN_CLOSE_NOWRITE

// FileClosed event when a file is closed after write or no write
FileClosed Action = unix.FAN_CLOSE_WRITE | unix.FAN_CLOSE_NOWRITE
FileClosed EventType = unix.FAN_CLOSE_WRITE | unix.FAN_CLOSE_NOWRITE

// FileOpened event when a file is opened
// BUG Using FileOpened flag with any OrDirectory actions
// BUG Using FileOpened flag with any OrDirectory event types
// causes an event flood and complete stoppage of events. The flag
// can be used with other file only flags or by itself
// without any errors/issues.
FileOpened Action = unix.FAN_OPEN
FileOpened EventType = unix.FAN_OPEN

// FileOrDirectoryOpened event when a file or directory is opened
// BUG Using FileOrDirectoryOpened causes an event flood and complete
// stoppage of events. The flag by itself without any errors/issues.
FileOrDirectoryOpened Action = unix.FAN_OPEN | unix.FAN_ONDIR
FileOrDirectoryOpened EventType = unix.FAN_OPEN | unix.FAN_ONDIR

// FileOpenedForExec event when a file is opened with the intent to be executed.
// Requires Linux kernel 5.0 or later
FileOpenedForExec Action = unix.FAN_OPEN_EXEC
FileOpenedForExec EventType = unix.FAN_OPEN_EXEC

// FileAttribChanged event when a file attribute has changed
// Requires Linux kernel 5.1 or later (requires FID)
FileAttribChanged Action = unix.FAN_ATTRIB
FileAttribChanged EventType = unix.FAN_ATTRIB

// FileOrDirectoryAttribChanged event when a file or directory attribute has changed
// Requires Linux kernel 5.1 or later (requires FID)
FileOrDirectoryAttribChanged Action = unix.FAN_ATTRIB | unix.FAN_ONDIR
FileOrDirectoryAttribChanged EventType = unix.FAN_ATTRIB | unix.FAN_ONDIR

// FileCreated event when file a has been created
// Requires Linux kernel 5.1 or later (requires FID)
// BUG FileCreated does not work with FileClosed, FileClosedAfterWrite or FileClosedWithNoWrite
FileCreated Action = unix.FAN_CREATE
FileCreated EventType = unix.FAN_CREATE

// FileOrDirectoryCreated event when a file or directory has been created
// Requires Linux kernel 5.1 or later (requires FID)
FileOrDirectoryCreated Action = unix.FAN_CREATE | unix.FAN_ONDIR
FileOrDirectoryCreated EventType = unix.FAN_CREATE | unix.FAN_ONDIR

// FileDeleted event when file a has been deleted
// Requires Linux kernel 5.1 or later (requires FID)
FileDeleted Action = unix.FAN_DELETE
FileDeleted EventType = unix.FAN_DELETE

// FileOrDirectoryDeleted event when a file or directory has been deleted
// Requires Linux kernel 5.1 or later (requires FID)
FileOrDirectoryDeleted Action = unix.FAN_DELETE | unix.FAN_ONDIR
FileOrDirectoryDeleted EventType = unix.FAN_DELETE | unix.FAN_ONDIR

// WatchedFileDeleted event when a watched file has been deleted
// Requires Linux kernel 5.1 or later (requires FID)
WatchedFileDeleted Action = unix.FAN_DELETE_SELF
WatchedFileDeleted EventType = unix.FAN_DELETE_SELF

// WatchedFileOrDirectoryDeleted event when a watched file or directory has been deleted
// Requires Linux kernel 5.1 or later (requires FID)
WatchedFileOrDirectoryDeleted Action = unix.FAN_DELETE_SELF | unix.FAN_ONDIR
WatchedFileOrDirectoryDeleted EventType = unix.FAN_DELETE_SELF | unix.FAN_ONDIR

// FileMovedFrom event when a file has been moved from the watched directory
// Requires Linux kernel 5.1 or later (requires FID)
FileMovedFrom Action = unix.FAN_MOVED_FROM
FileMovedFrom EventType = unix.FAN_MOVED_FROM

// FileOrDirectoryMovedFrom event when a file or directory has been moved from the watched directory
// Requires Linux kernel 5.1 or later (requires FID)
FileOrDirectoryMovedFrom Action = unix.FAN_MOVED_FROM | unix.FAN_ONDIR
FileOrDirectoryMovedFrom EventType = unix.FAN_MOVED_FROM | unix.FAN_ONDIR

// FileMovedTo event when a file has been moved to the watched directory
// Requires Linux kernel 5.1 or later (requires FID)
FileMovedTo Action = unix.FAN_MOVED_TO
FileMovedTo EventType = unix.FAN_MOVED_TO

// FileOrDirectoryMovedTo event when a file or directory has been moved to the watched directory
// Requires Linux kernel 5.1 or later (requires FID)
FileOrDirectoryMovedTo Action = unix.FAN_MOVED_TO | unix.FAN_ONDIR
FileOrDirectoryMovedTo EventType = unix.FAN_MOVED_TO | unix.FAN_ONDIR

// WatchedFileMoved event when a watched file has moved
// Requires Linux kernel 5.1 or later (requires FID)
WatchedFileMoved Action = unix.FAN_MOVE_SELF
WatchedFileMoved EventType = unix.FAN_MOVE_SELF

// WatchedFileOrDirectoryMoved event when a watched file or directory has moved
// Requires Linux kernel 5.1 or later (requires FID)
WatchedFileOrDirectoryMoved Action = unix.FAN_MOVE_SELF | unix.FAN_ONDIR
WatchedFileOrDirectoryMoved EventType = unix.FAN_MOVE_SELF | unix.FAN_ONDIR
)
Loading

0 comments on commit e1329dc

Please sign in to comment.