lib9p

Go 9P library.
Log | Files | Refs | LICENSE

commit 3c471431ecaa5bd5c2ee73095c4a979ce55d9c9c
parent 1c1350af11687f183d26b16c8a50c76c7f0726db
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat, 19 Oct 2024 13:53:29 +0900

Permit changing Atime field by Wstat messages.
This operation is not permitted by the 9P protocol, but
some utilities (touch, mv, git...) try to change them.

Diffstat:
Mdiskfs/stat_unix.go | 12++++++++++--
Mserver.go | 46+++++++++++++++++++++++++++++++++++++---------
2 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/diskfs/stat_unix.go b/diskfs/stat_unix.go @@ -116,10 +116,18 @@ func (f *File) wstat(s *lib9p.Stat) error { return fmt.Errorf("chmod: %v", err) } } + // TODO: changing atime is not permitted by the protocol, but some unix + // utilities try to change it (e.g. mv, touch, git). + if s.Atime != oldStat.Atime { + err := os.Chtimes(path.Join(f.fs.rootPath, f.path), time.Unix(int64(s.Mtime), 0), time.Time{}) + if err != nil { + return fmt.Errorf("change atime: %v", err) + } + } if s.Mtime != oldStat.Mtime { - err := os.Chtimes(f.path, time.Time{}, time.Unix(int64(s.Mtime), 0)) + err := os.Chtimes(path.Join(f.fs.rootPath, f.path), time.Time{}, time.Unix(int64(s.Mtime), 0)) if err != nil { - return fmt.Errorf("chtimes: %v", err) + return fmt.Errorf("change mtime: %v", err) } } if s.Gid != oldStat.Gid { diff --git a/server.go b/server.go @@ -1114,15 +1114,43 @@ func sWStat(ctx context.Context, c *conn, rc <-chan *request) { r.err = fmt.Errorf("qid mismatch") goto resp } - if wstat.Type != ^uint16(0) && wstat.Type != newStat.Type || - wstat.Dev != ^uint32(0) && wstat.Dev != newStat.Dev || - wstat.Qid.Type != QidType(^uint8(0)) && wstat.Qid.Type != newStat.Qid.Type || - wstat.Qid.Vers != ^uint32(0) && wstat.Qid.Vers != newStat.Qid.Vers || - wstat.Qid.Path != ^uint64(0) && wstat.Qid.Path != newStat.Qid.Path || - wstat.Atime != ^uint32(0) && wstat.Atime != newStat.Atime || - wstat.Uid != "" && wstat.Uid != newStat.Uid || - wstat.Muid != "" && wstat.Muid != newStat.Muid { - r.err = fmt.Errorf("operation not permitted") + if wstat.Type != ^uint16(0) && wstat.Type != newStat.Type { + r.err = fmt.Errorf("changing type is not permitted") + goto resp + } + if wstat.Dev != ^uint32(0) && wstat.Dev != newStat.Dev { + r.err = fmt.Errorf("changing dev is not permitted") + goto resp + } + if wstat.Qid.Type != QidType(^uint8(0)) && wstat.Qid.Type != newStat.Qid.Type { + r.err = fmt.Errorf("changing qid type is not permitted") + goto resp + } + if wstat.Qid.Vers != ^uint32(0) && wstat.Qid.Vers != newStat.Qid.Vers { + r.err = fmt.Errorf("changing qid vers is not permitted") + goto resp + } + if wstat.Qid.Path != ^uint64(0) && wstat.Qid.Path != newStat.Qid.Path { + r.err = fmt.Errorf("changing qid path is not permitted") + goto resp + } + // TODO: some unix utilities (e.g. touch, mv, git) tries to change atime. + // But changing atime is prohibited by the protocol. + if wstat.Atime != ^uint32(0) && wstat.Atime != newStat.Atime { + if r.fid.uid != newStat.Uid && !isGroupLeader(r.fid.fs, newStat.Gid, r.fid.uid) { + r.err = ErrPerm + goto resp + } + newStat.Atime = wstat.Atime + //r.err = fmt.Errorf("changing atime is not permitted") + //goto resp + } + if wstat.Uid != "" && wstat.Uid != newStat.Uid { + r.err = fmt.Errorf("changing uid is not permitted") + goto resp + } + if wstat.Muid != "" && wstat.Muid != newStat.Muid { + r.err = fmt.Errorf("changing muid is not permitted") goto resp } if wstat.Name != "" && newStat.Name != wstat.Name {