From 3850a341141ca83562022478ed4af769b7c320b1 Mon Sep 17 00:00:00 2001 From: Nick Santos Date: Wed, 22 Aug 2018 15:59:46 -0400 Subject: [PATCH] watch: fix a segfault on linux (#148) --- pkg/watch/notify_test.go | 33 +++++++++++++++++++++++++++++++++ pkg/watch/watcher_linux.go | 24 +++++++++++++++++++----- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/pkg/watch/notify_test.go b/pkg/watch/notify_test.go index 421f4eec4..90d1578d4 100644 --- a/pkg/watch/notify_test.go +++ b/pkg/watch/notify_test.go @@ -240,6 +240,39 @@ func TestSingleFile(t *testing.T) { f.assertEvents(path) } +func TestWriteBrokenLink(t *testing.T) { + f := newNotifyFixture(t) + defer f.tearDown() + + link := filepath.Join(f.watched.Path(), "brokenLink") + missingFile := filepath.Join(f.watched.Path(), "missingFile") + err := os.Symlink(missingFile, link) + if err != nil { + t.Fatal(err) + } + + f.assertEvents(link) +} + +func TestWriteGoodLink(t *testing.T) { + f := newNotifyFixture(t) + defer f.tearDown() + + goodFile := filepath.Join(f.watched.Path(), "goodFile") + err := ioutil.WriteFile(goodFile, []byte("hello"), 0644) + if err != nil { + t.Fatal(err) + } + + link := filepath.Join(f.watched.Path(), "goodFileSymlink") + err = os.Symlink(goodFile, link) + if err != nil { + t.Fatal(err) + } + + f.assertEvents(goodFile, link) +} + type notifyFixture struct { t *testing.T root *TempDir diff --git a/pkg/watch/watcher_linux.go b/pkg/watch/watcher_linux.go index 16beef1b4..20e2f2fb8 100644 --- a/pkg/watch/watcher_linux.go +++ b/pkg/watch/watcher_linux.go @@ -79,7 +79,17 @@ func (d *linuxNotify) Errors() chan error { func (d *linuxNotify) loop() { for e := range d.events { - if e.Op&fsnotify.Create == fsnotify.Create && isDir(e.Name) { + isCreateOp := e.Op&fsnotify.Create == fsnotify.Create + shouldWalk := false + if isCreateOp { + isDir, err := isDir(e.Name) + if err != nil { + log.Printf("Error stat-ing file %s: %s", e.Name, err) + continue + } + shouldWalk = isDir + } + if shouldWalk { err := filepath.Walk(e.Name, func(path string, mode os.FileInfo, err error) error { if err != nil { return err @@ -140,10 +150,14 @@ func NewWatcher() (*linuxNotify, error) { return wmw, nil } -func isDir(pth string) bool { - fi, _ := os.Stat(pth) - - return fi.IsDir() +func isDir(pth string) (bool, error) { + fi, err := os.Lstat(pth) + if os.IsNotExist(err) { + return false, nil + } else if err != nil { + return false, err + } + return fi.IsDir(), nil } func checkInotifyLimits() error {