]> go.fuhry.dev Git - fsnotify.git/commitdiff
windows: ignore file attributes (#520)
authorMartin Tournoij <martin@arp242.net>
Fri, 14 Oct 2022 16:34:54 +0000 (18:34 +0200)
committerGitHub <noreply@github.com>
Fri, 14 Oct 2022 16:34:54 +0000 (18:34 +0200)
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 the tilt-dev/fsnotify fork:
https://github.com/tilt-dev/fsnotify/pull/8

Fixes #487

backend_windows.go
backend_windows_test.go
fsnotify_test.go

index 5e62b4b4080aaa3bc9ab7e7604d363d19fe5bb28..1bdadf3a2b31209bd9b58ad5775098f7ff02ff89 100644 (file)
@@ -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
@@ -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
 }
 
@@ -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
        }
index 213f14cb5db893502ec349195515959652879393..dd593dc26019cc80cce7bac821fc8272753046c7 100644 (file)
@@ -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)
+       }
+}
index 0a3f778917ff21753d919252c4ff4402cd632626..d2710b8d0d0055485d4739fbb03017899a334808 100644 (file)
@@ -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
@@ -519,10 +511,6 @@ func TestWatchSymlink(t *testing.T) {
                }, `
                        create /link
 
-                       windows:
-                               create    /link
-                               write     /link
-
                        # No events at all on Dragonfly
                        # TODO: should fix this.
                        dragonfly: