diff options
Diffstat (limited to 'internal/fusefrontend/file2_setattr.go')
-rw-r--r-- | internal/fusefrontend/file2_setattr.go | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/internal/fusefrontend/file2_setattr.go b/internal/fusefrontend/file2_setattr.go new file mode 100644 index 0000000..c341e53 --- /dev/null +++ b/internal/fusefrontend/file2_setattr.go @@ -0,0 +1,83 @@ +package fusefrontend + +import ( + "context" + "syscall" + + "github.com/hanwen/go-fuse/v2/fs" + "github.com/hanwen/go-fuse/v2/fuse" + + "github.com/rfjakob/gocryptfs/internal/syscallcompat" +) + +func (f *File2) Setattr(ctx context.Context, in *fuse.SetAttrIn, out *fuse.AttrOut) (errno syscall.Errno) { + errno = f.setAttr(ctx, in) + if errno != 0 { + return errno + } + return f.Getattr(ctx, out) +} + +func (f *File2) setAttr(ctx context.Context, in *fuse.SetAttrIn) (errno syscall.Errno) { + f.fdLock.RLock() + defer f.fdLock.RUnlock() + if f.released { + return syscall.EBADF + } + f.fileTableEntry.ContentLock.Lock() + defer f.fileTableEntry.ContentLock.Unlock() + + // chmod(2) & fchmod(2) + if mode, ok := in.GetMode(); ok { + errno = fs.ToErrno(syscall.Fchmod(f.intFd(), mode)) + if errno != 0 { + return errno + } + } + + // chown(2) & fchown(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(syscall.Fchown(f.intFd(), uid, gid)) + 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.FutimesNano(f.intFd(), ap, mp)) + if errno != 0 { + return errno + } + } + + // truncate(2) + if sz, ok := in.GetSize(); ok { + errno = syscall.Errno(f.truncate(sz)) + if errno != 0 { + return errno + } + } + return 0 +} |