From 15a3ec8fa1427dee28f941dd7724897e4f3ca953 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 3 Apr 2023 16:28:12 +0100 Subject: [PATCH] local: fix filtering of symlinks with -l/--links flag Before this fix, with the -l flag, the `.rclonelink` suffix wasn't being added to the file names before filtering by name. See #6855 --- backend/local/local.go | 10 ++--- backend/local/local_internal_test.go | 66 +++++++++++++++++++++------- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/backend/local/local.go b/backend/local/local.go index 48f646bce..984cd4910 100644 --- a/backend/local/local.go +++ b/backend/local/local.go @@ -540,11 +540,6 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e } mode = fi.Mode() } - // Don't include non directory if not included - // we leave directory filtering to the layer above - if useFilter && !fi.IsDir() && !filter.IncludeRemote(newRemote) { - continue - } if fi.IsDir() { // Ignore directories which are symlinks. These are junction points under windows which // are kind of a souped up symlink. Unix doesn't have directories which are symlinks. @@ -557,6 +552,11 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e if f.opt.TranslateSymlinks && fi.Mode()&os.ModeSymlink != 0 { newRemote += linkSuffix } + // Don't include non directory if not included + // we leave directory filtering to the layer above + if useFilter && !filter.IncludeRemote(newRemote) { + continue + } fso, err := f.newObjectWithInfo(newRemote, fi) if err != nil { return nil, err diff --git a/backend/local/local_internal_test.go b/backend/local/local_internal_test.go index 0fa78cd9f..7fcacaf33 100644 --- a/backend/local/local_internal_test.go +++ b/backend/local/local_internal_test.go @@ -397,7 +397,7 @@ func TestFilter(t *testing.T) { require.Equal(t, "[included]", fmt.Sprint(entries)) } -func TestFilterSymlink(t *testing.T) { +func testFilterSymlink(t *testing.T, copyLinks bool) { ctx := context.Background() r := fstest.NewRun(t) defer r.Finalise() @@ -411,15 +411,23 @@ func TestFilterSymlink(t *testing.T) { require.NoError(t, os.Symlink("included.dir", filepath.Join(r.LocalName, "included.dir.link"))) require.NoError(t, os.Symlink("dangling", filepath.Join(r.LocalName, "dangling.link"))) - // Set fs into "-L" mode - f.opt.FollowSymlinks = true - f.opt.TranslateSymlinks = false - f.lstat = os.Stat - - // Set fs into "-l" mode - // f.opt.FollowSymlinks = false - // f.opt.TranslateSymlinks = true - // f.lstat = os.Lstat + defer func() { + // Reset -L/-l mode + f.opt.FollowSymlinks = false + f.opt.TranslateSymlinks = false + f.lstat = os.Lstat + }() + if copyLinks { + // Set fs into "-L" mode + f.opt.FollowSymlinks = true + f.opt.TranslateSymlinks = false + f.lstat = os.Stat + } else { + // Set fs into "-l" mode + f.opt.FollowSymlinks = false + f.opt.TranslateSymlinks = true + f.lstat = os.Lstat + } // Check set up for filtering assert.True(t, f.Features().FilterAware) @@ -431,21 +439,35 @@ func TestFilterSymlink(t *testing.T) { // Add a filter ctx, fi := filter.AddConfig(ctx) require.NoError(t, fi.AddRule("+ included.file")) - require.NoError(t, fi.AddRule("+ included.file.link")) require.NoError(t, fi.AddRule("+ included.dir/**")) - require.NoError(t, fi.AddRule("+ included.dir.link/**")) + if copyLinks { + require.NoError(t, fi.AddRule("+ included.file.link")) + require.NoError(t, fi.AddRule("+ included.dir.link/**")) + } else { + require.NoError(t, fi.AddRule("+ included.file.link.rclonelink")) + require.NoError(t, fi.AddRule("+ included.dir.link.rclonelink")) + } require.NoError(t, fi.AddRule("- *")) // Check listing without use filter flag entries, err := f.List(ctx, "") require.NoError(t, err) - // Check 1 global errors one for each dangling symlink - assert.Equal(t, int64(1), accounting.Stats(ctx).GetErrors(), "global errors found") + if copyLinks { + // Check 1 global errors one for each dangling symlink + assert.Equal(t, int64(1), accounting.Stats(ctx).GetErrors(), "global errors found") + } else { + // Check 0 global errors as dangling symlink copied properly + assert.Equal(t, int64(0), accounting.Stats(ctx).GetErrors(), "global errors found") + } accounting.Stats(ctx).ResetErrors() sort.Sort(entries) - require.Equal(t, "[included.dir included.dir.link included.file included.file.link]", fmt.Sprint(entries)) + if copyLinks { + require.Equal(t, "[included.dir included.dir.link included.file included.file.link]", fmt.Sprint(entries)) + } else { + require.Equal(t, "[dangling.link.rclonelink included.dir included.dir.link.rclonelink included.file included.file.link.rclonelink]", fmt.Sprint(entries)) + } // Add user filter flag ctx = filter.SetUseFilter(ctx, true) @@ -456,7 +478,11 @@ func TestFilterSymlink(t *testing.T) { assert.Equal(t, int64(0), accounting.Stats(ctx).GetErrors(), "global errors found") sort.Sort(entries) - require.Equal(t, "[included.dir included.dir.link included.file included.file.link]", fmt.Sprint(entries)) + if copyLinks { + require.Equal(t, "[included.dir included.dir.link included.file included.file.link]", fmt.Sprint(entries)) + } else { + require.Equal(t, "[included.dir included.dir.link.rclonelink included.file included.file.link.rclonelink]", fmt.Sprint(entries)) + } // Check listing through a symlink still works entries, err = f.List(ctx, "included.dir") @@ -466,3 +492,11 @@ func TestFilterSymlink(t *testing.T) { sort.Sort(entries) require.Equal(t, "[included.dir/included.sub.file]", fmt.Sprint(entries)) } + +func TestFilterSymlinkCopyLinks(t *testing.T) { + testFilterSymlink(t, true) +} + +func TestFilterSymlinkLinks(t *testing.T) { + testFilterSymlink(t, false) +}