syscallcompat: Introduce unlinkat syscall with flags argument

This commit is contained in:
Sebastian Lackner 2017-11-29 12:23:40 +01:00
parent 5d44a31b41
commit 0f44c617d0
5 changed files with 34 additions and 19 deletions

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}
path, err := dirfdAbs(dirfd, path)
cwd, err := syscall.Open(".", syscall.O_RDONLY, 0)
if err != nil {
return err
}
return syscall.Unlink(path)
defer syscall.Close(cwd)
err = syscall.Fchdir(dirfd)
if err != nil {
return err
}
defer syscall.Fchdir(cwd)
if (flags & unix.AT_REMOVEDIR) != 0 {
return syscall.Rmdir(path)
} else {
return syscall.Unlink(path)
}
}
// Poor man's Mknodat

View File

@ -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.