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:
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 {