diff --git a/backend/local/local.go b/backend/local/local.go index 156c2ce26..5b491be26 100644 --- a/backend/local/local.go +++ b/backend/local/local.go @@ -28,6 +28,7 @@ var ( followSymlinks = flags.BoolP("copy-links", "L", false, "Follow symlinks and copy the pointed to item.") skipSymlinks = flags.BoolP("skip-links", "", false, "Don't warn about skipped symlinks.") noUTFNorm = flags.BoolP("local-no-unicode-normalization", "", false, "Don't apply unicode normalization to paths and filenames") + noCheckUpdated = flags.BoolP("local-no-check-updated", "", false, "Don't check to see if the files change during upload") ) // Constants @@ -673,16 +674,18 @@ type localOpenFile struct { // Read bytes from the object - see io.Reader func (file *localOpenFile) Read(p []byte) (n int, err error) { - // Check if file has the same size and modTime - fi, err := file.fd.Stat() - if err != nil { - return 0, errors.Wrap(err, "can't read status of source file while transferring") - } - if file.o.size != fi.Size() { - return 0, errors.Errorf("can't copy - source file is being updated (size changed from %d to %d)", file.o.size, fi.Size()) - } - if !file.o.modTime.Equal(fi.ModTime()) { - return 0, errors.Errorf("can't copy - source file is being updated (mod time changed from %v to %v)", file.o.modTime, fi.ModTime()) + if !*noCheckUpdated { + // Check if file has the same size and modTime + fi, err := file.fd.Stat() + if err != nil { + return 0, errors.Wrap(err, "can't read status of source file while transferring") + } + if file.o.size != fi.Size() { + return 0, errors.Errorf("can't copy - source file is being updated (size changed from %d to %d)", file.o.size, fi.Size()) + } + if !file.o.modTime.Equal(fi.ModTime()) { + return 0, errors.Errorf("can't copy - source file is being updated (mod time changed from %v to %v)", file.o.modTime, fi.ModTime()) + } } n, err = file.in.Read(p) diff --git a/backend/local/local_internal_test.go b/backend/local/local_internal_test.go index 9ac99e7f7..791c1036f 100644 --- a/backend/local/local_internal_test.go +++ b/backend/local/local_internal_test.go @@ -29,8 +29,10 @@ func TestMapper(t *testing.T) { }) assert.Equal(t, "potato", m.Load("potato")) assert.Equal(t, "-r?'a´o¨", m.Load("-r'áö")) +} - // Test copy with source file that's updating +// Test copy with source file that's updating +func TestUpdatingCheck(t *testing.T) { r := fstest.NewRun(t) defer r.Finalise() filePath := "sub dir/local test" @@ -59,4 +61,16 @@ func TestMapper(t *testing.T) { r.WriteFile(filePath, "content updated", time.Now()) _, err = in.Read(buf) require.Errorf(t, err, "can't copy - source file is being updated") + + // turn the checking off and try again + + *noCheckUpdated = true + defer func() { + *noCheckUpdated = false + }() + + r.WriteFile(filePath, "content updated", time.Now()) + _, err = in.Read(buf) + require.NoError(t, err) + } diff --git a/docs/content/local.md b/docs/content/local.md index 723e944b6..a77abf94b 100644 --- a/docs/content/local.md +++ b/docs/content/local.md @@ -120,6 +120,18 @@ $ rclone -L ls /tmp/a 6 b/one ``` +#### --local-no-check-updated #### + +Don't check to see if the files change during upload. + +Normally rclone checks the size and modification time of files as they +are being uploaded and aborts with a message which starts `can't copy +- source file is being updated` if the file changes during upload. + +However on some file systems this modification time check may fail (eg +[Glusterfs #2206](https://github.com/ncw/rclone/issues/2206)) so this +check can be disabled with this flag. + #### --local-no-unicode-normalization #### This flag is deprecated now. Rclone no longer normalizes unicode file