lib9p

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

commit 9ea6d89879fdf596905e9c7e03023decf9e71b46
parent 087982208a459c81026e30d43d386b8cb6836dc9
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue,  2 Jan 2024 09:14:42 +0900

remove group methods from FS and add new interface GroupFS

Diffstat:
Mfs.go | 7++++++-
Mserver.go | 6+++---
Mserver2_test.go | 4++--
Muid.go | 23++++++++++++++++++++++-
4 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/fs.go b/fs.go @@ -4,10 +4,15 @@ import ( "io/fs" ) -// FS is an file system to be exported by 9P server. +// An FS is an file system to be exported by 9P server. type FS interface { // OpenFile opens file named name with omode. OpenFile(name string, omode OpenMode) (File, error) +} + +// A GroupFS is an file system with the notion of group. +type GroupFS interface { + FS // IsGroupLeader reports whether uid is the leader of group. IsGroupLeader(group, uid string) bool // IsGroupMember reports whether uid is a member of group. diff --git a/server.go b/server.go @@ -1122,9 +1122,9 @@ func sWStat(ctx context.Context, c *conn, rc <-chan *request) { // by the owner if also a member of the new group; // or by the group leader of the file'c current group if // also the leader of the new group. - if r.fid.uid == newStat.Uid && c.s.fs.IsGroupMember(wstat.Gid, r.fid.uid) || - c.s.fs.IsGroupLeader(newStat.Gid, r.fid.uid) && - c.s.fs.IsGroupLeader(wstat.Gid, r.fid.uid) { + if r.fid.uid == newStat.Uid && isGroupMember(c.s.fs, wstat.Gid, r.fid.uid) || + isGroupLeader(c.s.fs, newStat.Gid, r.fid.uid) && + isGroupLeader(c.s.fs, wstat.Gid, r.fid.uid) { newStat.Gid = wstat.Gid } else { r.err = ErrPerm diff --git a/server2_test.go b/server2_test.go @@ -13,8 +13,6 @@ import ( // TestRunListener tests if the listener goroutine receives 9P messages // and send them through the server's listenChan channel. -// It also checks whether the listener goroutine returns by canceling -// ctx, by checking if the server's listenChan is closed. func TestRunListener(t *testing.T) { tFile, err := os.Open("testdata/test_Tmsg.dat") if err != nil { @@ -96,6 +94,8 @@ func TestRunResponder(t *testing.T) { } } +// TestGetReq tests if getReq returns the same Msg as RecvMsg and +// registers the Msg to the ReqPool. func TestGetReq(t *testing.T) { tFile, err := os.Open("testdata/test_Tmsg.dat") if err != nil { diff --git a/uid.go b/uid.go @@ -19,7 +19,7 @@ func hasPerm(fsys FS, fi fs.FileInfo, uid string, p fs.FileMode) bool { return true } } - if fsys.IsGroupMember(stat.Gid, uid) { + if isGroupMember(fsys, stat.Gid, uid) { m |= (fp >> 3) & 7 if (p & m) == p { return true @@ -27,3 +27,23 @@ func hasPerm(fsys FS, fi fs.FileInfo, uid string, p fs.FileMode) bool { } return false } + +// IsGroupMember reports whether the user uid belongs to the group gid. +// If fsys implement GroupFS, it calls fsys.IsGroupMember, otherwise, +// it just reports whether uid is equal to gid. +func isGroupMember(fsys FS, gid, uid string) bool { + if fsys, ok := fsys.(GroupFS); ok { + return fsys.IsGroupMember(gid, uid) + } + return gid == uid +} + +// IsGroupLeader reports whether the user uid is the leader of the group gid. +// If fsys implement GroupFS, it calls fsys.IsGroupLeader, otherwise, +// it just reports whether uid is equal to gid. +func isGroupLeader(fsys FS, gid, uid string) bool { + if fsys, ok := fsys.(GroupFS); ok { + return fsys.IsGroupLeader(gid, uid) + } + return gid == uid +} +\ No newline at end of file