commit 7a7f18f9bc9ba240e32963b4507c39d23ac3e78c
parent 8a84f2d965a87e77b329f5ee8fc36bb770396eff
Author: Matsuda Kenji <info@mtkn.jp>
Date: Mon, 25 Dec 2023 18:39:53 +0900
delete r... functions
Diffstat:
| M | auth_test.go | | | 15 | +++++++++------ |
| M | server.go | | | 359 | +++++++++++++++++++++++++++---------------------------------------------------- |
2 files changed, 132 insertions(+), 242 deletions(-)
diff --git a/auth_test.go b/auth_test.go
@@ -9,6 +9,9 @@ import (
"git.mtkn.jp/lib9p/testfs"
)
+// TODO: this test sometimes fails.
+// err: unknown fid, or err: not authenticated.
+// maybe there is some race condition or something.
func TestAuth(t *testing.T) {
conn := testfs.SetupConn()
defer conn.Close()
@@ -55,27 +58,27 @@ func TestAuth(t *testing.T) {
}
_, err = conn.C.Auth(ctx, 0, 0, "kenji", "")
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
_, err = conn.C.Attach(ctx, 0, 1, 0, "kenji", "")
if err == nil {
- t.Error("authentication skipped")
+ t.Fatal("authentication skipped")
}
_, _, err = conn.C.Open(ctx, 0, 0, lib9p.ORDWR)
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
_, err = conn.C.Write(ctx, 0, 0, 0, 5, []byte("kenji"))
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
_, err = conn.C.Write(ctx, 0, 0, 0, 8, []byte("password"))
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
_, err = conn.C.Attach(ctx, 0, 1, 0, "kenji", "")
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
}
diff --git a/server.go b/server.go
@@ -445,7 +445,7 @@ func sOpen(ctx context.Context, s *Server, c <-chan *Req) {
return
}
var (
- p fs.FileMode
+ p fs.FileMode
err error
qid Qid
st fs.FileInfo
@@ -548,9 +548,6 @@ func sOpen(ctx context.Context, s *Server, c <-chan *Req) {
}
func sCreate(ctx context.Context, s *Server, c <-chan *Req) {
- rc := make(chan *Req)
- defer close(rc)
- go rCreate(ctx, rc)
for {
select {
case <-ctx.Done():
@@ -559,80 +556,70 @@ func sCreate(ctx context.Context, s *Server, c <-chan *Req) {
if !ok {
return
}
+ var (
+ st fs.FileInfo
+ dirstat fs.FileInfo
+ err error
+ file File
+ cfs CreaterFS
+ cpath string
+ perm FileMode
+ dirperm FileMode
+ )
ifcall := r.Ifcall.(*TCreate)
r.Fid, ok = s.fPool.lookup(ifcall.Fid)
if !ok {
r.err = ErrUnknownFid
- rc <- r
- continue
+ goto resp
}
- dirstat, err := fs.Stat(ExportFS{s.fs}, r.Fid.path)
+ dirstat, err = fs.Stat(ExportFS{s.fs}, r.Fid.path)
if err != nil {
r.err = fmt.Errorf("stat: %v", err)
- rc <- r
- continue
+ goto resp
}
if !dirstat.IsDir() {
r.err = fmt.Errorf("create in non-dir")
- rc <- r
- continue
+ goto resp
}
if !hasPerm(s.fs, dirstat, r.Fid.Uid, AWRITE) {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
- cfs, ok := s.fs.(CreaterFS)
+ cfs, ok = s.fs.(CreaterFS)
if !ok {
r.err = ErrOperation
- rc <- r
- continue
+ goto resp
}
- perm := ifcall.Perm
- dirperm := dirstat.Mode()
+ perm = ifcall.Perm
+ dirperm = dirstat.Mode()
if perm&fs.ModeDir == 0 {
perm &= ^FileMode(0666) | (dirperm & FileMode(0666))
} else {
perm &= ^FileMode(0777) | (dirperm & FileMode(0777))
}
- cpath := path.Join(r.Fid.path, ifcall.Name)
- file, err := cfs.Create(cpath, r.Fid.Uid, ifcall.Mode, perm)
+ cpath = path.Join(r.Fid.path, ifcall.Name)
+ file, err = cfs.Create(cpath, r.Fid.Uid, ifcall.Mode, perm)
if err != nil {
r.err = fmt.Errorf("create: %v", err)
- rc <- r
- continue
+ goto resp
}
r.Fid.File = file
r.Fid.path = cpath
r.Fid.OMode = ifcall.Mode
- st, err := r.Fid.File.Stat()
+ st, err = r.Fid.File.Stat()
if err != nil {
r.err = fmt.Errorf("stat: %v", err)
- rc <- r
- continue
+ goto resp
}
r.Ofcall = &RCreate{
Qid: st.Sys().(*Stat).Qid,
Iounit: s.mSize() - IOHDRSZ,
}
- rc <- r
- }
- }
-}
-
-func rCreate(ctx context.Context, c <-chan *Req) {
- for {
- select {
- case <-ctx.Done():
- return
- case r, ok := <-c:
- if !ok {
- return
- }
+ resp:
if r.err != nil {
setError(r, r.err)
}
- r.Srv.respChan <- r
+ s.respChan <- r
}
}
}
@@ -640,14 +627,18 @@ func rCreate(ctx context.Context, c <-chan *Req) {
// TODO: I think the file should be locked while reading.
// or should the undeterminism left for the client side?
func sRead(ctx context.Context, s *Server, c <-chan *Req) {
- rc := make(chan *Req)
- defer close(rc)
- go rRead(ctx, rc)
for {
select {
case <-ctx.Done():
return
case r, ok := <-c:
+ var (
+ fi fs.FileInfo
+ err error
+ data []byte
+ errc chan error
+ n int
+ )
if !ok {
return
}
@@ -655,28 +646,23 @@ func sRead(ctx context.Context, s *Server, c <-chan *Req) {
r.Fid, ok = s.fPool.lookup(ifcall.Fid)
if !ok {
r.err = ErrUnknownFid
- rc <- r
- continue
+ goto resp
}
if r.Fid.OMode == -1 {
r.err = fmt.Errorf("not open")
- rc <- r
- continue
+ goto resp
}
if r.Fid.OMode != OREAD && r.Fid.OMode != ORDWR && r.Fid.OMode != OEXEC {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
- fi, err := r.Fid.File.Stat()
+ fi, err = r.Fid.File.Stat()
if err != nil {
r.err = fmt.Errorf("stat: %v", err)
- rc <- r
- continue
+ goto resp
}
- data := make([]byte, ifcall.Count)
- errc := make(chan error)
- var n int
+ data = make([]byte, ifcall.Count)
+ errc = make(chan error)
go func() {
defer close(errc)
if fi.IsDir() {
@@ -729,8 +715,7 @@ func sRead(ctx context.Context, s *Server, c <-chan *Req) {
case err := <-errc:
if err != nil {
r.err = err
- rc <- r
- continue
+ goto resp
}
case <-r.Done:
continue
@@ -739,33 +724,17 @@ func sRead(ctx context.Context, s *Server, c <-chan *Req) {
Count: uint32(n),
Data: data[:n],
}
- rc <- r
- }
- }
-}
-
-func rRead(ctx context.Context, c <-chan *Req) {
- for {
- select {
- case <-ctx.Done():
- return
- case r, ok := <-c:
- if !ok {
- return
- }
+ resp:
if r.err != nil {
setError(r, r.err)
}
- r.Srv.respChan <- r
+ s.respChan <- r
}
}
}
// TODO: I think the file should be locked while reading.
func sWrite(ctx context.Context, s *Server, c <-chan *Req) {
- rc := make(chan *Req)
- defer close(rc)
- go rWrite(ctx, rc)
for {
select {
case <-ctx.Done():
@@ -774,24 +743,27 @@ func sWrite(ctx context.Context, s *Server, c <-chan *Req) {
if !ok {
return
}
+ var (
+ ofcall *RWrite
+ errc chan error
+ omode OpenMode
+ )
ifcall := r.Ifcall.(*TWrite)
r.Fid, ok = s.fPool.lookup(ifcall.Fid)
if !ok {
r.err = ErrUnknownFid
- rc <- r
- continue
+ goto resp
}
if ifcall.Count > s.mSize()-IOHDRSZ {
ifcall.Count = s.mSize() - IOHDRSZ
}
- omode := r.Fid.OMode & 3
+ omode = r.Fid.OMode & 3
if omode != OWRITE && omode != ORDWR {
r.err = fmt.Errorf("write on fid with open mode 0x%x", r.Fid.OMode)
- rc <- r
- continue
+ goto resp
}
- ofcall := new(RWrite)
- errc := make(chan error)
+ ofcall = new(RWrite)
+ errc = make(chan error)
go func() {
defer close(errc)
switch file := r.Fid.File.(type) {
@@ -818,39 +790,22 @@ func sWrite(ctx context.Context, s *Server, c <-chan *Req) {
case err := <-errc:
if err != nil {
r.err = err
- rc <- r
- continue
+ goto resp
}
case <-r.Done:
continue
}
r.Ofcall = ofcall
- rc <- r
- }
- }
-}
-
-func rWrite(ctx context.Context, c <-chan *Req) {
- for {
- select {
- case <-ctx.Done():
- return
- case r, ok := <-c:
- if !ok {
- return
- }
+ resp:
if r.err != nil {
setError(r, r.err)
}
- r.Srv.respChan <- r
+ s.respChan <- r
}
}
}
func sClunk(ctx context.Context, s *Server, c <-chan *Req) {
- rc := make(chan *Req)
- defer close(rc)
- go rClunk(ctx, rc)
for {
select {
case <-ctx.Done():
@@ -863,45 +818,27 @@ func sClunk(ctx context.Context, s *Server, c <-chan *Req) {
fid, ok := s.fPool.lookup(ifcall.Fid)
if !ok {
r.err = ErrUnknownFid
- rc <- r
- continue
+ goto resp
}
s.fPool.delete(ifcall.Fid)
if fid.OMode != -1 {
if err := fid.File.Close(); err != nil {
r.err = fmt.Errorf("close: %v", err)
- rc <- r
- continue
+ goto resp
}
}
r.Ofcall = &RClunk{}
- rc <- r
- }
- }
-}
-
-func rClunk(ctx context.Context, c <-chan *Req) {
- for {
- select {
- case <-ctx.Done():
- return
- case r, ok := <-c:
- if !ok {
- return
- }
+ resp:
if r.err != nil {
log.Printf("clunk: %v", r.err)
r.Ofcall = &RClunk{}
}
- r.Srv.respChan <- r
+ s.respChan <- r
}
}
}
func sRemove(ctx context.Context, s *Server, c <-chan *Req) {
- rc := make(chan *Req)
- defer close(rc)
- go rRemove(ctx, rc)
for {
select {
case <-ctx.Done():
@@ -910,67 +847,52 @@ func sRemove(ctx context.Context, s *Server, c <-chan *Req) {
if !ok {
return
}
+ var (
+ parentPath string
+ pstat fs.FileInfo
+ err error
+ rfs RemoverFS
+ )
ifcall := r.Ifcall.(*TRemove)
r.Fid, ok = s.fPool.lookup(ifcall.Fid)
if !ok {
r.err = ErrUnknownFid
- rc <- r
- continue
+ goto resp
}
s.fPool.delete(ifcall.Fid)
if r.Fid.OMode != -1 {
r.Fid.File.Close()
}
- parentPath := path.Dir(r.Fid.path)
- pstat, err := fs.Stat(ExportFS{s.fs}, parentPath)
+ parentPath = path.Dir(r.Fid.path)
+ pstat, err = fs.Stat(ExportFS{s.fs}, parentPath)
if err != nil {
r.err = fmt.Errorf("stat parent: %v", err)
- rc <- r
- continue
+ goto resp
}
if !hasPerm(s.fs, pstat, r.Fid.Uid, AWRITE) {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
- rfs, ok := s.fs.(RemoverFS)
+ rfs, ok = s.fs.(RemoverFS)
if !ok {
r.err = ErrOperation
- rc <- r
- continue
+ goto resp
}
- if err := rfs.Remove(r.Fid.path); err != nil {
+ if err = rfs.Remove(r.Fid.path); err != nil {
r.err = fmt.Errorf("remove: %v", err)
- rc <- r
- continue
+ goto resp
}
r.Ofcall = &RRemove{}
- rc <- r
- }
- }
-}
-
-func rRemove(ctx context.Context, c <-chan *Req) {
- for {
- select {
- case <-ctx.Done():
- return
- case r, ok := <-c:
- if !ok {
- return
- }
+ resp:
if r.err != nil {
setError(r, r.err)
}
- r.Srv.respChan <- r
+ s.respChan <- r
}
}
}
func sStat(ctx context.Context, s *Server, c <-chan *Req) {
- rc := make(chan *Req)
- defer close(rc)
- go rStat(ctx, rc)
for {
select {
case <-ctx.Done():
@@ -979,48 +901,34 @@ func sStat(ctx context.Context, s *Server, c <-chan *Req) {
if !ok {
return
}
+ var (
+ fi fs.FileInfo
+ err error
+ )
ifcall := r.Ifcall.(*TStat)
r.Fid, ok = s.fPool.lookup(ifcall.Fid)
if !ok {
r.err = ErrUnknownFid
- rc <- r
- continue
+ goto resp
}
- fi, err := fs.Stat(ExportFS{s.fs}, r.Fid.path)
+ fi, err = fs.Stat(ExportFS{s.fs}, r.Fid.path)
if err != nil {
r.err = fmt.Errorf("stat: %v", err)
- rc <- r
- continue
+ goto resp
}
r.Ofcall = &RStat{
Stat: fi.Sys().(*Stat),
}
- rc <- r
- }
- }
-}
-
-func rStat(ctx context.Context, c <-chan *Req) {
- for {
- select {
- case <-ctx.Done():
- return
- case r, ok := <-c:
- if !ok {
- return
- }
+ resp:
if r.err != nil {
setError(r, r.err)
}
- r.Srv.respChan <- r
+ s.respChan <- r
}
}
}
func sWStat(ctx context.Context, s *Server, c <-chan *Req) {
- rc := make(chan *Req)
- defer close(rc)
- go rWStat(ctx, rc)
for {
select {
case <-ctx.Done():
@@ -1029,37 +937,40 @@ func sWStat(ctx context.Context, s *Server, c <-chan *Req) {
if !ok {
return
}
+ var (
+ wsfile WriterStatFile
+ wstat *Stat
+ newStat *Stat
+ fi fs.FileInfo
+ err error
+ )
ifcall := r.Ifcall.(*TWStat)
r.Fid, ok = s.fPool.lookup(ifcall.Fid)
if !ok {
r.err = ErrUnknownFid
- rc <- r
- continue
+ goto resp
}
if r.Fid.OMode == -1 {
var err error
r.Fid.File, err = s.fs.OpenFile(r.Fid.path, OREAD)
if err != nil {
r.err = fmt.Errorf("open: %v", err)
- rc <- r
- continue
+ goto resp
}
defer r.Fid.File.Close()
}
- wsfile, ok := r.Fid.File.(WriterStatFile)
+ wsfile, ok = r.Fid.File.(WriterStatFile)
if !ok {
r.err = ErrOperation
- rc <- r
- continue
+ goto resp
}
- wstat := ifcall.Stat
- fi, err := r.Fid.File.Stat()
+ wstat = ifcall.Stat
+ fi, err = r.Fid.File.Stat()
if err != nil {
r.err = fmt.Errorf("stat: %v", err)
- rc <- r
- continue
+ goto resp
}
- newStat := fi.Sys().(*Stat)
+ newStat = fi.Sys().(*Stat)
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 ||
@@ -1069,21 +980,18 @@ func sWStat(ctx context.Context, s *Server, c <-chan *Req) {
wstat.Uid != "" && wstat.Uid != newStat.Uid ||
wstat.Muid != "" && wstat.Muid != newStat.Muid {
r.err = fmt.Errorf("operation not permitted")
- rc <- r
- continue
+ goto resp
}
if wstat.Name != "" && newStat.Name != wstat.Name {
parentPath := path.Dir(r.Fid.path)
pstat, err := fs.Stat(ExportFS{s.fs}, parentPath)
if err != nil {
r.err = fmt.Errorf("stat parent: %v", err)
- rc <- r
- continue
+ goto resp
}
if !hasPerm(s.fs, pstat, r.Fid.Uid, AWRITE) {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
// TODO: I think 9P protocol prohibits renaming to existent file.
// Wstat(9P) in p9p says:
@@ -1091,27 +999,24 @@ func sWStat(ctx context.Context, s *Server, c <-chan *Req) {
// an existing file.
// but 9pfs, 9pfuse does the rename when used with `git init`.
/*
- children, err := fs.Glob(ExportFS{s.fs}, path.Join(parentPath, "*"))
- if err != nil {
- r.err = fmt.Errorf("glob children: %v", err)
- rc <- r
- continue
- }
- for _, f := range children {
- if path.Base(f) == wstat.Name {
- r.err = fmt.Errorf("file already exists")
- rc <- r
- continue
- }
+ children, err := fs.Glob(ExportFS{s.fs}, path.Join(parentPath, "*"))
+ if err != nil {
+ r.err = fmt.Errorf("glob children: %v", err)
+ goto resp
+ }
+ for _, f := range children {
+ if path.Base(f) == wstat.Name {
+ r.err = fmt.Errorf("file already exists")
+ goto resp
}
+ }
*/
newStat.Name = wstat.Name
}
if wstat.Length != ^int64(0) && wstat.Length != newStat.Length {
if fi.IsDir() || !hasPerm(s.fs, fi, r.Fid.Uid, AWRITE) {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
newStat.Length = wstat.Length
}
@@ -1119,13 +1024,11 @@ func sWStat(ctx context.Context, s *Server, c <-chan *Req) {
// the owner of the file or the group leader of the file's group.
if r.Fid.Uid != newStat.Uid && r.Fid.Uid != newStat.Gid {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
if wstat.Mode&fs.ModeDir != newStat.Mode&fs.ModeDir {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
newStat.Mode = wstat.Mode
}
@@ -1133,8 +1036,7 @@ func sWStat(ctx context.Context, s *Server, c <-chan *Req) {
// the owner of the file or the group leader of the file's group.
if r.Fid.Uid != newStat.Uid && r.Fid.Uid != newStat.Gid {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
newStat.Mtime = wstat.Mtime
}
@@ -1150,35 +1052,20 @@ func sWStat(ctx context.Context, s *Server, c <-chan *Req) {
newStat.Gid = wstat.Gid
} else {
r.err = ErrPerm
- rc <- r
- continue
+ goto resp
}
}
err = wsfile.WStat(newStat)
if err != nil {
r.err = fmt.Errorf("wstat: %v", err)
- rc <- r
- continue
+ goto resp
}
r.Ofcall = &RWStat{}
- rc <- r
- }
- }
-}
-
-func rWStat(ctx context.Context, c <-chan *Req) {
- for {
- select {
- case <-ctx.Done():
- return
- case r, ok := <-c:
- if !ok {
- return
- }
+ resp:
if r.err != nil {
setError(r, r.err)
}
- r.Srv.respChan <- r
+ s.respChan <- r
}
}
}