diff options
| author | Sebastian Lackner | 2017-12-12 14:42:49 +0100 | 
|---|---|---|
| committer | rfjakob | 2017-12-25 15:07:37 +0100 | 
| commit | a85dbcab38bcad0ef713187a637a7023d016829f (patch) | |
| tree | 879fd621012544fba6319dabb9e051dde7cdda5e | |
| parent | a24342f656f6acd544ec07dada576d57a716b34d (diff) | |
fusefrontend: Use Linkat syscall to implement Link
| -rw-r--r-- | internal/fusefrontend/fs.go | 29 | ||||
| -rw-r--r-- | internal/syscallcompat/sys_common.go | 5 | 
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) +} | 
