mirror of https://github.com/rclone/rclone
WIP: Fix links creation for windows/winfsp
This commit is contained in:
parent
e15f711117
commit
2a00583f5c
|
@ -16,3 +16,5 @@ Thumbs.db
|
||||||
__pycache__
|
__pycache__
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.kate-swp
|
*.kate-swp
|
||||||
|
*debug*bin*
|
||||||
|
.vscode/
|
||||||
|
|
|
@ -1101,12 +1101,18 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
|
||||||
rnewName += fs.LinkSuffix
|
rnewName += fs.LinkSuffix
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = destDir.stat(rnewName)
|
statFile, err := destDir.stat(rnewName)
|
||||||
|
|
||||||
switch err {
|
switch err {
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
// not found, carry on
|
// not found, carry on
|
||||||
case nil:
|
case nil:
|
||||||
|
// Special case for windows / winfsp symlinks, it create a file early that is never deleted, leading to clash.
|
||||||
|
if d.vfs.Opt.Links && isLink && strings.HasPrefix(oldName, ".fuse_hidden") {
|
||||||
|
statFile.(*File).winfspPendingSymlink = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
return EEXIST
|
return EEXIST
|
||||||
default:
|
default:
|
||||||
// a different error - report
|
// a different error - report
|
||||||
|
|
29
vfs/file.go
29
vfs/file.go
|
@ -41,18 +41,19 @@ type File struct {
|
||||||
|
|
||||||
muRW sync.Mutex // synchronize RWFileHandle.openPending(), RWFileHandle.close() and File.Remove
|
muRW sync.Mutex // synchronize RWFileHandle.openPending(), RWFileHandle.close() and File.Remove
|
||||||
|
|
||||||
mu sync.RWMutex // protects the following
|
mu sync.RWMutex // protects the following
|
||||||
d *Dir // parent directory
|
d *Dir // parent directory
|
||||||
dPath string // path of parent directory. NB dir rename means all Files are flushed
|
dPath string // path of parent directory. NB dir rename means all Files are flushed
|
||||||
o fs.Object // NB o may be nil if file is being written
|
o fs.Object // NB o may be nil if file is being written
|
||||||
leaf string // leaf name of the object
|
leaf string // leaf name of the object
|
||||||
writers []Handle // writers for this file
|
writers []Handle // writers for this file
|
||||||
virtualModTime *time.Time // modtime for backends with Precision == fs.ModTimeNotSupported
|
virtualModTime *time.Time // modtime for backends with Precision == fs.ModTimeNotSupported
|
||||||
pendingModTime time.Time // will be applied once o becomes available, i.e. after file was written
|
pendingModTime time.Time // will be applied once o becomes available, i.e. after file was written
|
||||||
pendingRenameFun func(ctx context.Context) error // will be run/renamed after all writers close
|
pendingRenameFun func(ctx context.Context) error // will be run/renamed after all writers close
|
||||||
sys atomic.Value // user defined info to be attached here
|
sys atomic.Value // user defined info to be attached here
|
||||||
nwriters atomic.Int32 // len(writers)
|
nwriters atomic.Int32 // len(writers)
|
||||||
appendMode bool // file was opened with O_APPEND
|
appendMode bool // file was opened with O_APPEND
|
||||||
|
winfspPendingSymlink bool // windows/winfsp symlinks support - when true, this file node needs to be deleted
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFile creates a new File
|
// newFile creates a new File
|
||||||
|
@ -285,6 +286,10 @@ func (f *File) addWriter(h Handle) {
|
||||||
// delWriter removes a write handle from the file
|
// delWriter removes a write handle from the file
|
||||||
func (f *File) delWriter(h Handle) {
|
func (f *File) delWriter(h Handle) {
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
|
// Special case for windows / winfsp symlinks
|
||||||
|
if f.d.vfs.Opt.Links && f.winfspPendingSymlink && len(f.writers) == 1 {
|
||||||
|
defer f.Remove()
|
||||||
|
}
|
||||||
defer f.applyPendingRename()
|
defer f.applyPendingRename()
|
||||||
defer f.mu.Unlock()
|
defer f.mu.Unlock()
|
||||||
var found = -1
|
var found = -1
|
||||||
|
|
|
@ -78,10 +78,6 @@ func TestFileModTimeWithOpenWriters(t *testing.T) {
|
||||||
func TestSymlinks(t *testing.T) {
|
func TestSymlinks(t *testing.T) {
|
||||||
run.skipIfNoFUSE(t)
|
run.skipIfNoFUSE(t)
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
t.Skip("Skipping test on Windows")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// VFS only implements os.Stat, which return information to target for symlinks, getting symlink information would require os.Lstat implementation.
|
// VFS only implements os.Stat, which return information to target for symlinks, getting symlink information would require os.Lstat implementation.
|
||||||
// We will not bother to add Lstat implemented, but in the test we can just call os.Lstat which return the information needed when !useVFS
|
// We will not bother to add Lstat implemented, but in the test we can just call os.Lstat which return the information needed when !useVFS
|
||||||
|
|
Loading…
Reference in New Issue