From 1a66ed9315f37a48a01e40bfe3dd00cc49327198 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Wed, 8 Mar 2023 12:10:50 +0000 Subject: [PATCH] vfs: make uploaded files retain modtime with non-modtime backends Before this change if a file was uploaded to a backend which didn't support modtimes, the time of the file read after the upload had completed would change to the time the file was uploaded on the backend. When using `--vfs-cache-mode writes` or `full` this time would be different by the `--vfs-write-back` delay which would cause applications to think the file had been modified. This changes uses the last modification time read in the cache as the modtime for backends which don't support setting modtimes. It does not change the modtime to that actually uploaded. This means that as long as the file remains in the directory cache it will have the expected modtime. See: https://forum.rclone.org/t/saving-files-causes-wrong-modified-time-to-be-set-for-a-few-seconds-on-webdav-mount-with-bitrix24/36451 --- vfs/file.go | 4 +++- vfs/vfscache/item.go | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/vfs/file.go b/vfs/file.go index 44a4ebb88..52fff453e 100644 --- a/vfs/file.go +++ b/vfs/file.go @@ -322,7 +322,9 @@ func (f *File) ModTime() (modTime time.Time) { } // Read the modtime from a dirty item if it exists if f.d.vfs.Opt.CacheMode >= vfscommon.CacheModeMinimal { - if item := f.d.vfs.cache.DirtyItem(f._path()); item != nil { + item := f.d.vfs.cache.ItemOrNil(f._path()) + noModTime := f.d.f.Precision() == fs.ModTimeNotSupported + if item != nil && (item.IsDirty() || noModTime) { modTime, err := item.GetModTime() if err != nil { fs.Errorf(f._path(), "ModTime: Item GetModTime failed: %v", err) diff --git a/vfs/vfscache/item.go b/vfs/vfscache/item.go index e1575eca3..431599b63 100644 --- a/vfs/vfscache/item.go +++ b/vfs/vfscache/item.go @@ -1223,7 +1223,7 @@ func (item *Item) setModTime(modTime time.Time) { item.mu.Unlock() } -// GetModTime of the cache file +// GetModTime of the cache item func (item *Item) GetModTime() (modTime time.Time, err error) { // defer log.Trace(item.name, "modTime=%v", modTime)("") item.mu.Lock() @@ -1231,6 +1231,9 @@ func (item *Item) GetModTime() (modTime time.Time, err error) { fi, err := item._stat() if err == nil { modTime = fi.ModTime() + item.info.ModTime = modTime + } else { + modTime = item.info.ModTime } return modTime, nil }