commit 5972869a67b1f2b564bc5a59fd84823bb03a41e2
parent 5b7c15103632e9d8c9e2fdd54fc9d678f05b9d6f
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sun, 17 Sep 2023 06:50:06 +0900
fix walk
Diffstat:
| M | server.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) {