lib9p

Go 9P library.
Log | Files | Refs

commit 5972869a67b1f2b564bc5a59fd84823bb03a41e2
parent 5b7c15103632e9d8c9e2fdd54fc9d678f05b9d6f
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sun, 17 Sep 2023 06:50:06 +0900

fix walk

Diffstat:
Mserver.go | 73++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 48 insertions(+), 25 deletions(-)

diff --git a/server.go b/server.go @@ -22,6 +22,8 @@ var ( ErrOperation = fmt.Errorf("operation not supported") ErrDupTag = fmt.Errorf("duplicate tag") ErrUnknownFid = fmt.Errorf("unknown fid") + ErrDupFid = fmt.Errorf("duplicate fid") + ErrNotFound = fmt.Errorf("not found") ) type Server struct { @@ -101,6 +103,8 @@ func sVersion(s *Server, r *Req) { } else { version = "9P2000" } + + // TODO: In plan9, s.mSize is changed in rversion(). msize := ifcall.MSize() if msize < s.mSize { s.mSize = msize @@ -108,13 +112,12 @@ func sVersion(s *Server, r *Req) { msize = s.mSize } - ofcall := &RVersion{ + r.ofcall = &RVersion{ tag: ifcall.Tag(), mSize: msize, version: version, } - r.ofcall = ofcall respond(r, nil) } @@ -130,11 +133,11 @@ func sAttach(s *Server, r *Req) { ifcall := r.ifcall.(*TAttach) fid, err := s.fPool.alloc(ifcall.Fid()) if err != nil { - respond(r, ErrUnknownFid) + respond(r, ErrDupFid) return } - f, err := s.fs.Open(".") // TODO: use aname? + f, err := s.fs.Open(".") // TODO: use aname? // TODO: open mode? if err != nil { log.Printf("open fs: %v", err) respond(r, fmt.Errorf("unable to open file tree")) @@ -143,7 +146,7 @@ func sAttach(s *Server, r *Req) { fid.File = f fid.Uid = ifcall.UName() - fid.OMode = OREAD // TODO: right? + fid.OMode = -1 // TODO: right? info, err := fid.File.Stat() if err != nil { @@ -180,55 +183,75 @@ func sWalk(s *Server, r *Req) { respond(r, ErrUnknownFid) return } - _, ok = s.fPool.lookup(ifcall.NewFid()) - if ok { - respond(r, fmt.Errorf("duplicate fid")) + if oldFid.OMode != -1 { + respond(r, fmt.Errorf("cannot clone open fid")) return } - newFid, err := s.fPool.alloc(ifcall.NewFid()) - if err != nil { - log.Printf("alloc: %v", err) - respond(r, fmt.Errorf("internal error")) + if ifcall.NWName() > 0 && oldFid.Qid.Type&QTDIR == 0 { + respond(r, fmt.Errorf("walk on non-dir")) return } + var newFid *Fid + if ifcall.Fid() == ifcall.NewFid() { + newFid = oldFid + } else { + var err error + newFid, err = s.fPool.alloc(ifcall.NewFid()) + if err != nil { + log.Printf("alloc: %v", err) + respond(r, fmt.Errorf("internal error")) + return + } + } + wqids := make([]Qid, ifcall.NWName()) cwd := oldFid.File + var n int for i, name := range ifcall.WName() { child, err := walkfile(cwd, name) if err != nil { - s.fPool.delete(ifcall.NewFid()) - respond(r, fmt.Errorf("walk: %v", err)) - return + break } stat, err := child.Stat() if err != nil { - s.fPool.delete(ifcall.NewFid()) - respond(r, fmt.Errorf("stat: %v", err)) - return + break } wqids[i] = stat.Qid() cwd = child + n++ + log.Printf("child, n: %s, %d", stat.Name(), n) } newFid.File = cwd newFid.Uid = oldFid.Uid - info, err := newFid.File.Stat() - if err != nil { - log.Printf("Stat %v, %v", newFid.File, err) - respond(r, fmt.Errorf("internal error")) - return + if n == 0 { + newFid.Qid = oldFid.Qid + } else { + newFid.Qid = wqids[n-1] } - newFid.Qid = info.Qid() r.ofcall = &RWalk{ tag: r.ifcall.Tag(), - qid: wqids, + qid: wqids[:n], } respond(r, nil) } func rWalk(r *Req, err error) { + ifcall := r.ifcall.(*TWalk) + ofcall := r.ofcall.(*RWalk) + if err != nil || len(ofcall.Qid()) < int(ifcall.NWName()) { + if ifcall.Fid() != ifcall.NewFid() { + r.srv.fPool.delete(ifcall.NewFid()) + } + if len(ofcall.Qid()) == 0 { + if err == nil && ifcall.NWName() != 0 { + rError(r, ErrNotFound) + return + } + } + } } func sOpen(s *Server, r *Req) {