forked from TrueCloudLab/rclone
vfs: fix renaming/deleting open files with cache mode "writes" under Windows
Before this change, renaming and deleting of open files (which can easily happen due to the asynchronous nature of file systems) would produce an error, for example saving files with Firefox. After this change we open files with the flags necessary for open files to be renamed or deleted. Fixes #2730
This commit is contained in:
parent
42d997f639
commit
71e98ea584
3 changed files with 12 additions and 7 deletions
|
@ -15,6 +15,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ncw/rclone/lib/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interprets err into a vfs error
|
// Interprets err into a vfs error
|
||||||
|
@ -45,7 +47,7 @@ func test(fileName string, flags int, mode string) {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
log.Fatalf("File must not exist")
|
log.Fatalf("File must not exist")
|
||||||
}
|
}
|
||||||
f, openNonExistentErr := os.OpenFile(fileName, flags, 0666)
|
f, openNonExistentErr := file.OpenFile(fileName, flags, 0666)
|
||||||
|
|
||||||
var readNonExistentErr error
|
var readNonExistentErr error
|
||||||
var writeNonExistentErr error
|
var writeNonExistentErr error
|
||||||
|
@ -65,7 +67,7 @@ func test(fileName string, flags int, mode string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the file
|
// write the file
|
||||||
f, err = os.Create(fileName)
|
f, err = file.Create(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to create: %v", err)
|
log.Fatalf("failed to create: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -81,7 +83,7 @@ func test(fileName string, flags int, mode string) {
|
||||||
|
|
||||||
// then open file and try with file existing
|
// then open file and try with file existing
|
||||||
|
|
||||||
f, openExistingErr := os.OpenFile(fileName, flags, 0666)
|
f, openExistingErr := file.OpenFile(fileName, flags, 0666)
|
||||||
var readExistingErr error
|
var readExistingErr error
|
||||||
var writeExistingErr error
|
var writeExistingErr error
|
||||||
if openExistingErr == nil {
|
if openExistingErr == nil {
|
||||||
|
@ -100,7 +102,7 @@ func test(fileName string, flags int, mode string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the file
|
// read the file
|
||||||
f, err = os.Open(fileName)
|
f, err = file.Open(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to open: %v", err)
|
log.Fatalf("failed to open: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/ncw/rclone/fs/accounting"
|
"github.com/ncw/rclone/fs/accounting"
|
||||||
"github.com/ncw/rclone/fs/log"
|
"github.com/ncw/rclone/fs/log"
|
||||||
"github.com/ncw/rclone/fs/operations"
|
"github.com/ncw/rclone/fs/operations"
|
||||||
|
"github.com/ncw/rclone/lib/file"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -124,7 +125,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to open a exising cache file
|
// try to open a exising cache file
|
||||||
fd, err = os.OpenFile(fh.osPath, cacheFileOpenFlags&^os.O_CREATE, 0600)
|
fd, err = file.OpenFile(fh.osPath, cacheFileOpenFlags&^os.O_CREATE, 0600)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
// cache file does not exist, so need to fetch it if we have an object to fetch
|
// cache file does not exist, so need to fetch it if we have an object to fetch
|
||||||
// it from
|
// it from
|
||||||
|
@ -185,7 +186,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
||||||
|
|
||||||
if fd == nil {
|
if fd == nil {
|
||||||
fs.Debugf(fh.logPrefix(), "Opening cached copy with flags=%s", decodeOpenFlags(fh.flags))
|
fs.Debugf(fh.logPrefix(), "Opening cached copy with flags=%s", decodeOpenFlags(fh.flags))
|
||||||
fd, err = os.OpenFile(fh.osPath, cacheFileOpenFlags, 0600)
|
fd, err = file.OpenFile(fh.osPath, cacheFileOpenFlags, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "cache open file failed")
|
return errors.Wrap(err, "cache open file failed")
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ncw/rclone/lib/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -194,7 +196,7 @@ func (t *Test) close() {
|
||||||
func (t *Test) open() {
|
func (t *Test) open() {
|
||||||
t.close()
|
t.close()
|
||||||
t.logf("open")
|
t.logf("open")
|
||||||
handle, err := os.OpenFile(t.path(), os.O_RDWR|os.O_CREATE, 0666)
|
handle, err := file.OpenFile(t.path(), os.O_RDWR|os.O_CREATE, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.errorf("failed to open: %v", err)
|
t.errorf("failed to open: %v", err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue