aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/fusefrontend/fs.go20
-rw-r--r--internal/syscallcompat/sys_darwin.go16
-rw-r--r--internal/syscallcompat/sys_linux.go5
3 files changed, 32 insertions, 9 deletions
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index b4819fd..8f77538 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -10,6 +10,8 @@ import (
"syscall"
"time"
+ "golang.org/x/sys/unix"
+
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
@@ -280,15 +282,14 @@ func (fs *FS) Mknod(path string, mode uint32, dev uint32, context *fuse.Context)
if err != nil {
return fuse.ToStatus(err)
}
+ dirfd, err := os.Open(filepath.Dir(cPath))
+ if err != nil {
+ return fuse.ToStatus(err)
+ }
+ defer dirfd.Close()
// Create ".name" file to store long file name
cName := filepath.Base(cPath)
if nametransform.IsLongContent(cName) {
- var dirfd *os.File
- dirfd, err = os.Open(filepath.Dir(cPath))
- if err != nil {
- return fuse.ToStatus(err)
- }
- defer dirfd.Close()
err = fs.nameTransform.WriteLongName(dirfd, cName, path)
if err != nil {
return fuse.ToStatus(err)
@@ -300,16 +301,17 @@ func (fs *FS) Mknod(path string, mode uint32, dev uint32, context *fuse.Context)
}
} else {
// Create regular device node
- err = syscall.Mknod(cPath, mode, int(dev))
+ err = syscallcompat.Mknodat(int(dirfd.Fd()), cName, mode, int(dev))
}
if err != nil {
return fuse.ToStatus(err)
}
// Set owner
if fs.args.PreserveOwner {
- err = os.Lchown(cPath, int(context.Owner.Uid), int(context.Owner.Gid))
+ err = syscallcompat.Fchownat(int(dirfd.Fd()), cName, int(context.Owner.Uid),
+ int(context.Owner.Gid), unix.AT_SYMLINK_NOFOLLOW)
if err != nil {
- tlog.Warn.Printf("Mknod: Lchown failed: %v", err)
+ tlog.Warn.Printf("Mknod: Fchownat failed: %v", err)
}
}
return fuse.OK
diff --git a/internal/syscallcompat/sys_darwin.go b/internal/syscallcompat/sys_darwin.go
index e77cd98..5bc5fba 100644
--- a/internal/syscallcompat/sys_darwin.go
+++ b/internal/syscallcompat/sys_darwin.go
@@ -131,3 +131,19 @@ func Dup3(oldfd int, newfd int, flags int) (err error) {
}
return syscall.Dup2(oldfd, newfd)
}
+
+// Poor man's Fchownat.
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+ cwd, err := syscall.Open(".", syscall.O_RDONLY, 0)
+ if err != nil {
+ return err
+ }
+ chdirMutex.Lock()
+ defer chdirMutex.Unlock()
+ err = syscall.Fchdir(dirfd)
+ if err != nil {
+ return err
+ }
+ defer syscall.Fchdir(cwd)
+ return syscall.Lchown(path, uid, gid)
+}
diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go
index 441f904..8a64a81 100644
--- a/internal/syscallcompat/sys_linux.go
+++ b/internal/syscallcompat/sys_linux.go
@@ -68,3 +68,8 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
func Dup3(oldfd int, newfd int, flags int) (err error) {
return syscall.Dup3(oldfd, newfd, flags)
}
+
+// Fchownat syscall.
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+ return syscall.Fchownat(dirfd, path, uid, gid, flags)
+}