mirror of
https://github.com/rclone/rclone.git
synced 2024-11-23 02:34:40 +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
|
flags int // open flags
|
||||||
osPath string // path to the file in the cache
|
osPath string // path to the file in the cache
|
||||||
writeCalled bool // if any Write() methods have been called
|
writeCalled bool // if any Write() methods have been called
|
||||||
|
changed bool // file contents was changed in any other way
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check interfaces
|
// 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
|
// if the object wasn't found AND O_CREATE is set then
|
||||||
// ignore error as we are about to create the file
|
// ignore error as we are about to create the file
|
||||||
fh.file.setSize(0)
|
fh.file.setSize(0)
|
||||||
fh.writeCalled = true
|
fh.changed = true
|
||||||
} else {
|
} else {
|
||||||
return errors.Wrap(err, "open RW handle failed to cache file")
|
return errors.Wrap(err, "open RW handle failed to cache file")
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
||||||
} else {
|
} else {
|
||||||
// Set the size to 0 since we are truncating and flag we need to write it back
|
// Set the size to 0 since we are truncating and flag we need to write it back
|
||||||
fh.file.setSize(0)
|
fh.file.setSize(0)
|
||||||
fh.writeCalled = true
|
fh.changed = true
|
||||||
if fh.flags&os.O_CREATE == 0 && fh.file.exists() {
|
if fh.flags&os.O_CREATE == 0 && fh.file.exists() {
|
||||||
// create an empty file if it exists on the source
|
// create an empty file if it exists on the source
|
||||||
err = ioutil.WriteFile(fh.osPath, []byte{}, 0600)
|
err = ioutil.WriteFile(fh.osPath, []byte{}, 0600)
|
||||||
|
@ -215,6 +216,20 @@ func (fh *RWFileHandle) Node() Node {
|
||||||
return fh.file
|
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
|
// close the file handle returning EBADF if it has been
|
||||||
// closed already.
|
// closed already.
|
||||||
//
|
//
|
||||||
|
@ -301,24 +316,6 @@ func (fh *RWFileHandle) Close() error {
|
||||||
return fh.close()
|
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.
|
// Flush is called each time the file or directory is closed.
|
||||||
// Because there can be multiple file descriptors referring to a
|
// Because there can be multiple file descriptors referring to a
|
||||||
// single opened file, Flush can be called multiple times.
|
// 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 {
|
if err = fh.openPending(size == 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fh.writeCalled = true
|
fh.changed = true
|
||||||
fh.file.setSize(size)
|
fh.file.setSize(size)
|
||||||
return fh.File.Truncate(size)
|
return fh.File.Truncate(size)
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,7 +350,8 @@ func TestRWFileHandleWriteAt(t *testing.T) {
|
||||||
// Preconditions
|
// Preconditions
|
||||||
assert.Equal(t, int64(0), offset())
|
assert.Equal(t, int64(0), offset())
|
||||||
assert.True(t, fh.opened)
|
assert.True(t, fh.opened)
|
||||||
assert.True(t, fh.writeCalled)
|
assert.False(t, fh.writeCalled)
|
||||||
|
assert.True(t, fh.changed)
|
||||||
|
|
||||||
// Write the data
|
// Write the data
|
||||||
n, err := fh.WriteAt([]byte("hello**"), 0)
|
n, err := fh.WriteAt([]byte("hello**"), 0)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user