diff --git a/vfs/cache.go b/vfs/cache.go index 8a9ade07a..18f85a8cf 100644 --- a/vfs/cache.go +++ b/vfs/cache.go @@ -381,6 +381,15 @@ func (c *cache) removeDir(dir string) bool { return false } +// setModTime should be called to set the modification time of the cache file +func (c *cache) setModTime(name string, modTime time.Time) { + osPath := c.toOSPath(name) + err := os.Chtimes(osPath, modTime, modTime) + if err != nil { + fs.Errorf(name, "Failed to set modification time of cached file: %v", err) + } +} + // cleanUp empties the cache of everything func (c *cache) cleanUp() error { return os.RemoveAll(c.root) diff --git a/vfs/file.go b/vfs/file.go index c3a227b74..16f0581ff 100644 --- a/vfs/file.go +++ b/vfs/file.go @@ -88,11 +88,17 @@ func (f *File) Name() (name string) { return f.leaf } +// _path returns the full path of the file +// use when lock is held +func (f *File) _path() string { + return path.Join(f.d.path, f.leaf) +} + // Path returns the full path of the file func (f *File) Path() string { f.mu.RLock() defer f.mu.RUnlock() - return path.Join(f.d.path, f.leaf) + return f._path() } // osPath returns the full path of the file in the cache in OS format @@ -372,6 +378,12 @@ func (f *File) _applyPendingModTime() error { return errors.New("Cannot apply ModTime, file object is not available") } + // set the time of the file in the cache + if f.d.vfs.Opt.CacheMode != CacheModeOff { + f.d.vfs.cache.setModTime(f._path(), f.pendingModTime) + } + + // set the time of the object err := f.o.SetModTime(context.TODO(), f.pendingModTime) switch err { case nil: diff --git a/vfs/read_write_test.go b/vfs/read_write_test.go index ef4a6ec48..13555db1b 100644 --- a/vfs/read_write_test.go +++ b/vfs/read_write_test.go @@ -2,6 +2,7 @@ package vfs import ( "context" + "fmt" "io" "io/ioutil" "os" @@ -687,7 +688,12 @@ func TestRWFileModTimeWithOpenWriters(t *testing.T) { err = fh.Node().SetModTime(mtime) require.NoError(t, err) - err = fh.Close() + // Using Flush/Release to mimic mount instead of Close + + err = fh.Flush() + require.NoError(t, err) + + err = fh.Release() require.NoError(t, err) info, err := vfs.Stat("file1") @@ -695,8 +701,11 @@ func TestRWFileModTimeWithOpenWriters(t *testing.T) { if r.Fremote.Precision() != fs.ModTimeNotSupported { // avoid errors because of timezone differences - assert.Equal(t, info.ModTime().Unix(), mtime.Unix()) + assert.Equal(t, info.ModTime().Unix(), mtime.Unix(), fmt.Sprintf("Time mismatch: %v != %v", info.ModTime(), mtime)) } + + file1 := fstest.NewItem("file1", "hi", mtime) + fstest.CheckItems(t, r.Fremote, file1) } func TestRWCacheRename(t *testing.T) {