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
This commit is contained in:
Nick Craig-Wood 2023-03-08 12:10:50 +00:00
parent f07abea072
commit 1a66ed9315
2 changed files with 7 additions and 2 deletions

View File

@ -322,7 +322,9 @@ func (f *File) ModTime() (modTime time.Time) {
} }
// Read the modtime from a dirty item if it exists // Read the modtime from a dirty item if it exists
if f.d.vfs.Opt.CacheMode >= vfscommon.CacheModeMinimal { 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() modTime, err := item.GetModTime()
if err != nil { if err != nil {
fs.Errorf(f._path(), "ModTime: Item GetModTime failed: %v", err) fs.Errorf(f._path(), "ModTime: Item GetModTime failed: %v", err)

View File

@ -1223,7 +1223,7 @@ func (item *Item) setModTime(modTime time.Time) {
item.mu.Unlock() item.mu.Unlock()
} }
// GetModTime of the cache file // GetModTime of the cache item
func (item *Item) GetModTime() (modTime time.Time, err error) { func (item *Item) GetModTime() (modTime time.Time, err error) {
// defer log.Trace(item.name, "modTime=%v", modTime)("") // defer log.Trace(item.name, "modTime=%v", modTime)("")
item.mu.Lock() item.mu.Lock()
@ -1231,6 +1231,9 @@ func (item *Item) GetModTime() (modTime time.Time, err error) {
fi, err := item._stat() fi, err := item._stat()
if err == nil { if err == nil {
modTime = fi.ModTime() modTime = fi.ModTime()
item.info.ModTime = modTime
} else {
modTime = item.info.ModTime
} }
return modTime, nil return modTime, nil
} }