Skip to content

Commit

Permalink
windows: ignore file attributes
Browse files Browse the repository at this point in the history
On Windows a FILE_ACTION_MODIFIED event (i.e. a Write event) is
triggered on file attribute changes, rather than some dedicates
ATTRIBUTE_CHANGED event. Looking at the docs, I don't really see a way
to distinguish between "real" write events and attribute changes. This is
very odd, but seems to be how the ReadDirectoryChangesW() API works.

The only way I can see to distinguish between the two events is to set
up two filters: one with a FILE_NOTIFY_CHANGE_ATTRIBUTES, and one
without. But that seems overly complex, and no one asked to get Chmod
events for Windows; it's not really all that interesting on Windows
anyway.

The problem is that some software (anti-virus, backup software, etc.)
can issue lots of attribute changes, causing a lot of "fake" Write
events.

So remove the FILE_NOTIFY_CHANGE_ATTRIBUTES and sysFSATTRIB flags.

This was adapted from some changes done in the tilt-dev/fsnotify fork;
specifically:
f6dca35
3ee2a2f

Fixes #487
  • Loading branch information
arp242 committed Oct 13, 2022
1 parent d892de1 commit 6ffde91
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 19 deletions.
7 changes: 0 additions & 7 deletions backend_windows.go
Expand Up @@ -294,7 +294,6 @@ func (w *Watcher) WatchList() []string {
// This should all be removed at some point, and just use windows.FILE_NOTIFY_*
const (
sysFSALLEVENTS = 0xfff
sysFSATTRIB = 0x4
sysFSCREATE = 0x100
sysFSDELETE = 0x200
sysFSDELETESELF = 0x400
Expand All @@ -320,9 +319,6 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM {
e.Op |= Rename
}
if mask&sysFSATTRIB == sysFSATTRIB {
e.Op |= Chmod
}
return e
}

Expand Down Expand Up @@ -735,9 +731,6 @@ func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
if mask&sysFSMODIFY != 0 {
m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
}
if mask&sysFSATTRIB != 0 {
m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES
}
if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 {
m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME
}
Expand Down
15 changes: 15 additions & 0 deletions backend_windows_test.go
Expand Up @@ -50,3 +50,18 @@ func TestRemoveState(t *testing.T) {
}
check(0)
}

func TestWindowsNoAttributeChanges(t *testing.T) {
tmp := t.TempDir()
file := filepath.Join(tmp, "TestFsnotifyEventsExisting.testfile")

touch(t, file) // Create a file before watching directory
w := newCollector(t, tmp)
w.collect(t)
chmod(t, 0o400, file) // Make the file read-only, which is an attribute change

have := w.stop(t)
if len(have) != 0 {
t.Fatalf("should not have received any events, received:\n%s", have)
}
}
12 changes: 0 additions & 12 deletions fsnotify_test.go
Expand Up @@ -252,20 +252,12 @@ func TestWatchCreate(t *testing.T) {
symlink(t, filepath.Join(tmp, "file"), tmp, "link")
}, `
create /link
windows:
create /link
write /link
`},
{"create new symlink to directory", func(t *testing.T, w *Watcher, tmp string) {
addWatch(t, w, tmp)
symlink(t, tmp, tmp, "link")
}, `
create /link
windows:
create /link
write /link
`},

// FIFO
Expand Down Expand Up @@ -548,10 +540,6 @@ func TestWatchSymlink(t *testing.T) {
}, `
create /link
windows:
create /link
write /link
# No events at all on Dragonfly
# TODO: should fix this.
dragonfly:
Expand Down

0 comments on commit 6ffde91

Please sign in to comment.