From 2a00583f5cc9811812e99d7122b5b18a7c533e9d Mon Sep 17 00:00:00 2001 From: Filipe Azevedo Date: Sun, 11 Jun 2023 17:27:46 +0200 Subject: [PATCH] WIP: Fix links creation for windows/winfsp --- .gitignore | 2 ++ vfs/dir.go | 8 +++++++- vfs/file.go | 29 +++++++++++++++++------------ vfs/vfstest/file.go | 4 ---- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index a8409626e..50b2c1656 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ Thumbs.db __pycache__ .DS_Store *.kate-swp +*debug*bin* +.vscode/ diff --git a/vfs/dir.go b/vfs/dir.go index d203588f2..9c709bc04 100644 --- a/vfs/dir.go +++ b/vfs/dir.go @@ -1101,12 +1101,18 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error { rnewName += fs.LinkSuffix } - _, err = destDir.stat(rnewName) + statFile, err := destDir.stat(rnewName) switch err { case ENOENT: // not found, carry on 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 default: // a different error - report diff --git a/vfs/file.go b/vfs/file.go index c943e31c6..65633eb88 100644 --- a/vfs/file.go +++ b/vfs/file.go @@ -41,18 +41,19 @@ type File struct { muRW sync.Mutex // synchronize RWFileHandle.openPending(), RWFileHandle.close() and File.Remove - mu sync.RWMutex // protects the following - d *Dir // parent directory - 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 - leaf string // leaf name of the object - writers []Handle // writers for this file - 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 - pendingRenameFun func(ctx context.Context) error // will be run/renamed after all writers close - sys atomic.Value // user defined info to be attached here - nwriters atomic.Int32 // len(writers) - appendMode bool // file was opened with O_APPEND + mu sync.RWMutex // protects the following + d *Dir // parent directory + 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 + leaf string // leaf name of the object + writers []Handle // writers for this file + 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 + pendingRenameFun func(ctx context.Context) error // will be run/renamed after all writers close + sys atomic.Value // user defined info to be attached here + nwriters atomic.Int32 // len(writers) + 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 @@ -285,6 +286,10 @@ func (f *File) addWriter(h Handle) { // delWriter removes a write handle from the file func (f *File) delWriter(h Handle) { 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.mu.Unlock() var found = -1 diff --git a/vfs/vfstest/file.go b/vfs/vfstest/file.go index 13c81b473..f6a3d8550 100644 --- a/vfs/vfstest/file.go +++ b/vfs/vfstest/file.go @@ -78,10 +78,6 @@ func TestFileModTimeWithOpenWriters(t *testing.T) { func TestSymlinks(t *testing.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. // 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