From 241921c786cddffef606f980add71f581d2e5914 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 9 Dec 2019 14:25:54 +0000 Subject: [PATCH] vfs: don't cache the path in RW file objects to fix renaming --- vfs/file.go | 7 ++++++- vfs/read_write.go | 47 ++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/vfs/file.go b/vfs/file.go index ab6dbee40..8a6e1fe49 100644 --- a/vfs/file.go +++ b/vfs/file.go @@ -95,6 +95,11 @@ func (f *File) Path() string { return path.Join(f.d.path, f.leaf) } +// osPath returns the full path of the file in the cache in OS format +func (f *File) osPath() string { + return f.d.vfs.cache.toOSPath(f.Path()) +} + // Sys returns underlying data source (can be nil) - satisfies Node interface func (f *File) Sys() interface{} { return nil @@ -473,7 +478,7 @@ func (f *File) openRW(flags int) (fh *RWFileHandle, err error) { } // fs.Debugf(o, "File.openRW") - fh, err = newRWFileHandle(d, f, f.Path(), flags) + fh, err = newRWFileHandle(d, f, flags) if err != nil { fs.Errorf(f, "File.openRW failed: %v", err) return nil, err diff --git a/vfs/read_write.go b/vfs/read_write.go index 58742e9d9..05fcf8a88 100644 --- a/vfs/read_write.go +++ b/vfs/read_write.go @@ -24,14 +24,12 @@ type RWFileHandle struct { *os.File mu sync.Mutex closed bool // set if handle has been closed - remote string file *File d *Dir opened bool - flags int // open flags - osPath string // path to the file in the cache - writeCalled bool // if any Write() methods have been called - changed bool // file contents was changed in any other way + flags int // open flags + writeCalled bool // if any Write() methods have been called + changed bool // file contents was changed in any other way } // Check interfaces @@ -44,26 +42,25 @@ var ( _ io.Closer = (*RWFileHandle)(nil) ) -func newRWFileHandle(d *Dir, f *File, remote string, flags int) (fh *RWFileHandle, err error) { +func newRWFileHandle(d *Dir, f *File, flags int) (fh *RWFileHandle, err error) { // if O_CREATE and O_EXCL are set and if path already exists, then return EEXIST if flags&(os.O_CREATE|os.O_EXCL) == os.O_CREATE|os.O_EXCL && f.exists() { return nil, EEXIST } fh = &RWFileHandle{ - file: f, - d: d, - remote: remote, - flags: flags, + file: f, + d: d, + flags: flags, } // mark the file as open in the cache - must be done before the mkdir - fh.d.vfs.cache.open(fh.remote) + fh.d.vfs.cache.open(fh.file.Path()) // Make a place for the file - fh.osPath, err = d.vfs.cache.mkdir(remote) + _, err = d.vfs.cache.mkdir(fh.file.Path()) if err != nil { - fh.d.vfs.cache.close(fh.remote) + fh.d.vfs.cache.close(fh.file.Path()) return nil, errors.Wrap(err, "open RW handle failed to make cache directory") } @@ -113,9 +110,9 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) { // If the remote object exists AND its cached file exists locally AND there are no // other RW handles with it open, then attempt to update it. if o != nil && fh.file.rwOpens() == 0 { - cacheObj, err := fh.d.vfs.cache.f.NewObject(context.TODO(), fh.remote) + cacheObj, err := fh.d.vfs.cache.f.NewObject(context.TODO(), fh.file.Path()) if err == nil && cacheObj != nil { - _, err = copyObj(fh.d.vfs.cache.f, cacheObj, fh.remote, o) + _, err = copyObj(fh.d.vfs.cache.f, cacheObj, fh.file.Path(), o) if err != nil { return errors.Wrap(err, "open RW handle failed to update cached file") } @@ -123,12 +120,12 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) { } // try to open a exising cache file - fd, err = file.OpenFile(fh.osPath, cacheFileOpenFlags&^os.O_CREATE, 0600) + fd, err = file.OpenFile(fh.file.osPath(), cacheFileOpenFlags&^os.O_CREATE, 0600) if os.IsNotExist(err) { // cache file does not exist, so need to fetch it if we have an object to fetch // it from if o != nil { - _, err = copyObj(fh.d.vfs.cache.f, nil, fh.remote, o) + _, err = copyObj(fh.d.vfs.cache.f, nil, fh.file.Path(), o) if err != nil { cause := errors.Cause(err) if cause != fs.ErrorObjectNotFound && cause != fs.ErrorDirNotFound { @@ -162,7 +159,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) { fh.changed = true if fh.flags&os.O_CREATE == 0 && fh.file.exists() { // create an empty file if it exists on the source - err = ioutil.WriteFile(fh.osPath, []byte{}, 0600) + err = ioutil.WriteFile(fh.file.osPath(), []byte{}, 0600) if err != nil { return errors.Wrap(err, "cache open failed to create zero length file") } @@ -172,9 +169,9 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) { // exists in these cases. if runtime.GOOS == "windows" && fh.flags&os.O_APPEND != 0 { cacheFileOpenFlags &^= os.O_TRUNC - _, err = os.Stat(fh.osPath) + _, err = os.Stat(fh.file.osPath()) if err == nil { - err = os.Truncate(fh.osPath, 0) + err = os.Truncate(fh.file.osPath(), 0) if err != nil { return errors.Wrap(err, "cache open failed to truncate") } @@ -184,7 +181,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) { if fd == nil { fs.Debugf(fh.logPrefix(), "Opening cached copy with flags=%s", decodeOpenFlags(fh.flags)) - fd, err = file.OpenFile(fh.osPath, cacheFileOpenFlags, 0600) + fd, err = file.OpenFile(fh.file.osPath(), cacheFileOpenFlags, 0600) if err != nil { return errors.Wrap(err, "cache open file failed") } @@ -280,14 +277,14 @@ func (fh *RWFileHandle) flushWrites(closeFile bool) error { if isCopied { // Transfer the temp file to the remote - cacheObj, err := fh.d.vfs.cache.f.NewObject(context.TODO(), fh.remote) + cacheObj, err := fh.d.vfs.cache.f.NewObject(context.TODO(), fh.file.Path()) if err != nil { err = errors.Wrap(err, "failed to find cache file") fs.Errorf(fh.logPrefix(), "%v", err) return err } - o, err := copyObj(fh.d.vfs.f, fh.file.getObject(), fh.remote, cacheObj) + o, err := copyObj(fh.d.vfs.f, fh.file.getObject(), fh.file.Path(), cacheObj) if err != nil { err = errors.Wrap(err, "failed to transfer file from cache to remote") fs.Errorf(fh.logPrefix(), "%v", err) @@ -320,7 +317,7 @@ func (fh *RWFileHandle) close() (err error) { if fh.opened { fh.file.delRWOpen() } - fh.d.vfs.cache.close(fh.remote) + fh.d.vfs.cache.close(fh.file.Path()) }() return fh.flushWrites(true) @@ -549,5 +546,5 @@ func (fh *RWFileHandle) Sync() error { } func (fh *RWFileHandle) logPrefix() string { - return fmt.Sprintf("%s(%p)", fh.remote, fh) + return fmt.Sprintf("%s(%p)", fh.file.Path(), fh) }