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