From 9c56cd3ecb521dfbc5aba8724f35013c985bc91f Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Tue, 26 May 2015 16:28:12 +0900 Subject: [PATCH] Improved support for get/setattr --- dir.go | 7 ++---- file.go | 7 ++---- node.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/dir.go b/dir.go index 580fb40..3bbf184 100644 --- a/dir.go +++ b/dir.go @@ -91,19 +91,16 @@ func (this *versionedDir) Attr(attr *fuse.Attr) { } func (this *versionedDir) Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error { - info, err := os.Stat(this.node.rebasedPath()) - if err != nil { + if err := this.node.updateInfo(); err != nil { return err } - this.node.info = info this.Attr(&resp.Attr) return nil } func (this *versionedDir) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { - this.Attr(&resp.Attr) - return nil + return this.node.setAttr(req, resp) } func (this *versionedDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) { diff --git a/file.go b/file.go index af6c964..f55f8f9 100644 --- a/file.go +++ b/file.go @@ -64,19 +64,16 @@ func (this *versionedFile) Attr(attr *fuse.Attr) { } func (this *versionedFile) Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error { - info, err := os.Stat(this.node.rebasedPath()) - if err != nil { + if err := this.node.updateInfo(); err != nil { return err } - this.node.info = info this.Attr(&resp.Attr) return nil } func (this *versionedFile) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { - this.Attr(&resp.Attr) - return nil + return this.node.setAttr(req, resp) } func (this *versionedFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error { diff --git a/node.go b/node.go index f2b1ebc..a0eb9fa 100644 --- a/node.go +++ b/node.go @@ -52,22 +52,89 @@ func newVersionedNodeStat(path string, ver *version, info os.FileInfo) *versione return &versionedNode{path, info, ver, nil} } +func (this *versionedNode) setAttr(req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { + if req.Valid&fuse.SetattrMode != 0 { + if err := os.Chmod(this.rebasedPath(), req.Mode); err != nil { + return err + } + } + + if setGid, setUid := req.Valid&fuse.SetattrGid != 0, req.Valid&fuse.SetattrUid != 0; setGid || setUid { + gid, uid := this.owner() + if setGid { + gid = req.Gid + } + if setUid { + uid = req.Uid + } + + if err := os.Chown(this.rebasedPath(), int(uid), int(gid)); err != nil { + return err + } + } + + if setAtime, setMtime := req.Valid&fuse.SetattrAtime != 0, req.Valid&fuse.SetattrMtime != 0; setAtime || setMtime { + atime, mtime, _ := this.times() + if setAtime { + atime = req.Atime + } + if setMtime { + mtime = req.Mtime + } + + if err := os.Chtimes(this.rebasedPath(), atime, mtime); err != nil { + return err + } + } + + if err := this.updateInfo(); err != nil { + return err + } + + this.attr(&resp.Attr) + return nil +} + +func (this *versionedNode) updateInfo() error { + info, err := os.Stat(this.rebasedPath()) + if err != nil { + return err + } + + this.info = info + return nil +} + func (this *versionedNode) rebasedPath() string { return this.ver.rebasePath(this.path) } +func (this *versionedNode) owner() (gid, uid uint32) { + stat := this.info.Sys().(*syscall.Stat_t) + + gid = stat.Gid + uid = stat.Uid + return +} + +func (this *versionedNode) times() (atime, mtime, ctime time.Time) { + stat := this.info.Sys().(*syscall.Stat_t) + + atime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) + mtime = this.info.ModTime() + ctime = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)) + return +} + func (this *versionedNode) attr(attr *fuse.Attr) { stat := this.info.Sys().(*syscall.Stat_t) attr.Size = uint64(this.info.Size()) attr.Blocks = uint64(stat.Blocks) - attr.Atime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) - attr.Mtime = this.info.ModTime() - attr.Ctime = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)) + attr.Atime, attr.Mtime, attr.Ctime = this.times() attr.Mode = this.info.Mode() attr.Nlink = uint32(stat.Nlink) - attr.Uid = stat.Uid - attr.Gid = stat.Gid + attr.Uid, attr.Gid = this.owner() attr.Rdev = uint32(stat.Rdev) }