From 64cf9ac911529bad9b62b09a4012e84a1e406c6f Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 3 Apr 2023 17:14:04 +0100 Subject: [PATCH] local: fix /path/to/file.rclonelink when -l/--links is in use Before this change using /path/to/file.rclonelink would not find the file when using -l/--links. This fixes the problem by doing another stat call if the file wasn't found without the suffix if -l/--links is in use. It will also give an error if you refer to a symlink without its suffix which will not work because the limit to a single file filtering will be using the file name without the .rclonelink suffix. need ".rclonelink" suffix to refer to symlink when using -l/--links Before this change it would use the symlink as a directory which then would fail when listed. See: #6855 --- backend/local/local.go | 14 +++++++++++++- backend/local/local_internal_test.go | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/backend/local/local.go b/backend/local/local.go index 984cd4910..4acb1b788 100644 --- a/backend/local/local.go +++ b/backend/local/local.go @@ -266,7 +266,10 @@ type Object struct { // ------------------------------------------------------------ -var errLinksAndCopyLinks = errors.New("can't use -l/--links with -L/--copy-links") +var ( + errLinksAndCopyLinks = errors.New("can't use -l/--links with -L/--copy-links") + errLinksNeedsSuffix = errors.New("need \"" + linkSuffix + "\" suffix to refer to symlink when using -l/--links") +) // NewFs constructs an Fs from the path func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, error) { @@ -310,7 +313,16 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e if err == nil { f.dev = readDevice(fi, f.opt.OneFileSystem) } + // Check to see if this is a .rclonelink if not found + hasLinkSuffix := strings.HasSuffix(f.root, linkSuffix) + if hasLinkSuffix && opt.TranslateSymlinks && os.IsNotExist(err) { + fi, err = f.lstat(strings.TrimSuffix(f.root, linkSuffix)) + } if err == nil && f.isRegular(fi.Mode()) { + // Handle the odd case, that a symlink was specified by name without the link suffix + if !hasLinkSuffix && opt.TranslateSymlinks && fi.Mode()&os.ModeSymlink != 0 { + return nil, errLinksNeedsSuffix + } // It is a file, so use the parent as the root f.root = filepath.Dir(f.root) // return an error with an fs which points to the parent diff --git a/backend/local/local_internal_test.go b/backend/local/local_internal_test.go index 7fcacaf33..2e2cfbca6 100644 --- a/backend/local/local_internal_test.go +++ b/backend/local/local_internal_test.go @@ -146,6 +146,20 @@ func TestSymlink(t *testing.T) { _, err = r.Flocal.NewObject(ctx, "symlink2.txt") require.Equal(t, fs.ErrorObjectNotFound, err) + // Check that NewFs works with the suffixed version and --links + f2, err := NewFs(ctx, "local", filepath.Join(dir, "symlink2.txt"+linkSuffix), configmap.Simple{ + "links": "true", + }) + require.Equal(t, fs.ErrorIsFile, err) + require.Equal(t, dir, f2.(*Fs).root) + + // Check that NewFs doesn't see the non suffixed version with --links + f2, err = NewFs(ctx, "local", filepath.Join(dir, "symlink2.txt"), configmap.Simple{ + "links": "true", + }) + require.Equal(t, errLinksNeedsSuffix, err) + require.Nil(t, f2) + // Check reading the object in, err := o.Open(ctx) require.NoError(t, err)