Skip to content

Commit 57f8918

Browse files
committed
Revert "Fix DeleteWatch/UnwatchMount does not work"
This reverts commit 6e8fbeb.
1 parent 6e8fbeb commit 57f8918

File tree

3 files changed

+25
-125
lines changed

3 files changed

+25
-125
lines changed

fanotify_api.go

Lines changed: 25 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@ type Listener struct {
7373
fd int
7474
// flags passed to fanotify_init
7575
flags uint
76-
// markMask current fanotify mark mask
77-
markMask uint64
7876
// mount fd is the file descriptor of the mountpoint
7977
mountpoint *os.File
8078
kernelMajorVersion int
@@ -205,23 +203,14 @@ func (l *Listener) Stop() {
205203
// for - [FileCreated], [FileAttribChanged], [FileMovedTo], [FileMovedFrom], [WatchedFileDeleted],
206204
// [WatchedFileOrDirectoryDeleted], [FileDeleted], [FileOrDirectoryDeleted]
207205
func (l *Listener) WatchMount(eventTypes EventType) error {
208-
mask := l.getMaskAfterAdd(eventTypes)
209-
l.clearWatch()
210-
l.markMask = uint64(mask)
211-
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_ADD|unix.FAN_MARK_MOUNT, uint64(mask))
206+
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_ADD|unix.FAN_MARK_MOUNT, uint64(eventTypes))
212207
}
213208

214209
// UnwatchMount removes the notification marks for the entire mount point.
215210
// This method returns an [ErrWatchPath] if the listener was not initialized to monitor
216211
// the entire mount point. To unmark specific files or directories use [DeleteWatch] method.
217212
func (l *Listener) UnwatchMount(eventTypes EventType) error {
218-
if l.markMask == 0 {
219-
return l.clearWatch()
220-
}
221-
remaining := l.getMaskAfterRemove(eventTypes)
222-
l.clearWatch()
223-
l.markMask = uint64(remaining)
224-
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_ADD|unix.FAN_MARK_MOUNT, uint64(remaining))
213+
return l.fanotifyMark(l.mountpoint.Name(), unix.FAN_MARK_REMOVE|unix.FAN_MARK_MOUNT, uint64(eventTypes))
225214
}
226215

227216
// AddWatch adds or modifies the fanotify mark for the specified path.
@@ -232,46 +221,14 @@ func (l *Listener) UnwatchMount(eventTypes EventType) error {
232221
// - [FileCreated] cannot be or-ed / combined with [FileClosed]. The fanotify system does not generate any event for this combination.
233222
// - [FileOpened] with any of the event types containing OrDirectory causes an event flood for the directory and then stopping raising any events at all.
234223
// - [FileOrDirectoryOpened] with any of the other event types causes an event flood for the directory and then stopping raising any events at all.
235-
//
236-
// NOTE:
237-
// Any event type that contains "OrDirectory" applies the OrDirectory mask to any other applicable
238-
// marks. For example adding [FileDeleted] and [FileOrDirectoryOpened] will apply "OrDirectory" to
239-
// [FileDeleted] thus the resulting mask will be set to [FileOrDirectoryOpened] and [FileOrDirectoryDeleted]
240224
func (l *Listener) AddWatch(path string, eventTypes EventType) error {
241225
if l == nil {
242226
panic("nil listener")
243227
}
244228
if l.entireMount {
245229
return os.ErrInvalid
246230
}
247-
mask := l.getMaskAfterAdd(eventTypes)
248-
l.clearWatch()
249-
l.markMask = uint64(mask)
250-
return l.fanotifyMark(path, unix.FAN_MARK_ADD, uint64(mask|unix.FAN_EVENT_ON_CHILD))
251-
}
252-
253-
// DeleteWatch removes/unmarks the fanotify mark for the specified path.
254-
// Calling DeleteWatch on the listener initialized to monitor the entire mount point
255-
// results in [os.ErrInvalid]. Use [UnwatchMount] for deleting marks on the mount point.
256-
func (l *Listener) DeleteWatch(parentDir string, eventTypes EventType) error {
257-
if l.entireMount {
258-
return os.ErrInvalid
259-
}
260-
if l.markMask == 0 {
261-
return l.clearWatch()
262-
}
263-
remaining := l.getMaskAfterRemove(eventTypes)
264-
l.clearWatch()
265-
l.markMask = uint64(remaining)
266-
return l.fanotifyMark(parentDir, unix.FAN_MARK_ADD, uint64(remaining|unix.FAN_EVENT_ON_CHILD))
267-
}
268-
269-
// ClearWatch stops watching for all event types
270-
func (l *Listener) ClearWatch() error {
271-
if l == nil {
272-
panic("nil listener")
273-
}
274-
return l.clearWatch()
231+
return l.fanotifyMark(path, unix.FAN_MARK_ADD, uint64(eventTypes|unix.FAN_EVENT_ON_CHILD))
275232
}
276233

277234
// Allow sends an "allowed" response to the permission request event.
@@ -294,6 +251,28 @@ func (l *Listener) Deny(e Event) {
294251
unix.Write(l.fd, buf.Bytes())
295252
}
296253

254+
// DeleteWatch removes/unmarks the fanotify mark for the specified path.
255+
// Calling DeleteWatch on the listener initialized to monitor the entire mount point
256+
// results in [os.ErrInvalid]. Use [UnwatchMount] for deleting marks on the mount point.
257+
func (l *Listener) DeleteWatch(parentDir string, eventTypes EventType) error {
258+
if l.entireMount {
259+
return os.ErrInvalid
260+
}
261+
return l.fanotifyMark(parentDir, unix.FAN_MARK_REMOVE, uint64(eventTypes|unix.FAN_EVENT_ON_CHILD))
262+
}
263+
264+
// ClearWatch stops watching for all event types
265+
func (l *Listener) ClearWatch() error {
266+
if l == nil {
267+
panic("nil listener")
268+
}
269+
if err := unix.FanotifyMark(l.fd, unix.FAN_MARK_FLUSH, 0, -1, ""); err != nil {
270+
return err
271+
}
272+
l.watches = make(map[string]bool)
273+
return nil
274+
}
275+
297276
// Has returns true if event types (e) contains the passed in event type (et).
298277
func (e EventType) Has(et EventType) bool {
299278
return e&et == et

fanotify_event.go

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -204,22 +204,6 @@ func fanotifyEventOK(meta *unix.FanotifyEventMetadata, n int) bool {
204204
int(meta.Event_len) <= n)
205205
}
206206

207-
func (l *Listener) getMaskAfterRemove(removeMask EventType) EventType {
208-
if l.markMask == 0 {
209-
return EventType(0)
210-
}
211-
mask := EventType(l.markMask) ^ removeMask
212-
return mask
213-
}
214-
215-
func (l *Listener) getMaskAfterAdd(addMask EventType) EventType {
216-
if l.markMask == 0 {
217-
return addMask
218-
}
219-
mask := EventType(l.markMask) | addMask
220-
return mask
221-
}
222-
223207
// permissionType is ignored when isNotificationListener is true.
224208
func newListener(mountpointPath string, entireMount bool, notificationOnly bool, permissionType PermissionType) (*Listener, error) {
225209

@@ -307,15 +291,6 @@ func newListener(mountpointPath string, entireMount bool, notificationOnly bool,
307291
return listener, nil
308292
}
309293

310-
func (l *Listener) clearWatch() error {
311-
if err := unix.FanotifyMark(l.fd, unix.FAN_MARK_FLUSH, 0, -1, ""); err != nil {
312-
return err
313-
}
314-
l.watches = make(map[string]bool)
315-
l.markMask = 0
316-
return nil
317-
}
318-
319294
func (l *Listener) fanotifyMark(path string, flags uint, mask uint64) error {
320295
if l == nil {
321296
panic("nil listener")

fanotify_test.go

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -410,60 +410,6 @@ func TestMultipleEvents(t *testing.T) {
410410
}
411411
}
412412

413-
func TestAddPathBeforeWatchStart(t *testing.T) {
414-
l, err := NewListener("/", false, PermissionNone)
415-
assert.Nil(t, err)
416-
assert.NotNil(t, l)
417-
go l.Start()
418-
defer l.Stop()
419-
420-
watchDir := t.TempDir()
421-
422-
testFile := fmt.Sprintf("%s/test.txt", watchDir)
423-
pid, err := runAsCmd("touch", testFile) // create file
424-
assert.Nil(t, err)
425-
select {
426-
case <-time.After(100 * time.Millisecond):
427-
t.Logf("FileCreated Event not received as expected")
428-
case event := <-l.Events:
429-
t.Errorf("Timeout Error: Unexpected FileCreated event received (%s)", event)
430-
}
431-
touchPid := pid
432-
433-
eventTypes := FileModified.Or(FileDeleted)
434-
l.AddWatch(watchDir, eventTypes)
435-
// modify file
436-
os.WriteFile(testFile, []byte("test string"), 0666)
437-
pid = os.Getpid()
438-
select {
439-
case <-time.After(100 * time.Millisecond):
440-
t.Error("Timeout Error: FileModified event not received")
441-
case event := <-l.Events:
442-
assert.Equal(t, fmt.Sprintf("%s/%s", event.Path, event.FileName), testFile)
443-
assert.Equal(t, event.Pid, pid)
444-
assert.True(t, event.EventTypes.Has(FileModified))
445-
t.Logf("Received: (%s)", event)
446-
}
447-
448-
t.Logf("Pids: Self(%d), Touch(%d)", pid, touchPid)
449-
// NOTE: os.WriteFile sends two modify events; so draining them
450-
for len(l.Events) > 0 {
451-
e := <-l.Events
452-
t.Logf("Drain-Event: (%s)", e)
453-
}
454-
pid, err = runAsCmd("rm", "-f", testFile)
455-
assert.Nil(t, err)
456-
select {
457-
case <-time.After(100 * time.Millisecond):
458-
t.Error("Timeout Error: FileDeleted event not received")
459-
case event := <-l.Events:
460-
assert.Equal(t, fmt.Sprintf("%s/%s", event.Path, event.FileName), testFile)
461-
assert.Equal(t, event.Pid, pid)
462-
assert.True(t, event.EventTypes.Has(FileDeleted))
463-
t.Logf("Received: (%s)", event)
464-
}
465-
}
466-
467413
// FileCreated and FileClosed combination does not raise any events
468414
func TestWithCapSysAdmMarkCreateCloseBug(t *testing.T) {
469415
if *bug {

0 commit comments

Comments
 (0)