mirror of
https://github.com/rclone/rclone.git
synced 2024-12-22 23:22:08 +01:00
vfs: fix Create causing windows explorer to truncate files on CTRL-C CTRL-V
Before this fix, doing CTRL-C and CTRL-V on a file in Windows explorer caused the **source** and the the destination to be truncated to 0. This is because Windows opens the source file with Create with flags `O_RDWR|O_CREATE|O_EXCL` but doesn't write to it - it only reads from it. Rclone was taking the call to Create as a signal to always make a new file, but this is incorrect. This fix reads an existing file from the directory if it exists when Create is called rather than always creating a new one. This fixes the problem. Fixes #5181
This commit is contained in:
parent
d0f8b4f479
commit
20e15e52a9
17
vfs/dir.go
17
vfs/dir.go
@ -843,6 +843,23 @@ func (d *Dir) Open(flags int) (fd Handle, err error) {
|
||||
// Create makes a new file node
|
||||
func (d *Dir) Create(name string, flags int) (*File, error) {
|
||||
// fs.Debugf(path, "Dir.Create")
|
||||
// Return existing node if one exists
|
||||
node, err := d.stat(name)
|
||||
switch err {
|
||||
case ENOENT:
|
||||
// not found, carry on
|
||||
case nil:
|
||||
// found so check what it is
|
||||
if node.IsFile() {
|
||||
return node.(*File), err
|
||||
}
|
||||
return nil, EEXIST // EISDIR would be better but we don't have that
|
||||
default:
|
||||
// a different error - report
|
||||
fs.Errorf(d, "Dir.Create stat failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
// node doesn't exist so create it
|
||||
if d.vfs.Opt.ReadOnly {
|
||||
return nil, EROFS
|
||||
}
|
||||
|
@ -375,6 +375,13 @@ func TestDirCreate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(5), file2.Size())
|
||||
|
||||
// Try creating the file again - make sure we get the same file node
|
||||
file3, err := dir.Create("potato", os.O_RDWR|os.O_CREATE)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(5), file3.Size())
|
||||
assert.Equal(t, fmt.Sprintf("%p", file), fmt.Sprintf("%p", file3), "didn't return same node")
|
||||
|
||||
// Test read only fs creating new
|
||||
vfs.Opt.ReadOnly = true
|
||||
_, err = dir.Create("sausage", os.O_WRONLY|os.O_CREATE)
|
||||
assert.Equal(t, EROFS, err)
|
||||
|
Loading…
Reference in New Issue
Block a user