]> go.fuhry.dev Git - fsnotify.git/commitdiff
Revert "Add AddRaw to not follow symlinks + Fix link folloing on Windows (#289)"
authorNathan Youngman <4566+nathany@users.noreply.github.com>
Tue, 24 Aug 2021 19:09:43 +0000 (13:09 -0600)
committerNathan Youngman <4566+nathany@users.noreply.github.com>
Tue, 24 Aug 2021 19:25:33 +0000 (13:25 -0600)
This reverts commit e2e95171bc7c7402864e613c8b00a768fbcc2380.

README.md
fen.go
fsnotify.go
fsnotify_test.go
inotify.go
inotify_test.go
integration_test.go
kqueue.go
windows.go

index 670f2cfc2636dd5c47848997b0356bda7d4856c9..df57b1b282c6714f111f85d2062d2cee90efd47c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -72,18 +72,10 @@ func main() {
                }
        }()
 
-       // if this is a link, it will follow all the links and watch the file pointed to
        err = watcher.Add("/tmp/foo")
        if err != nil {
                log.Fatal(err)
        }
-
-       // this will watch the link, rather than the file it points to
-       err = watcher.AddRaw("/tmp/link")
-       if err != nil {
-               log.Fatal(err)
-       }
-
        <-done
 }
 ```
@@ -98,10 +90,6 @@ See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_t
 
 ## FAQ
 
-**Are symlinks resolved?**
-Symlinks are implicitly resolved by [`filepath.EvalSymlinks(path)`](https://golang.org/pkg/path/filepath/#EvalSymlinks) when `watcher.Add(name)` is used. If that is not desired, you can use `watcher.AddRaw(name)` to not follow any symlinks before watching. See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go).
-
-
 **When a file is moved to another directory is it still being watched?**
 
 No (it shouldn't be, unless you are watching where it was moved to).
@@ -139,3 +127,4 @@ fsnotify requires support from underlying OS to work. The current NFS protocol d
 
 * [notify](https://github.com/rjeczalik/notify)
 * [fsevents](https://github.com/fsnotify/fsevents)
+
diff --git a/fen.go b/fen.go
index 325ece593f366e68bb0b71af7526a4da11df2198..b3ac3d8f55faf53adf88849af1cb884946a51917 100644 (file)
--- a/fen.go
+++ b/fen.go
@@ -27,8 +27,8 @@ func (w *Watcher) Close() error {
        return nil
 }
 
-// AddRaw starts watching the named file or directory (non-recursively). Symlinks are not implicitly resolved.
-func (w *Watcher) AddRaw(name string) error {
+// Add starts watching the named file or directory (non-recursively).
+func (w *Watcher) Add(name string) error {
        return nil
 }
 
index 5e240dc2a35a07f44b0739d6ee978a2453ec1cba..0f4ee52e8aa202bc8c6d89eaa2c5f4efd554f69e 100644 (file)
@@ -12,7 +12,6 @@ import (
        "bytes"
        "errors"
        "fmt"
-       "path/filepath"
 )
 
 // Event represents a single file system notification.
@@ -68,19 +67,3 @@ func (e Event) String() string {
 var (
        ErrEventOverflow = errors.New("fsnotify queue overflow")
 )
-
-// Add starts watching the named file or directory (non-recursively). Symlinks are implicitly resolved.
-func (w *Watcher) Add(name string) error {
-       rawPath, err := filepath.EvalSymlinks(name)
-       if err != nil {
-               return fmt.Errorf("error resolving %#v: %s", name, err)
-       }
-       err = w.AddRaw(rawPath)
-       if err != nil {
-               if name != rawPath {
-                       return fmt.Errorf("error adding %#v for %#v: %s", rawPath, name, err)
-               }
-               return err
-       }
-       return nil
-}
index 5751fbabd123c9d01078ae872f55b6142427e684..51aa49c58f551258efc51bd8b68f43ee3688e15a 100644 (file)
@@ -52,7 +52,7 @@ func TestWatcherClose(t *testing.T) {
 
        name := tempMkFile(t, "")
        w := newWatcher(t)
-       err := w.AddRaw(name)
+       err := w.Add(name)
        if err != nil {
                t.Fatal(err)
        }
index 994daf091b2702ba2b11f9c50538f379805d4981..eb87699b5b4c15494d394afbd9dd689341a38e9b 100644 (file)
@@ -88,8 +88,8 @@ func (w *Watcher) Close() error {
        return nil
 }
 
-// AddRaw starts watching the named file or directory (non-recursively). Symlinks are not implicitly resolved.
-func (w *Watcher) AddRaw(name string) error {
+// Add starts watching the named file or directory (non-recursively).
+func (w *Watcher) Add(name string) error {
        name = filepath.Clean(name)
        if w.isClosed() {
                return errors.New("inotify instance already closed")
@@ -97,7 +97,7 @@ func (w *Watcher) AddRaw(name string) error {
 
        const agnosticEvents = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
                unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
-               unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF | unix.IN_DONT_FOLLOW
+               unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
 
        var flags uint32 = agnosticEvents
 
index 8cd1cfd5ee3f1556d044bd72365f6babeb7ef650..90c82b8ef7e0fce45f0e33ec95bc01821d2e4c2a 100644 (file)
@@ -54,7 +54,7 @@ func TestInotifyCloseSlightlyLaterWithWatch(t *testing.T) {
        if err != nil {
                t.Fatalf("Failed to create watcher")
        }
-       w.AddRaw(testDir)
+       w.Add(testDir)
 
        // Wait until readEvents has reached unix.Read, and Close.
        <-time.After(50 * time.Millisecond)
@@ -74,7 +74,7 @@ func TestInotifyCloseAfterRead(t *testing.T) {
                t.Fatalf("Failed to create watcher")
        }
 
-       err = w.AddRaw(testDir)
+       err = w.Add(testDir)
        if err != nil {
                t.Fatalf("Failed to add .")
        }
@@ -121,7 +121,7 @@ func TestInotifyCloseCreate(t *testing.T) {
        }
        defer w.Close()
 
-       err = w.AddRaw(testDir)
+       err = w.Add(testDir)
        if err != nil {
                t.Fatalf("Failed to add testDir: %v", err)
        }
@@ -149,7 +149,7 @@ func TestInotifyCloseCreate(t *testing.T) {
        }
 
        <-time.After(50 * time.Millisecond)
-       err = w.AddRaw(testDir)
+       err = w.Add(testDir)
        if err != nil {
                t.Fatalf("Error adding testDir again: %v", err)
        }
@@ -170,7 +170,7 @@ func TestInotifyStress(t *testing.T) {
        }
        defer w.Close()
 
-       err = w.AddRaw(testDir)
+       err = w.Add(testDir)
        if err != nil {
                t.Fatalf("Failed to add testDir: %v", err)
        }
@@ -290,7 +290,7 @@ func TestInotifyRemoveTwice(t *testing.T) {
        }
        defer w.Close()
 
-       err = w.AddRaw(testFile)
+       err = w.Add(testFile)
        if err != nil {
                t.Fatalf("Failed to add testFile: %v", err)
        }
@@ -332,7 +332,7 @@ func TestInotifyInnerMapLength(t *testing.T) {
        }
        defer w.Close()
 
-       err = w.AddRaw(testFile)
+       err = w.Add(testFile)
        if err != nil {
                t.Fatalf("Failed to add testFile: %v", err)
        }
@@ -384,7 +384,7 @@ func TestInotifyOverflow(t *testing.T) {
                        t.Fatalf("Cannot create subdir: %v", err)
                }
 
-               err = w.AddRaw(testSubdir)
+               err = w.Add(testSubdir)
                if err != nil {
                        t.Fatalf("Failed to add subdir: %v", err)
                }
index cf1b8cff8a9f89da5bfef9b6afd71083196af657..fc09e03f78141d81d0f0c3c1d5e1173bcb54b89d 100644 (file)
@@ -66,8 +66,8 @@ func newWatcher(t *testing.T) *Watcher {
 
 // addWatch adds a watch for a directory
 func addWatch(t *testing.T, watcher *Watcher, dir string) {
-       if err := watcher.AddRaw(dir); err != nil {
-               t.Fatalf("watcher.AddRaw(%q) failed: %s", dir, err)
+       if err := watcher.Add(dir); err != nil {
+               t.Fatalf("watcher.Add(%q) failed: %s", dir, err)
        }
 }
 
@@ -1008,74 +1008,11 @@ func TestFsnotifyClose(t *testing.T) {
        testDir := tempMkdir(t)
        defer os.RemoveAll(testDir)
 
-       if err := watcher.AddRaw(testDir); err == nil {
+       if err := watcher.Add(testDir); err == nil {
                t.Fatal("expected error on Watch() after Close(), got nil")
        }
 }
 
-func TestSymlinkNotResolved(t *testing.T) {
-       testDir := tempMkdir(t)
-       file1 := filepath.Join(testDir, "file1")
-       file2 := filepath.Join(testDir, "file2")
-       link := filepath.Join(testDir, "link")
-
-       f1, err := os.Create(file1)
-       if err != nil {
-               t.Fatalf("Failed to create file1: %s", err)
-       }
-       defer f1.Close()
-       if _, err := os.Create(file2); err != nil {
-               t.Fatalf("Failed to create file2: %s", err)
-       }
-
-       // symlink works for Windows too
-       if err := os.Symlink(file1, link); err != nil {
-               t.Fatalf("Failed to create symlink: %s", err)
-       }
-
-       w, err := NewWatcher()
-       if err != nil {
-               t.Fatalf("Failed to create watcher")
-       }
-
-       err = w.AddRaw(link)
-       if err != nil {
-               t.Fatalf("Failed to add link: %s", err)
-       }
-
-       // change file 1 - no event
-       f1.Write([]byte("Hello"))
-       f1.Sync()
-       // XXX(Code0x58): doing a create here shows a CHMOD event on mac - is that an issue?
-
-       select {
-       case event := <-w.Events:
-               t.Fatalf("Event from watcher: %v", event)
-       case err := <-w.Errors:
-               t.Fatalf("Error from watcher: %v", err)
-       case <-time.After(50 * time.Millisecond):
-       }
-
-       // ~atomic link change event
-       tmpLink := filepath.Join(testDir, "tmp-link")
-       if err := os.Symlink(file2, tmpLink); err != nil {
-               t.Fatalf("Failed to create symlink: %s", err)
-       }
-
-       if err := os.Rename(tmpLink, link); err != nil {
-               t.Fatalf("Failed to replace symlink: %s", err)
-       }
-
-       select {
-       case _ = <-w.Events:
-       case err := <-w.Errors:
-               t.Fatalf("Error from watcher: %v", err)
-       case <-time.After(50 * time.Millisecond):
-               t.Fatalf("Took too long to wait for event")
-       }
-
-}
-
 func TestFsnotifyFakeSymlink(t *testing.T) {
        if runtime.GOOS == "windows" {
                t.Skip("symlinks don't work on Windows.")
@@ -1237,7 +1174,7 @@ func TestClose(t *testing.T) {
        defer os.RemoveAll(testDir)
 
        watcher := newWatcher(t)
-       if err := watcher.AddRaw(testDir); err != nil {
+       if err := watcher.Add(testDir); err != nil {
                t.Fatalf("Expected no error on Add, got %v", err)
        }
        err := watcher.Close()
@@ -1258,7 +1195,7 @@ func TestRemoveWithClose(t *testing.T) {
                tempFiles = append(tempFiles, tempMkFile(t, testDir))
        }
        watcher := newWatcher(t)
-       if err := watcher.AddRaw(testDir); err != nil {
+       if err := watcher.Add(testDir); err != nil {
                t.Fatalf("Expected no error on Add, got %v", err)
        }
        startC, stopC := make(chan struct{}), make(chan struct{})
index caecacb51bbd6a9ef4a47174c9b079e752571edd..368f5b790d4de625f4e953dfb1001f60590d27f3 100644 (file)
--- a/kqueue.go
+++ b/kqueue.go
@@ -91,8 +91,8 @@ func (w *Watcher) Close() error {
        return nil
 }
 
-// AddRaw starts watching the named file or directory (non-recursively). Symlinks are not implicitly resolved.
-func (w *Watcher) AddRaw(name string) error {
+// Add starts watching the named file or directory (non-recursively).
+func (w *Watcher) Add(name string) error {
        w.mu.Lock()
        w.externalWatches[name] = true
        w.mu.Unlock()
@@ -190,7 +190,33 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
                        return "", nil
                }
 
-               watchfd, err = unix.Open(name, openMode|unix.O_SYMLINK, 0700)
+               // Follow Symlinks
+               // Unfortunately, Linux can add bogus symlinks to watch list without
+               // issue, and Windows can't do symlinks period (AFAIK). To  maintain
+               // consistency, we will act like everything is fine. There will simply
+               // be no file events for broken symlinks.
+               // Hence the returns of nil on errors.
+               if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
+                       name, err = filepath.EvalSymlinks(name)
+                       if err != nil {
+                               return "", nil
+                       }
+
+                       w.mu.Lock()
+                       _, alreadyWatching = w.watches[name]
+                       w.mu.Unlock()
+
+                       if alreadyWatching {
+                               return name, nil
+                       }
+
+                       fi, err = os.Lstat(name)
+                       if err != nil {
+                               return "", nil
+                       }
+               }
+
+               watchfd, err = unix.Open(name, openMode, 0700)
                if watchfd == -1 {
                        return "", err
                }
index 7dd514816691c44485f47b531543c6a1e5b476e7..c02b75f7c374733c4c657215d59b1afd00dada9a 100644 (file)
@@ -64,8 +64,8 @@ func (w *Watcher) Close() error {
        return <-ch
 }
 
-// AddRaw starts watching the named file or directory (non-recursively). Symlinks are not implicitly resolved.
-func (w *Watcher) AddRaw(name string) error {
+// Add starts watching the named file or directory (non-recursively).
+func (w *Watcher) Add(name string) error {
        if w.isClosed {
                return errors.New("watcher already closed")
        }