mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 14:51:48 +08:00
vfs: Fix TestWriteFileDoubleClose with --vfs-cache-mode >= writes
This was causing the file to be closed on Flush() instead of Release() when the file was opened with O_TRUNC.
This commit is contained in:
parent
c3d0f68923
commit
b91bd32489
|
@ -31,6 +31,7 @@ type RWFileHandle struct {
|
|||
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
|
||||
}
|
||||
|
||||
// Check interfaces
|
||||
|
@ -146,7 +147,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
|||
// if the object wasn't found AND O_CREATE is set then
|
||||
// ignore error as we are about to create the file
|
||||
fh.file.setSize(0)
|
||||
fh.writeCalled = true
|
||||
fh.changed = true
|
||||
} else {
|
||||
return errors.Wrap(err, "open RW handle failed to cache file")
|
||||
}
|
||||
|
@ -159,7 +160,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
|||
} else {
|
||||
// Set the size to 0 since we are truncating and flag we need to write it back
|
||||
fh.file.setSize(0)
|
||||
fh.writeCalled = true
|
||||
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)
|
||||
|
@ -215,6 +216,20 @@ func (fh *RWFileHandle) Node() Node {
|
|||
return fh.file
|
||||
}
|
||||
|
||||
// Returns whether the file needs to be written back.
|
||||
//
|
||||
// If write hasn't been called and the file hasn't been changed in any other
|
||||
// way we haven't modified it so we don't need to transfer it
|
||||
//
|
||||
// Must be called with fh.mu held
|
||||
func (fh *RWFileHandle) modified() bool {
|
||||
if !fh.writeCalled && !fh.changed {
|
||||
fs.Debugf(fh.logPrefix(), "not modified so not transferring")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// close the file handle returning EBADF if it has been
|
||||
// closed already.
|
||||
//
|
||||
|
@ -301,24 +316,6 @@ func (fh *RWFileHandle) Close() error {
|
|||
return fh.close()
|
||||
}
|
||||
|
||||
func (fh *RWFileHandle) modified() bool {
|
||||
rdwrMode := fh.flags & accessModeMask
|
||||
// no writes means no transfer?
|
||||
if rdwrMode == os.O_RDONLY && fh.flags&os.O_TRUNC == 0 {
|
||||
fs.Debugf(fh.logPrefix(), "read only and not truncating so not transferring")
|
||||
return false
|
||||
}
|
||||
|
||||
// If write hasn't been called and we aren't creating or
|
||||
// truncating the file then we haven't modified it so don't
|
||||
// need to transfer it
|
||||
if !fh.writeCalled && fh.flags&(os.O_CREATE|os.O_TRUNC) == 0 {
|
||||
fs.Debugf(fh.logPrefix(), "not modified so not transferring")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Flush is called each time the file or directory is closed.
|
||||
// Because there can be multiple file descriptors referring to a
|
||||
// single opened file, Flush can be called multiple times.
|
||||
|
@ -507,7 +504,7 @@ func (fh *RWFileHandle) Truncate(size int64) (err error) {
|
|||
if err = fh.openPending(size == 0); err != nil {
|
||||
return err
|
||||
}
|
||||
fh.writeCalled = true
|
||||
fh.changed = true
|
||||
fh.file.setSize(size)
|
||||
return fh.File.Truncate(size)
|
||||
}
|
||||
|
|
|
@ -350,7 +350,8 @@ func TestRWFileHandleWriteAt(t *testing.T) {
|
|||
// Preconditions
|
||||
assert.Equal(t, int64(0), offset())
|
||||
assert.True(t, fh.opened)
|
||||
assert.True(t, fh.writeCalled)
|
||||
assert.False(t, fh.writeCalled)
|
||||
assert.True(t, fh.changed)
|
||||
|
||||
// Write the data
|
||||
n, err := fh.WriteAt([]byte("hello**"), 0)
|
||||
|
|
Loading…
Reference in New Issue
Block a user