mirror of
https://github.com/rclone/rclone
synced 2024-12-23 14:23:44 +01:00
operations: fix very long file names when using copy with --partial
Before this change we were using the wrong variable to read the filename length from. This meant that very long filenames were not being truncated as intended. This problem was spotted by Wang Zhiwei on the forum in a code review. See: https://forum.rclone.org/t/why-use-c-remoteforcopy-instead-of-c-remote-to-check-length-in-copy-operation/45099
This commit is contained in:
parent
1cf1f4fab2
commit
7c828ffe09
@ -98,9 +98,9 @@ func (c *copy) checkPartial() (remoteForCopy string, inplace bool, err error) {
|
||||
// Avoid making the leaf name longer if it's already lengthy to avoid
|
||||
// trouble with file name length limits.
|
||||
suffix := "." + random.String(8) + c.ci.PartialSuffix
|
||||
base := path.Base(c.remoteForCopy)
|
||||
base := path.Base(remoteForCopy)
|
||||
if len(base) > 100 {
|
||||
remoteForCopy = TruncateString(c.remoteForCopy, len(c.remoteForCopy)-len(suffix)) + suffix
|
||||
remoteForCopy = TruncateString(remoteForCopy, len(remoteForCopy)-len(suffix)) + suffix
|
||||
} else {
|
||||
remoteForCopy += suffix
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -121,6 +124,46 @@ func TestCopyFile(t *testing.T) {
|
||||
r.CheckRemoteItems(t, file2)
|
||||
}
|
||||
|
||||
// Find the longest file name for writing to local
|
||||
func maxLengthFileName(t *testing.T, r *fstest.Run) string {
|
||||
require.NoError(t, r.Flocal.Mkdir(context.Background(), "")) // create the root
|
||||
const maxLen = 16 * 1024
|
||||
name := strings.Repeat("A", maxLen)
|
||||
i := sort.Search(len(name), func(i int) (fail bool) {
|
||||
filePath := path.Join(r.LocalName, name[:i])
|
||||
err := os.WriteFile(filePath, []byte{0}, 0777)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
err = os.Remove(filePath)
|
||||
if err != nil {
|
||||
t.Logf("Failed to remove test file: %v", err)
|
||||
}
|
||||
return false
|
||||
})
|
||||
return name[:i-1]
|
||||
}
|
||||
|
||||
// Check we can copy a file of maximum name length
|
||||
func TestCopyLongFile(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
r := fstest.NewRun(t)
|
||||
if !r.Fremote.Features().IsLocal {
|
||||
t.Skip("Test only runs on local")
|
||||
}
|
||||
|
||||
// Find the maximum length of file we can write
|
||||
name := maxLengthFileName(t, r)
|
||||
t.Logf("Max length of file name is %d", len(name))
|
||||
file1 := r.WriteFile(name, "file1 contents", t1)
|
||||
r.CheckLocalItems(t, file1)
|
||||
|
||||
err := operations.CopyFile(ctx, r.Fremote, r.Flocal, file1.Path, file1.Path)
|
||||
require.NoError(t, err)
|
||||
r.CheckLocalItems(t, file1)
|
||||
r.CheckRemoteItems(t, file1)
|
||||
}
|
||||
|
||||
func TestCopyFileBackupDir(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx, ci := fs.AddConfig(ctx)
|
||||
|
Loading…
Reference in New Issue
Block a user