lib9p

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

commit 0c7b1e586f357f47d72d06d12437549f6a675706
parent 7e515ad7cc20e51a137378d22abae7164d23e286
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 19 Dec 2023 14:46:05 +0900

add test for chgrp

Diffstat:
Mdiskfs/file.go | 2+-
Mdiskfs/stat_unix.go | 26+-------------------------
Mdiskfs/stat_unix_test.go | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mserver.go | 15++++++++++++---
4 files changed, 75 insertions(+), 29 deletions(-)

diff --git a/diskfs/file.go b/diskfs/file.go @@ -84,7 +84,7 @@ func (f *File) ReadDir(n int) ([]fs.DirEntry, error) { id := idFromInfo(f.path, fi) stat, err := fiStat(f.fs.qidPool, id, fi) if err != nil { - return nil, fmt.Errorf("fiStat: %v") + return nil, fmt.Errorf("fiStat: %v", err) } de[i] = &lib9p.DirEntry{Stat: *stat} diff --git a/diskfs/stat_unix.go b/diskfs/stat_unix.go @@ -141,7 +141,7 @@ func (f *File) wstat(s *lib9p.Stat) error { if err := os.Chown(filepath.Join(f.fs.rootPath, f.path), u, g); err != nil { return fmt.Errorf("chown: %v", err) } - st, err := fs.Stat(lib9p.ExportFS{f.fs}, filepath.Join(f.fs.rootPath, f.path)) + st, err := os.Stat(filepath.Join(f.fs.rootPath, f.path)) if err != nil { return fmt.Errorf("stat: %v", err) } @@ -159,26 +159,3 @@ func (f *File) wstat(s *lib9p.Stat) error { } return nil } - -func chown(ospath string, uid, gid string) error { - usr, err := user.Lookup(uid) - if err != nil { - return fmt.Errorf("lookup user: %v", err) - } - u, err := strconv.Atoi(usr.Uid) - if err != nil { - return fmt.Errorf("convert uid: %v", err) - } - group, err := user.LookupGroup(gid) - if err != nil { - return fmt.Errorf("lookupgroup: %v", err) - } - g, err := strconv.Atoi(group.Gid) - if err != nil { - return fmt.Errorf("convert gid: %v", err) - } - if err := os.Chown(ospath, u, g); err != nil { - return fmt.Errorf("set owner and group: %v", err) - } - return nil -} -\ No newline at end of file diff --git a/diskfs/stat_unix_test.go b/diskfs/stat_unix_test.go @@ -1,3 +1,4 @@ +//go:build unix package diskfs import ( @@ -38,4 +39,64 @@ func BenchmarkGID(b *testing.B) { b.Fatalf("stat: %v", err) } } +} + +func TestChgrp(t *testing.T) { + cr, sw := io.Pipe() + defer cr.Close() + defer sw.Close() + sr, cw := io.Pipe() + defer sr.Close() + defer cw.Close() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + disk, err := Open(testdir) + if err != nil { + t.Fatalf("open dir: %v", err) + } + s := lib9p.NewServer(disk, 8*1024, sr, sw) + go s.Serve(ctx) + c := client.NewClient(8*1024, "kenji", cr, cw) + defer c.Stop() + _, err = c.Attach(ctx, ^uint16(0), 0, lib9p.NOFID, "kenji", "") + if err != nil { + t.Fatalf("attach: %v", err) + } + wname := []string{"a"} + wqid, err := c.Walk(ctx, 0, 0, 1, wname) + if len(wqid) != len(wname) || err != nil { + t.Fatalf("file not found: %v", err) + } + st, err := c.Stat(ctx, 0, 1) + if err != nil { + t.Fatalf("stat: %v", err) + } + oldGid := st.Gid + t.Logf("old stat: %v", st) + st.Gid = "wheel" + err = c.Wstat(ctx, 0, 1, st) + if err != nil { + t.Fatalf("wstat: %v", err) + } + st, err = c.Stat(ctx, 0, 1) + if err != nil { + t.Fatalf("stat: %v", err) + } + t.Logf("new stat: %v", st) + if st.Gid != "wheel" { + t.Fatal("gid not changed to wheel.") + } + st.Gid = oldGid + err = c.Wstat(ctx, 0, 1, st) + if err != nil { + t.Fatalf("wstat: %v", err) + } + st, err = c.Stat(ctx, 0, 1) + if err != nil { + t.Fatalf("stat: %v", err) + } + t.Logf("restored stat: %v", st) + if st.Gid != oldGid { + t.Fatalf("gid not restored to %v.", oldGid) + } } \ No newline at end of file diff --git a/server.go b/server.go @@ -880,10 +880,19 @@ func sWStat(ctx context.Context, s *Server, r *Req) { } newStat.Mtime = wstat.Mtime } + // TODO: check group membership + // now group member == group leader == gid if wstat.Gid != "" && wstat.Gid != newStat.Gid { - // TODO implement - Respond(ctx, r, fmt.Errorf("not implemented")) - return + // by the owner if also a member of the new group; + // or by the group leader of the file's current group if + // also the leader of the new group. + if r.Fid.Uid == newStat.Uid && r.Fid.Uid == wstat.Gid || + r.Fid.Uid == newStat.Gid && r.Fid.Uid == wstat.Gid { + newStat.Gid = wstat.Gid + } else { + Respond(ctx, r, ErrPerm) + return + } } err = wsfile.WStat(newStat) if err != nil {