summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/fusefrontend/fs.go2
-rw-r--r--internal/fusefrontend/fs_dir.go8
-rw-r--r--internal/nametransform/longnames.go2
-rw-r--r--internal/syscallcompat/sys_darwin.go23
-rw-r--r--internal/syscallcompat/sys_linux.go16
5 files changed, 33 insertions, 18 deletions
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index 08edd2b..002b4e1 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -388,7 +388,7 @@ func (fs *FS) Unlink(path string, context *fuse.Context) (code fuse.Status) {
}
defer dirfd.Close()
// Delete content
- err = syscallcompat.Unlinkat(int(dirfd.Fd()), cName)
+ err = syscallcompat.Unlinkat(int(dirfd.Fd()), cName, 0)
if err != nil {
return fuse.ToStatus(err)
}
diff --git a/internal/fusefrontend/fs_dir.go b/internal/fusefrontend/fs_dir.go
index 91c899e..ae150b5 100644
--- a/internal/fusefrontend/fs_dir.go
+++ b/internal/fusefrontend/fs_dir.go
@@ -11,6 +11,8 @@ import (
"sync"
"syscall"
+ "golang.org/x/sys/unix"
+
"github.com/hanwen/go-fuse/fuse"
"github.com/rfjakob/gocryptfs/internal/configfile"
@@ -231,9 +233,7 @@ retry:
return fuse.ToStatus(err)
}
// Actual Rmdir
- // TODO Use syscall.Unlinkat with the AT_REMOVEDIR flag once it is available
- // in Go
- err = syscall.Rmdir(cPath)
+ err = syscallcompat.Unlinkat(int(parentDirFd.Fd()), cName, unix.AT_REMOVEDIR)
if err != nil {
// This can happen if another file in the directory was created in the
// meantime, undo the rename
@@ -245,7 +245,7 @@ retry:
return fuse.ToStatus(err)
}
// Delete "gocryptfs.diriv.rmdir.XYZ"
- err = syscallcompat.Unlinkat(int(parentDirFd.Fd()), tmpName)
+ err = syscallcompat.Unlinkat(int(parentDirFd.Fd()), tmpName, 0)
if err != nil {
tlog.Warn.Printf("Rmdir: Could not clean up %s: %v", tmpName, err)
}
diff --git a/internal/nametransform/longnames.go b/internal/nametransform/longnames.go
index 7cd904e..614af47 100644
--- a/internal/nametransform/longnames.go
+++ b/internal/nametransform/longnames.go
@@ -90,7 +90,7 @@ func ReadLongName(path string) (string, error) {
// DeleteLongName deletes "hashName.name".
func DeleteLongName(dirfd *os.File, hashName string) error {
- err := syscallcompat.Unlinkat(int(dirfd.Fd()), hashName+LongNameSuffix)
+ err := syscallcompat.Unlinkat(int(dirfd.Fd()), hashName+LongNameSuffix, 0)
if err != nil {
tlog.Warn.Printf("DeleteLongName: %v", err)
}
diff --git a/internal/syscallcompat/sys_darwin.go b/internal/syscallcompat/sys_darwin.go
index 4068e1a..527598b 100644
--- a/internal/syscallcompat/sys_darwin.go
+++ b/internal/syscallcompat/sys_darwin.go
@@ -6,6 +6,8 @@ import (
"path/filepath"
"sync"
"syscall"
+
+ "golang.org/x/sys/unix"
)
// Sorry, fallocate is not available on OSX at all and
@@ -71,21 +73,24 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) error
}
// Poor man's Unlinkat
-func Unlinkat(dirfd int, path string) error {
+func Unlinkat(dirfd int, path string, flags int) (err error) {
chdirMutex.Lock()
defer chdirMutex.Unlock()
- if !filepath.IsAbs(path) {
- oldWd, err := os.Getwd()
- if err != nil {
- return err
- }
- defer os.Chdir(oldWd)
+ cwd, err := syscall.Open(".", syscall.O_RDONLY, 0)
+ if err != nil {
+ return err
}
- path, err := dirfdAbs(dirfd, path)
+ defer syscall.Close(cwd)
+ err = syscall.Fchdir(dirfd)
if err != nil {
return err
}
- return syscall.Unlink(path)
+ defer syscall.Fchdir(cwd)
+ if (flags & unix.AT_REMOVEDIR) != 0 {
+ return syscall.Rmdir(path)
+ } else {
+ return syscall.Unlink(path)
+ }
}
// Poor man's Mknodat
diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go
index 277015e..0e9d6ac 100644
--- a/internal/syscallcompat/sys_linux.go
+++ b/internal/syscallcompat/sys_linux.go
@@ -54,9 +54,19 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e
return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath)
}
-// Unlinkat wraps the Unlinkat syscall.
-func Unlinkat(dirfd int, path string) error {
- return syscall.Unlinkat(dirfd, path)
+// Unlinkat syscall. In old versions the 'flags' argument was missing, so
+// manually call it by using the corresponding syscall number.
+func Unlinkat(dirfd int, path string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = syscall.BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ _, _, e1 := syscall.Syscall(syscall.SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags))
+ if e1 != 0 {
+ err = e1
+ }
+ return
}
// Mknodat wraps the Mknodat syscall.