diff --git a/lib/scanner/walk.go b/lib/scanner/walk.go index b46240b40..af3243a82 100644 --- a/lib/scanner/walk.go +++ b/lib/scanner/walk.go @@ -21,6 +21,7 @@ import ( "github.com/syncthing/syncthing/lib/events" "github.com/syncthing/syncthing/lib/fs" "github.com/syncthing/syncthing/lib/ignore" + "github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/protocol" "golang.org/x/text/unicode/norm" ) @@ -113,6 +114,10 @@ func (w *walker) walk(ctx context.Context) chan ScanResult { w.Filesystem.Walk(".", hashFiles) } else { for _, sub := range w.Subs { + if err := osutil.TraversesSymlink(w.Filesystem, filepath.Dir(sub)); err != nil { + l.Debugf("Skip walking %v as it is below a symlink", sub) + continue + } w.Filesystem.Walk(sub, hashFiles) } } diff --git a/lib/scanner/walk_test.go b/lib/scanner/walk_test.go index 5c01eba3d..b6df67b89 100644 --- a/lib/scanner/walk_test.go +++ b/lib/scanner/walk_test.go @@ -322,7 +322,7 @@ func TestWalkRootSymlink(t *testing.T) { } defer os.RemoveAll(tmp) - link := tmp + "/link" + link := filepath.Join(tmp, "link") dest, _ := filepath.Abs("testdata/dir1") if err := osutil.DebugSymlinkForTestsOnly(dest, link); err != nil { if runtime.GOOS == "windows" { @@ -333,13 +333,33 @@ func TestWalkRootSymlink(t *testing.T) { } } - // Scan it + // Scan root with symlink at FS root files := walkDir(fs.NewFilesystem(fs.FilesystemTypeBasic, link), ".", nil, nil, 0) // Verify that we got two files if len(files) != 2 { t.Errorf("expected two files, not %d", len(files)) } + + // Scan symlink below FS root + files = walkDir(fs.NewFilesystem(fs.FilesystemTypeBasic, tmp), "link", nil, nil, 0) + + // Verify that we got the one symlink, except on windows + if runtime.GOOS == "windows" { + if len(files) != 0 { + t.Errorf("expected no files, not %d", len(files)) + } + } else if len(files) != 1 { + t.Errorf("expected one file, not %d", len(files)) + } + + // Scan path below symlink + files = walkDir(fs.NewFilesystem(fs.FilesystemTypeBasic, tmp), filepath.Join("link", "cfile"), nil, nil, 0) + + // Verify that we get nothing + if len(files) != 0 { + t.Errorf("expected no files, not %d", len(files)) + } } func TestBlocksizeHysteresis(t *testing.T) {