From 7428e47ebc0bb44ce453e3b43cc7f16077bba421 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 25 Sep 2020 18:32:31 +0100 Subject: [PATCH] local: fix sizes and syncing with --links option on Windows - fixes #4581 Before this change rclone returned the size from the Stat call of the link. On Windows this reads as 0 always, however on unix it reads as the length of the text in the link. This caused errors like this when syncing: Failed to copy: corrupted on transfer: sizes differ 0 vs 13 This change causes Windows platforms to read the link and use that as the size of the link instead of 0 which fixes the problem. --- backend/local/local.go | 9 +++++++++ backend/local/local_internal_test.go | 11 +---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/local/local.go b/backend/local/local.go index d785fee85..a4a45cd91 100644 --- a/backend/local/local.go +++ b/backend/local/local.go @@ -1231,6 +1231,15 @@ func (o *Object) setMetadata(info os.FileInfo) { o.modTime = info.ModTime() o.mode = info.Mode() o.fs.objectMetaMu.Unlock() + // On Windows links read as 0 size so set the correct size here + if runtime.GOOS == "windows" && o.translatedLink { + linkdst, err := os.Readlink(o.path) + if err != nil { + fs.Errorf(o, "Failed to read link size: %v", err) + } else { + o.size = int64(len(linkdst)) + } + } } // Stat an Object into info diff --git a/backend/local/local_internal_test.go b/backend/local/local_internal_test.go index abdd74dad..f5e651398 100644 --- a/backend/local/local_internal_test.go +++ b/backend/local/local_internal_test.go @@ -6,7 +6,6 @@ import ( "os" "path" "path/filepath" - "runtime" "testing" "time" @@ -89,9 +88,6 @@ func TestSymlink(t *testing.T) { // Object viewed as symlink file2 := fstest.NewItem("symlink.txt"+linkSuffix, "file.txt", modTime2) - if runtime.GOOS == "windows" { - file2.Size = 0 // symlinks are 0 length under Windows - } // Object viewed as destination file2d := fstest.NewItem("symlink.txt", "hello", modTime1) @@ -121,9 +117,6 @@ func TestSymlink(t *testing.T) { // Create a symlink modTime3 := fstest.Time("2002-03-03T04:05:10.123123123Z") file3 := r.WriteObjectTo(ctx, r.Flocal, "symlink2.txt"+linkSuffix, "file.txt", modTime3, false) - if runtime.GOOS == "windows" { - file3.Size = 0 // symlinks are 0 length under Windows - } fstest.CheckListingWithPrecision(t, r.Flocal, []fstest.Item{file1, file2, file3}, nil, fs.ModTimeNotSupported) if haveLChtimes { fstest.CheckItems(t, r.Flocal, file1, file2, file3) @@ -142,9 +135,7 @@ func TestSymlink(t *testing.T) { o, err := r.Flocal.NewObject(ctx, "symlink2.txt"+linkSuffix) require.NoError(t, err) assert.Equal(t, "symlink2.txt"+linkSuffix, o.Remote()) - if runtime.GOOS != "windows" { - assert.Equal(t, int64(8), o.Size()) - } + assert.Equal(t, int64(8), o.Size()) // Check that NewObject doesn't see the non suffixed version _, err = r.Flocal.NewObject(ctx, "symlink2.txt")