lib9p

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

commit b1dc634e18ea7d53f3aa47c15ce925a4464296c3
parent c2354fbcab452d3371d2679e272e721ae1bdc2a8
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat, 28 Oct 2023 07:17:53 +0900

export fields of Req

Diffstat:
Mreq.go | 20++++++++++----------
Mserver.go | 222++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mserver_test.go | 21++++++++++++---------
Dtest_fs.go | 197-------------------------------------------------------------------------------
4 files changed, 133 insertions(+), 327 deletions(-)

diff --git a/req.go b/req.go @@ -7,23 +7,23 @@ import ( // Req represents each requests. type Req struct { - tag uint16 - srv *Server - ifcall Msg - ofcall Msg - fid *Fid - afid *Fid - oldReq *Req + Tag uint16 + Srv *Server + Ifcall Msg + Ofcall Msg + Fid *Fid + Afid *Fid + Oldreq *Req pool *ReqPool - cancel context.CancelFunc + Cancel context.CancelFunc } // flush cancels the Req by calling r.cancel. func (r *Req) flush() { // TODO: need mutex? // BUG: cancel() can be nil. - r.cancel() - r.pool.delete(r.tag) + r.Cancel() + r.pool.delete(r.Tag) } // ReqPool is the pool of Reqs the server is dealing with. diff --git a/server.go b/server.go @@ -23,7 +23,7 @@ var ( ) func setError(r *Req, err error) { - r.ofcall = &RError{ + r.Ofcall = &RError{ Ename: err, } } @@ -137,7 +137,7 @@ func (s *Server) runSpeaker(w io.Writer) (chan<- *Req, <-chan error) { defer close(ec) for { r := <-rc - _, err := w.Write(r.ofcall.marshal()) + _, err := w.Write(r.Ofcall.marshal()) if err != nil { ec <- err } @@ -161,21 +161,21 @@ func getReq(r io.Reader, s *Server) (*Req, error) { if err != nil { // duplicate tag: cons up a fake Req req := new(Req) - req.srv = s - req.ifcall = ifcall + req.Srv = s + req.Ifcall = ifcall if s.chatty9P { - fmt.Fprintf(os.Stderr, "<-- %v\n", req.ifcall) + fmt.Fprintf(os.Stderr, "<-- %v\n", req.Ifcall) } return req, ErrDupTag } - req.srv = s - req.tag = ifcall.GetTag() - req.ifcall = ifcall - if ifcall, ok := req.ifcall.(*TFlush); ok { - req.oldReq, _ = req.srv.rPool.lookup(ifcall.Oldtag) + req.Srv = s + req.Tag = ifcall.GetTag() + req.Ifcall = ifcall + if ifcall, ok := req.Ifcall.(*TFlush); ok { + req.Oldreq, _ = req.Srv.rPool.lookup(ifcall.Oldtag) } if s.chatty9P { - fmt.Fprintf(os.Stderr, "<-- %v\n", req.ifcall) + fmt.Fprintf(os.Stderr, "<-- %v\n", req.Ifcall) } return req, nil } @@ -189,7 +189,7 @@ func getReq(r io.Reader, s *Server) (*Req, error) { // TODO: abort all outstanding I/O on the same connection before // serving new Tversion. func sVersion(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TVersion) + ifcall := r.Ifcall.(*TVersion) version := ifcall.Version if ok := strings.HasPrefix(version, "9P2000"); !ok { version = "unknown" @@ -200,7 +200,7 @@ func sVersion(ctx context.Context, s *Server, r *Req) { if msize > s.mSize() { msize = s.mSize() } - r.ofcall = &RVersion{ + r.Ofcall = &RVersion{ Msize: msize, Version: version, } @@ -213,14 +213,14 @@ func rVersion(r *Req, err error) { if err != nil { panic(fmt.Errorf("rVersion err: %w", err)) } - r.srv.setMSize(r.ofcall.(*RVersion).Msize) + r.Srv.setMSize(r.Ofcall.(*RVersion).Msize) } // sAuth serves Tauth message. func sAuth(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TAuth) + ifcall := r.Ifcall.(*TAuth) var err error - r.afid, err = s.fPool.add(ifcall.Afid) + r.Afid, err = s.fPool.add(ifcall.Afid) if err != nil { respond(ctx, r, ErrDupFid) } @@ -236,13 +236,13 @@ func sAuth(ctx context.Context, s *Server, r *Req) { // allocated fid from fPool. func rAuth(r *Req, err error) { if err != nil { - r.srv.fPool.delete(r.ifcall.(*TAuth).Afid) + r.Srv.fPool.delete(r.Ifcall.(*TAuth).Afid) setError(r, err) } } func sAttach(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TAttach) + ifcall := r.Ifcall.(*TAttach) fid, err := s.fPool.add(ifcall.Fid) if err != nil { respond(ctx, r, ErrDupFid) @@ -284,7 +284,7 @@ func sAttach(ctx context.Context, s *Server, r *Req) { respond(ctx, r, fmt.Errorf("stat root: %v", err)) return } - r.ofcall = &RAttach{ + r.Ofcall = &RAttach{ Qid: st.Sys().(*Stat).Qid, } respond(ctx, r, nil) @@ -292,7 +292,7 @@ func sAttach(ctx context.Context, s *Server, r *Req) { func rAttach(r *Req, err error) { if err != nil { - r.srv.fPool.delete(r.ifcall.(*TAttach).Fid) + r.Srv.fPool.delete(r.Ifcall.(*TAttach).Fid) setError(r, err) } } @@ -305,14 +305,14 @@ func rFlush(r *Req, err error) { if err != nil { panic(fmt.Errorf("err in flush: %v", err)) } - if r.oldReq != nil { - r.oldReq.flush() + if r.Oldreq != nil { + r.Oldreq.flush() } - r.ofcall = &RFlush{} + r.Ofcall = &RFlush{} } func sWalk(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TWalk) + ifcall := r.Ifcall.(*TWalk) oldFid, ok := s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) @@ -366,18 +366,18 @@ func sWalk(ctx context.Context, s *Server, r *Req) { newFid.File = cwdf newFid.Uid = oldFid.Uid newFid.path = cwdp - r.ofcall = &RWalk{ + r.Ofcall = &RWalk{ Qids: wqids[:n], } respond(ctx, r, nil) } func rWalk(r *Req, err error) { - ifcall := r.ifcall.(*TWalk) - ofcall := r.ofcall.(*RWalk) + ifcall := r.Ifcall.(*TWalk) + ofcall := r.Ofcall.(*RWalk) if err != nil || len(ofcall.Qids) < len(ifcall.Wnames) { if ifcall.Fid != ifcall.Newfid { - r.srv.fPool.delete(ifcall.Newfid) + r.Srv.fPool.delete(ifcall.Newfid) } if len(ofcall.Qids) == 0 { if err == nil && len(ifcall.Wnames) != 0 { @@ -389,14 +389,14 @@ func rWalk(r *Req, err error) { } func sOpen(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TOpen) + ifcall := r.Ifcall.(*TOpen) var ok bool - r.fid, ok = s.fPool.lookup(ifcall.Fid) + r.Fid, ok = s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return } - if r.fid.OMode != -1 { + if r.Fid.OMode != -1 { respond(ctx, r, ErrBotch) return } @@ -404,7 +404,7 @@ func sOpen(ctx context.Context, s *Server, r *Req) { // See open(5). // In plan9 implementation, ifcall.Mode() is ANDed with ^ORCLOSE, // but ORCLOSE is also prohibitted by the protocol... - st, err := r.fid.File.Stat() + st, err := r.Fid.File.Stat() if err != nil { respond(ctx, r, fmt.Errorf("stat: %v", err)) return @@ -434,24 +434,24 @@ func sOpen(ctx context.Context, s *Server, r *Req) { respond(ctx, r, ErrPerm) return } - if !hasPerm(r.fid.File, r.fid.Uid, p) { + if !hasPerm(r.Fid.File, r.Fid.Uid, p) { respond(ctx, r, ErrPerm) return } if ifcall.Mode&ORCLOSE != 0 { - parentPath := path.Dir(r.fid.path) + parentPath := path.Dir(r.Fid.path) parent, err := s.fs.OpenFile(parentPath, OREAD, 0) defer parent.Close() if err != nil { respond(ctx, r, fmt.Errorf("open parent")) return } - if !hasPerm(parent, r.fid.Uid, AWRITE) { + if !hasPerm(parent, r.Fid.Uid, AWRITE) { respond(ctx, r, ErrPerm) return } } - r.ofcall = &ROpen{ + r.Ofcall = &ROpen{ Qid: qid, Iounit: s.mSize() - IOHDRSZ, } @@ -463,24 +463,24 @@ func rOpen(r *Req, err error) { setError(r, err) return } - r.fid.OMode = r.ifcall.(*TOpen).Mode - f, err := r.srv.fs.OpenFile(r.fid.path, r.fid.OMode, 0) + r.Fid.OMode = r.Ifcall.(*TOpen).Mode + f, err := r.Srv.fs.OpenFile(r.Fid.path, r.Fid.OMode, 0) if err != nil { setError(r, err) return } - r.fid.File = f + r.Fid.File = f } func sCreate(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TCreate) + ifcall := r.Ifcall.(*TCreate) var ok bool - r.fid, ok = s.fPool.lookup(ifcall.Fid) + r.Fid, ok = s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return } - dir := r.fid.File + dir := r.Fid.File dirstat, err := dir.Stat() if err != nil { respond(ctx, r, fmt.Errorf("stat: %v", err)) @@ -490,11 +490,11 @@ func sCreate(ctx context.Context, s *Server, r *Req) { respond(ctx, r, fmt.Errorf("create in non-dir")) return } - if !hasPerm(dir, r.fid.Uid, AWRITE) { + if !hasPerm(dir, r.Fid.Uid, AWRITE) { respond(ctx, r, ErrPerm) return } - cfdir, ok := r.fid.File.(CreaterFile) + cfdir, ok := r.Fid.File.(CreaterFile) if !ok { respond(ctx, r, ErrOperation) return @@ -506,23 +506,23 @@ func sCreate(ctx context.Context, s *Server, r *Req) { } else { perm &= ^FileMode(0777) | (dirperm & FileMode(0777)) } - file, err := cfdir.Create(ifcall.Name, r.fid.Uid, ifcall.Mode, perm) + file, err := cfdir.Create(ifcall.Name, r.Fid.Uid, ifcall.Mode, perm) if err != nil { respond(ctx, r, fmt.Errorf("create: %v", err)) return } - if err := r.fid.File.Close(); err != nil { + if err := r.Fid.File.Close(); err != nil { respond(ctx, r, fmt.Errorf("close: %v", err)) return } - r.fid.File = file - r.fid.path = path.Join(r.fid.path, ifcall.Name) - st, err := r.fid.File.Stat() + r.Fid.File = file + r.Fid.path = path.Join(r.Fid.path, ifcall.Name) + st, err := r.Fid.File.Stat() if err != nil { respond(ctx, r, fmt.Errorf("stat: %v", err)) return } - r.ofcall = &RCreate{ + r.Ofcall = &RCreate{ Qid: st.Sys().(*Stat).Qid, Iounit: s.mSize() - IOHDRSZ, } @@ -533,29 +533,29 @@ func rCreate(r *Req, err error) { setError(r, err) return } - r.fid.OMode = r.ifcall.(*TCreate).Mode + r.Fid.OMode = r.Ifcall.(*TCreate).Mode // TODO: pass OCREATE with non 0 perm. - f, err := r.srv.fs.OpenFile(r.fid.path, r.fid.OMode, 0) + f, err := r.Srv.fs.OpenFile(r.Fid.path, r.Fid.OMode, 0) if err != nil { setError(r, err) return } - r.fid.File = f + r.Fid.File = f } func sRead(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TRead) + ifcall := r.Ifcall.(*TRead) var ok bool - r.fid, ok = s.fPool.lookup(ifcall.Fid) + r.Fid, ok = s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return } - if r.fid.OMode == -1 { + if r.Fid.OMode == -1 { respond(ctx, r, fmt.Errorf("not open")) return } - if r.fid.OMode != OREAD && r.fid.OMode != ORDWR && r.fid.OMode != OEXEC { + if r.Fid.OMode != OREAD && r.Fid.OMode != ORDWR && r.Fid.OMode != OEXEC { respond(ctx, r, ErrPerm) return } @@ -566,7 +566,7 @@ func sRead(ctx context.Context, s *Server, r *Req) { err error wg sync.WaitGroup ) - fi, err := r.fid.File.Stat() + fi, err := r.Fid.File.Stat() if err != nil { log.Printf("Stat: %v", err) respond(ctx, r, fmt.Errorf("internal error")) @@ -580,20 +580,20 @@ func sRead(ctx context.Context, s *Server, r *Req) { }() defer wg.Done() if fi.IsDir() { - children, err := getChildren(s.fs, r.fid.path) + children, err := getChildren(s.fs, r.Fid.path) if err != nil { log.Printf("get children: %v", err) } - if ifcall.Offset != 0 && ifcall.Offset != r.fid.dirOffset { + if ifcall.Offset != 0 && ifcall.Offset != r.Fid.dirOffset { respond(ctx, r, fmt.Errorf("invalid dir offset")) return } if ifcall.Offset == 0 { - r.fid.dirIndex = 0 - r.fid.dirOffset = 0 + r.Fid.dirIndex = 0 + r.Fid.dirOffset = 0 } - k := r.fid.dirIndex + k := r.Fid.dirIndex for ; k < len(children); k++ { if children[k] == nil { continue @@ -613,13 +613,13 @@ func sRead(ctx context.Context, s *Server, r *Req) { } n += len(buf) } - r.fid.dirOffset += uint64(n) - r.fid.dirIndex = k + r.Fid.dirOffset += uint64(n) + r.Fid.dirIndex = k } else { - if reader, ok := r.fid.File.(io.ReaderAt); ok { + if reader, ok := r.Fid.File.(io.ReaderAt); ok { n, err = reader.ReadAt(data, int64(ifcall.Offset)) } else { - n, err = r.fid.File.Read(data) + n, err = r.Fid.File.Read(data) } if err != io.EOF && err != nil { log.Printf("sRead: %v\n", err) @@ -632,7 +632,7 @@ func sRead(ctx context.Context, s *Server, r *Req) { case <-done: case <-ctx.Done(): } - r.ofcall = &RRead{ + r.Ofcall = &RRead{ Count: uint32(n), Data: data[:n], } @@ -645,9 +645,9 @@ func rRead(r *Req, err error) { } func sWrite(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TWrite) + ifcall := r.Ifcall.(*TWrite) var ok bool - r.fid, ok = s.fPool.lookup(ifcall.Fid) + r.Fid, ok = s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return @@ -655,13 +655,13 @@ func sWrite(ctx context.Context, s *Server, r *Req) { if ifcall.Count > s.mSize()-IOHDRSZ { ifcall.Count = s.mSize() - IOHDRSZ } - if !hasPerm(r.fid.File, r.fid.Uid, AWRITE) { + if !hasPerm(r.Fid.File, r.Fid.Uid, AWRITE) { respond(ctx, r, ErrPerm) return } - omode := r.fid.OMode & 3 + omode := r.Fid.OMode & 3 if omode != OWRITE && omode != ORDWR { - respond(ctx, r, fmt.Errorf("write on fid with open mode 0x%x", r.fid.OMode)) + respond(ctx, r, fmt.Errorf("write on fid with open mode 0x%x", r.Fid.OMode)) return } ofcall := new(RWrite) @@ -673,7 +673,7 @@ func sWrite(ctx context.Context, s *Server, r *Req) { wg.Wait() close(done) }() - switch file := r.fid.File.(type) { + switch file := r.Fid.File.(type) { case io.WriterAt: n, err := file.WriteAt(ifcall.Data, int64(ifcall.Offset)) if err != nil { @@ -698,7 +698,7 @@ func sWrite(ctx context.Context, s *Server, r *Req) { case <-done: case <-ctx.Done(): } - r.ofcall = ofcall + r.Ofcall = ofcall respond(ctx, r, nil) } @@ -711,14 +711,14 @@ func rWrite(r *Req, err error) { } func sClunk(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TClunk) + ifcall := r.Ifcall.(*TClunk) _, ok := s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return } s.fPool.delete(ifcall.Fid) - r.ofcall = &RClunk{} + r.Ofcall = &RClunk{} respond(ctx, r, nil) } @@ -729,26 +729,26 @@ func rClunk(r *Req, err error) { } func sRemove(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TRemove) + ifcall := r.Ifcall.(*TRemove) var ok bool - r.fid, ok = s.fPool.lookup(ifcall.Fid) + r.Fid, ok = s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return } defer s.fPool.delete(ifcall.Fid) - parentPath := path.Dir(r.fid.path) + parentPath := path.Dir(r.Fid.path) parent, err := s.fs.OpenFile(parentPath, OREAD, 0) if err != nil { respond(ctx, r, fmt.Errorf("open parent: %v", err)) return } defer parent.Close() - if !hasPerm(parent, r.fid.Uid, AWRITE) { + if !hasPerm(parent, r.Fid.Uid, AWRITE) { respond(ctx, r, ErrPerm) return } - rfile, ok := r.fid.File.(RemoverFile) + rfile, ok := r.Fid.File.(RemoverFile) if !ok { respond(ctx, r, ErrOperation) return @@ -757,7 +757,7 @@ func sRemove(ctx context.Context, s *Server, r *Req) { respond(ctx, r, fmt.Errorf("remove: %v", err)) return } - r.ofcall = &RRemove{} + r.Ofcall = &RRemove{} respond(ctx, r, nil) } func rRemove(r *Req, err error) { @@ -767,20 +767,20 @@ func rRemove(r *Req, err error) { } func sStat(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TStat) + ifcall := r.Ifcall.(*TStat) var ok bool - r.fid, ok = s.fPool.lookup(ifcall.Fid) + r.Fid, ok = s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return } - fileInfo, err := r.fid.File.Stat() + fileInfo, err := r.Fid.File.Stat() if err != nil { - log.Printf("stat %v: %v", r.fid.File, err) + log.Printf("stat %v: %v", r.Fid.File, err) respond(ctx, r, fmt.Errorf("internal error")) return } - r.ofcall = &RStat{ + r.Ofcall = &RStat{ Stat: fileInfo.Sys().(*Stat), } respond(ctx, r, nil) @@ -793,20 +793,20 @@ func rStat(r *Req, err error) { } func sWStat(ctx context.Context, s *Server, r *Req) { - ifcall := r.ifcall.(*TWStat) + ifcall := r.Ifcall.(*TWStat) var ok bool - r.fid, ok = s.fPool.lookup(ifcall.Fid) + r.Fid, ok = s.fPool.lookup(ifcall.Fid) if !ok { respond(ctx, r, ErrUnknownFid) return } - wsfile, ok := r.fid.File.(WriterStatFile) + wsfile, ok := r.Fid.File.(WriterStatFile) if !ok { respond(ctx, r, ErrOperation) return } wstat := ifcall.Stat - fi, err := r.fid.File.Stat() + fi, err := r.Fid.File.Stat() if err != nil { respond(ctx, r, fmt.Errorf("stat: %v", err)) return @@ -820,13 +820,13 @@ func sWStat(ctx context.Context, s *Server, r *Req) { return } if wstat.Name != "" { - parentPath := path.Dir(r.fid.path) + parentPath := path.Dir(r.Fid.path) parent, err := s.fs.OpenFile(parentPath, OREAD, 0) if err != nil { respond(ctx, r, fmt.Errorf("get parent: %v", err)) return } - if !hasPerm(parent, r.fid.Uid, AWRITE) { + if !hasPerm(parent, r.Fid.Uid, AWRITE) { respond(ctx, r, ErrPerm) return } @@ -849,7 +849,7 @@ func sWStat(ctx context.Context, s *Server, r *Req) { newStat.Name = wstat.Name } if wstat.Length != ^int64(0) { - if fi.IsDir() || !hasPerm(r.fid.File, r.fid.Uid, AWRITE) { + if fi.IsDir() || !hasPerm(r.Fid.File, r.Fid.Uid, AWRITE) { respond(ctx, r, ErrPerm) return } @@ -857,7 +857,7 @@ func sWStat(ctx context.Context, s *Server, r *Req) { } if wstat.Mode != FileMode(^uint32(0)) { // 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 { + if r.Fid.Uid != newStat.Uid && r.Fid.Uid != newStat.Gid { respond(ctx, r, ErrPerm) return } @@ -869,7 +869,7 @@ func sWStat(ctx context.Context, s *Server, r *Req) { } if wstat.Mtime != ^uint32(0) { // 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 { + if r.Fid.Uid != newStat.Uid && r.Fid.Uid != newStat.Gid { respond(ctx, r, ErrPerm) return } @@ -885,7 +885,7 @@ func sWStat(ctx context.Context, s *Server, r *Req) { respond(ctx, r, fmt.Errorf("wstat: %v", err)) return } - r.ofcall = &RWStat{} + r.Ofcall = &RWStat{} respond(ctx, r, nil) } @@ -912,11 +912,11 @@ L: continue L case r := <-s.listenChan: ctx1, cancel := context.WithCancel(ctx) - r.cancel = cancel + r.Cancel = cancel go func() { - switch r.ifcall.(type) { + switch r.Ifcall.(type) { default: - respond(ctx1, r, fmt.Errorf("unknown message type: %d", r.ifcall.Type())) + respond(ctx1, r, fmt.Errorf("unknown message type: %d", r.Ifcall.Type())) case *TVersion: sVersion(ctx1, s, r) case *TAuth: @@ -952,13 +952,13 @@ L: } } -// Respond responds to the request r with the message r.ofcall if err is nil, +// Respond responds to the request r with the message r.Ofcall if err is nil, // or if err is not nil, with the Rerror with the error message. -// If r is nil, or both r.ofcall and err are nil it panics. +// If r is nil, or both r.Ofcall and err are nil it panics. func respond(ctx context.Context, r *Req, err error) { - switch r.ifcall.(type) { + switch r.Ifcall.(type) { default: - panic(fmt.Errorf("bug: r.ifcall: %v", r.ifcall)) + panic(fmt.Errorf("bug: r.Ifcall: %v", r.Ifcall)) case *TVersion: rVersion(r, err) case *TAuth: @@ -986,20 +986,20 @@ func respond(ctx context.Context, r *Req, err error) { case *TWStat: rWStat(r, err) } - r.ofcall.SetTag(r.tag) + r.Ofcall.SetTag(r.Tag) // free tag. if r.pool == nil && err != ErrDupTag { panic("ReqPool is nil but err is not EDupTag") } if r.pool != nil { - r.pool.delete(r.tag) + r.pool.delete(r.Tag) } select { - case r.srv.speakChan <- r: - if r.srv.chatty9P { - fmt.Fprintf(os.Stderr, "--> %s\n", r.ofcall) + case r.Srv.speakChan <- r: + if r.Srv.chatty9P { + fmt.Fprintf(os.Stderr, "--> %s\n", r.Ofcall) } case <-ctx.Done(): - log.Printf("req flush: %v", r.ifcall) + log.Printf("req flush: %v", r.Ifcall) } } diff --git a/server_test.go b/server_test.go @@ -1,4 +1,4 @@ -package lib9p +package lib9p_test import ( "context" @@ -6,12 +6,15 @@ import ( "io" "path/filepath" "testing" + + "git.mtkn.jp/lib9p" + "git.mtkn.jp/lib9p/testfs" ) -func newReq(s *Server, msg Msg) (*Req, error) { - r, err := s.rPool.add(msg.GetTag()) +func newReq(s *lib9p.Server, msg lib9p.Msg) (*lib9p.Req, error) { + r, err := s.RPool().Add(msg.GetTag()) if err != nil { - return nil, fmt.Errorf("ReqPool.add(%d): %w", msg.GetTag(), err) + return nil, fmt.Errorf("lib9p.ReqPool.add(%d): %w", msg.GetTag(), err) } r.srv = s r.tag = msg.GetTag() @@ -19,7 +22,7 @@ func newReq(s *Server, msg Msg) (*Req, error) { return r, nil } -func handleReq(ctx context.Context, s *Server, r *Req) { +func handleReq(ctx context.Context, s *lib9p.Server, r *lib9p.Req) { switch r.ifcall.(type) { default: respond(ctx, r, fmt.Errorf("unknown message type: %d", r.ifcall.Type())) @@ -51,7 +54,7 @@ func handleReq(ctx context.Context, s *Server, r *Req) { } // This function does the actual work for TestWalk(). -func testWalk(t *testing.T, fs *TestFS, path string, file *TestFile) { +func testWalk(t *testing.T, fs *testfs.TestFS, path string, file *testfs.TestFile) { t.Logf("walk %s", path) f, err := fs.walk(split9path(path)) if err != nil { @@ -80,7 +83,7 @@ func TestServer(t *testing.T) { cr, sw := io.Pipe() defer cr.Close() defer sw.Close() - msg := []Msg{ + msg := []lib9p.Msg{ &TVersion{ Tag: NOTAG, Msize: 1024, @@ -163,9 +166,9 @@ func TestServer(t *testing.T) { if err != nil { t.Fatalf("read: %v", err) } - t.Logf("--> %v\n", bufMsg(buf)) + t.Logf("--> %v\n", buflib9p.Msg(buf)) - if bufMsg(buf).Type() == Rread { + if buflib9p.Msg(buf).Type() == Rread { rread := newRRead(buf) data := rread.Data fid, ok := s.fPool.lookup(m.(*TRead).Fid) diff --git a/test_fs.go b/test_fs.go @@ -1,197 +0,0 @@ -package lib9p - -import ( - "bytes" - "fmt" - "io/fs" - "path" - "strings" - "time" -) - -const sleepTime = 1 * time.Second - -type TestFile struct { - Fsys *TestFS - Parent *TestFile - Children []*TestFile - Content []byte - Reader *bytes.Reader - - St Stat -} - -func (f *TestFile) Stat() (*FileInfo, error) { - return &FileInfo{Stat: f.St}, nil -} -func (f *TestFile) Close() error { - f.Reader = nil - return nil -} - -func (f *TestFile) Read(b []byte) (int, error) { - if f.Fsys.Slow { - time.Sleep(sleepTime) - } - return f.Reader.Read(b) -} - -func (f *TestFile) ReadAt(b []byte, off int64) (n int, err error) { - if f.Fsys.Slow { - time.Sleep(sleepTime) - } - return f.Reader.ReadAt(b, off) -} - -func (f *TestFile) ReadDir(n int) ([]*DirEntry, error) { - de := make([]*DirEntry, len(f.Children)) - for i, c := range f.Children { - de[i], _ = c.Stat() - } - return de, nil -} - -func (f *TestFile) WriteAt(p []byte, off int64) (int, error) { - if f.Fsys.Slow { - time.Sleep(sleepTime) - } - if f.Reader == nil { - return 0, fmt.Errorf("not open") - } - if off < 0 || off > int64(len(f.Content)) { - return 0, fmt.Errorf("bad offset") - } - - if off+int64(len(p)) > int64(len(f.Content)) { - newcon := make([]byte, off+int64(len(p))) - copy(newcon, f.Content) - f.Content = newcon - } - copy(f.Content[off:], p) - f.Reader.Reset(f.Content) - return len(p), nil -} - -type TestFS struct { - Root *TestFile - Slow bool -} - -func (fs *TestFS) OpenFile(path string, omode OpenMode, perm fs.FileMode) (File, error) { - path = clean9path(path) - wnames := split9path(path) - f, err := fs.walk(wnames) - if err != nil { - return nil, fmt.Errorf("walk: %v", err) - } - f.Reader = bytes.NewReader(f.Content) - return f, nil -} - -func (fs *TestFS) walk(wnames []string) (*TestFile, error) { - cwd := fs.Root -L: - for i, name := range wnames { - for _, child := range cwd.Children { - if child.St.Name == name { - cwd = child - continue L - } - } - return nil, fmt.Errorf("%s not found", strings.Join(wnames[:i+1], "/")) - } - return cwd, nil -} - -func clean9path(name string) string { - // TODO: eliminate leading ".." - name = path.Clean(name) - return name -} - -func split9path(path string) []string { - if path == "." || path == "/" { - return []string{} - } - return strings.Split(path, "/") -} - -var fsys *TestFS - -func init() { - fsys = &TestFS{ - Root: &TestFile{ - St: Stat{ - Qid: Qid{Path: 0, Type: QTDIR}, - Mode: FileMode(fs.ModeDir | 0755), - Name: "root", - Uid: "glenda", - Gid: "glenda", - Muid: "glenda", - }, - Children: []*TestFile{ - &TestFile{ - Content: []byte("a\n"), - St: Stat{ - Qid: Qid{Path: 1, Type: QTFILE}, - Mode: FileMode(0644), - Name: "a", - Uid: "glenda", - Gid: "glenda", - Muid: "glenda", - }, - }, - &TestFile{ - Content: []byte("b\n"), - St: Stat{ - Qid: Qid{Path: 2, Type: QTFILE}, - Mode: FileMode(0400), - Name: "b", - Uid: "ken", - Gid: "ken", - Muid: "ken", - }, - }, - &TestFile{ - St: Stat{ - Qid: Qid{Path: 3, Type: QTDIR}, - Mode: FileMode(fs.ModeDir | 0755), - Name: "dir", - Uid: "rob", - Gid: "rob", - Muid: "rob", - }, - Children: []*TestFile{ - &TestFile{ - Content: []byte("unko\n"), - St: Stat{ - Qid: Qid{Path: 4, Type: QTFILE}, - Mode: FileMode(0666), - Name: "file", - Uid: "brian", - Gid: "brian", - Muid: "dennis", - }, - }, - }, - }, - }, - }, - } - SetFsysAndParent(fsys, nil) -} - -// SetFsysAndParent sets file.fsys and file.parent for every file in the fsys. -// Pass nil as file to setup entire file system. -func SetFsysAndParent(fsys *TestFS, file *TestFile) { - if file == nil { - file = fsys.Root - file.Parent = fsys.Root - file.Fsys = fsys - } - for _, child := range file.Children { - child.Parent = file - child.Fsys = fsys - SetFsysAndParent(fsys, child) - } -}