aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorSebastian Lackner2017-12-12 14:42:49 +0100
committerrfjakob2017-12-25 15:07:37 +0100
commita85dbcab38bcad0ef713187a637a7023d016829f (patch)
tree879fd621012544fba6319dabb9e051dde7cdda5e /internal
parenta24342f656f6acd544ec07dada576d57a716b34d (diff)
fusefrontend: Use Linkat syscall to implement Link
Diffstat (limited to 'internal')
-rw-r--r--internal/fusefrontend/fs.go29
-rw-r--r--internal/syscallcompat/sys_common.go5
2 files changed, 18 insertions, 16 deletions
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index 8c9e5e4..cabfdd2 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -540,35 +540,32 @@ func (fs *FS) Link(oldPath string, newPath string, context *fuse.Context) (code
if fs.isFiltered(newPath) {
return fuse.EPERM
}
- cOldPath, err := fs.getBackingPath(oldPath)
+ oldDirFd, cOldName, err := fs.openBackingPath(oldPath)
if err != nil {
return fuse.ToStatus(err)
}
- cNewPath, err := fs.getBackingPath(newPath)
+ defer oldDirFd.Close()
+ newDirFd, cNewName, err := fs.openBackingPath(newPath)
if err != nil {
return fuse.ToStatus(err)
}
- // Handle long file name
- cNewName := filepath.Base(cNewPath)
+ defer newDirFd.Close()
+ // Handle long file name (except in PlaintextNames mode)
if !fs.args.PlaintextNames && nametransform.IsLongContent(cNewName) {
- dirfd, err := os.Open(filepath.Dir(cNewPath))
- if err != nil {
- return fuse.ToStatus(err)
- }
- defer dirfd.Close()
- err = fs.nameTransform.WriteLongName(dirfd, cNewName, newPath)
+ err = fs.nameTransform.WriteLongName(newDirFd, cNewName, newPath)
if err != nil {
return fuse.ToStatus(err)
}
- // TODO Use syscall.Linkat once it is available in Go (it is not in Go
- // 1.6).
- err = syscall.Link(cOldPath, cNewPath)
+ // Create "gocryptfs.longfile." link
+ err = syscallcompat.Linkat(int(oldDirFd.Fd()), cOldName, int(newDirFd.Fd()), cNewName, 0)
if err != nil {
- nametransform.DeleteLongName(dirfd, cNewName)
+ nametransform.DeleteLongName(newDirFd, cNewName)
}
- return fuse.ToStatus(err)
+ } else {
+ // Create regular link
+ err = syscallcompat.Linkat(int(oldDirFd.Fd()), cOldName, int(newDirFd.Fd()), cNewName, 0)
}
- return fuse.ToStatus(os.Link(cOldPath, cNewPath))
+ return fuse.ToStatus(err)
}
// Access implements pathfs.Filesystem.
diff --git a/internal/syscallcompat/sys_common.go b/internal/syscallcompat/sys_common.go
index 896aaf7..21823ef 100644
--- a/internal/syscallcompat/sys_common.go
+++ b/internal/syscallcompat/sys_common.go
@@ -38,3 +38,8 @@ func Faccessat(dirfd int, path string, mode uint32) error {
}
return unix.Faccessat(dirfd, path, mode, 0)
}
+
+// Linkat exists both in Linux and in MacOS 10.10+.
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+ return unix.Linkat(olddirfd, oldpath, newdirfd, newpath, flags)
+}