v2api: properly implement Node.Setattr
We used to always open a *File2 and letting the *File2 handle Setattr. This does not work it we cannot open the file! Before: $ go test 2020/07/12 20:14:57 writer: Write/Writev failed, err: 2=no such file or directory. opcode: INTERRUPT 2020/07/12 20:14:57 writer: Write/Writev failed, err: 2=no such file or directory. opcode: INTERRUPT --- FAIL: TestLchown (0.00s) matrix_test.go:634: lchown /tmp/gocryptfs-test-parent-1026/014500839/default-plain/symlink: too many levels of symbolic links touch: setting times of '/tmp/gocryptfs-test-parent-1026/014500839/default-plain/utimesnano_symlink': Too many levels of symbolic links --- FAIL: TestUtimesNanoSymlink (0.00s) matrix_test.go:655: exit status 1 --- FAIL: TestMkfifo (0.00s) matrix_test.go:755: file exists --- FAIL: TestMagicNames (0.00s) matrix_test.go:773: Testing n="gocryptfs.longname.QhUr5d9FHerwEs--muUs6_80cy6JRp89c1otLwp92Cs" matrix_test.go:773: Testing n="gocryptfs.diriv" matrix_test.go:815: open /tmp/gocryptfs-test-parent-1026/014500839/default-plain/linktarget: permission denied --- FAIL: TestChmod (0.00s) matrix_test.go:840: chmod 444 -> 000 failed: permission denied matrix_test.go:840: chmod 444 -> 111 failed: permission denied matrix_test.go:840: chmod 444 -> 123 failed: permission denied matrix_test.go:840: chmod 444 -> 321 failed: permission denied FAIL exit status 1 FAIL github.com/rfjakob/gocryptfs/tests/matrix 0.790s After: $ go test --- FAIL: TestMkfifo (0.00s) matrix_test.go:755: file exists --- FAIL: TestMagicNames (0.00s) matrix_test.go:773: Testing n="gocryptfs.longname.QhUr5d9FHerwEs--muUs6_80cy6JRp89c1otLwp92Cs" matrix_test.go:773: Testing n="gocryptfs.diriv" matrix_test.go:815: open /tmp/gocryptfs-test-parent-1026/501766059/default-plain/linktarget: permission denied --- FAIL: TestChmod (0.00s) matrix_test.go:849: modeHave 0644 != modeWant 0 FAIL exit status 1 FAIL github.com/rfjakob/gocryptfs/tests/matrix 0.787s
This commit is contained in:
parent
f11432d02a
commit
0fa824933c
|
@ -29,7 +29,7 @@ func (f *File2) setAttr(ctx context.Context, in *fuse.SetAttrIn) (errno syscall.
|
||||||
f.fileTableEntry.ContentLock.Lock()
|
f.fileTableEntry.ContentLock.Lock()
|
||||||
defer f.fileTableEntry.ContentLock.Unlock()
|
defer f.fileTableEntry.ContentLock.Unlock()
|
||||||
|
|
||||||
// chmod(2) & fchmod(2)
|
// fchmod(2)
|
||||||
if mode, ok := in.GetMode(); ok {
|
if mode, ok := in.GetMode(); ok {
|
||||||
errno = fs.ToErrno(syscall.Fchmod(f.intFd(), mode))
|
errno = fs.ToErrno(syscall.Fchmod(f.intFd(), mode))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
|
@ -37,7 +37,7 @@ func (f *File2) setAttr(ctx context.Context, in *fuse.SetAttrIn) (errno syscall.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// chown(2) & fchown(2)
|
// fchown(2)
|
||||||
uid32, uOk := in.GetUID()
|
uid32, uOk := in.GetUID()
|
||||||
gid32, gOk := in.GetGID()
|
gid32, gOk := in.GetGID()
|
||||||
if uOk || gOk {
|
if uOk || gOk {
|
||||||
|
|
|
@ -296,18 +296,77 @@ func (n *Node) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, fuseFl
|
||||||
|
|
||||||
// Setattr - FUSE call. Called for chmod, truncate, utimens, ...
|
// Setattr - FUSE call. Called for chmod, truncate, utimens, ...
|
||||||
func (n *Node) Setattr(ctx context.Context, f fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) (errno syscall.Errno) {
|
func (n *Node) Setattr(ctx context.Context, f fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) (errno syscall.Errno) {
|
||||||
var f2 *File2
|
// Use the fd if the kernel gave us one
|
||||||
if f != nil {
|
if f != nil {
|
||||||
f2 = f.(*File2)
|
f2 := f.(*File2)
|
||||||
} else {
|
return f2.Setattr(ctx, in, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
dirfd, cName, errno := n.prepareAtSyscall("")
|
||||||
|
if errno != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer syscall.Close(dirfd)
|
||||||
|
|
||||||
|
// chmod(2)
|
||||||
|
if mode, ok := in.GetMode(); ok {
|
||||||
|
errno = fs.ToErrno(syscallcompat.FchmodatNofollow(dirfd, cName, mode))
|
||||||
|
if errno != 0 {
|
||||||
|
return errno
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// chown(2)
|
||||||
|
uid32, uOk := in.GetUID()
|
||||||
|
gid32, gOk := in.GetGID()
|
||||||
|
if uOk || gOk {
|
||||||
|
uid := -1
|
||||||
|
gid := -1
|
||||||
|
|
||||||
|
if uOk {
|
||||||
|
uid = int(uid32)
|
||||||
|
}
|
||||||
|
if gOk {
|
||||||
|
gid = int(gid32)
|
||||||
|
}
|
||||||
|
errno = fs.ToErrno(syscallcompat.Fchownat(dirfd, cName, uid, gid, unix.AT_SYMLINK_NOFOLLOW))
|
||||||
|
if errno != 0 {
|
||||||
|
return errno
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// utimens(2)
|
||||||
|
mtime, mok := in.GetMTime()
|
||||||
|
atime, aok := in.GetATime()
|
||||||
|
if mok || aok {
|
||||||
|
ap := &atime
|
||||||
|
mp := &mtime
|
||||||
|
if !aok {
|
||||||
|
ap = nil
|
||||||
|
}
|
||||||
|
if !mok {
|
||||||
|
mp = nil
|
||||||
|
}
|
||||||
|
errno = fs.ToErrno(syscallcompat.UtimesNanoAtNofollow(dirfd, cName, ap, mp))
|
||||||
|
if errno != 0 {
|
||||||
|
return errno
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For truncate, the user has to have write permissions. That means we can
|
||||||
|
// depend on opening a RDWR fd and letting the File handle truncate.
|
||||||
|
if sz, ok := in.GetSize(); ok {
|
||||||
f, _, errno := n.Open(ctx, syscall.O_RDWR)
|
f, _, errno := n.Open(ctx, syscall.O_RDWR)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return errno
|
return errno
|
||||||
}
|
}
|
||||||
f2 = f.(*File2)
|
f2 := f.(*File2)
|
||||||
defer f2.Release(ctx)
|
errno = syscall.Errno(f2.truncate(sz))
|
||||||
|
if errno != 0 {
|
||||||
|
return errno
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return f2.Setattr(ctx, in, out)
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatFs - FUSE call. Returns information about the filesystem.
|
// StatFs - FUSE call. Returns information about the filesystem.
|
||||||
|
|
Loading…
Reference in New Issue