func (*Ufs) Walk(req *srv.Req) { fid := req.Fid.Aux.(*Fid) tc := req.Tc err := fid.stat() if err != nil { req.RespondError(err) return } if req.Newfid.Aux == nil { req.Newfid.Aux = new(Fid) } nfid := req.Newfid.Aux.(*Fid) wqids := make([]p.Qid, len(tc.Wname)) path := fid.path i := 0 for ; i < len(tc.Wname); i++ { p := path + "/" + tc.Wname[i] st, err := os.Lstat(p) if err != nil { if i == 0 { req.RespondError(Enoent) return } break } wqids[i] = *dir2Qid(st) path = p } nfid.path = path req.RespondRwalk(wqids[0:i]) }
// BUG(mbucc) does not fully implement spec when fid = newfid. // From http://plan9.bell-labs.com/magic/man2html/5/walk: // If newfid is the same as fid, the above discussion applies, with the // obvious difference that if the walk changes the state of newfid, it // also changes the state of fid; and if newfid is unaffected, then fid // is also unaffected. // func (u *VuFs) Walk(req *srv.Req) { fid := req.Fid.Aux.(*Fid) tc := req.Tc _, err := os.Stat(fid.path) if err != nil { req.RespondError(toError(err)) return } if req.Newfid.Aux == nil { req.Newfid.Aux = new(Fid) } newfid := req.Newfid.Aux.(*Fid) wqids := make([]p.Qid, len(tc.Wname)) path := fid.path i := 0 // Ensure execute permission on the walk root. st, err := os.Stat(path) if err != nil { req.RespondError(srv.Enoent) return } f, err := dir2Dir(path, st, req.Conn.Srv.Upool) if err != nil { req.RespondError(toError(err)) return } if !CheckPerm(f, req.Fid.User, p.DMEXEC) { req.RespondError(srv.Eperm) return } for ; i < len(tc.Wname); i++ { var newpath string // Don't allow client to dotdot out of the file system root. if tc.Wname[i] == ".." { if path == u.Root { continue } else { newpath = path[:strings.LastIndex(path, "/")] if newpath == u.Root { continue } } } else { newpath = path + "/" + tc.Wname[i] } st, err := os.Stat(newpath) if err != nil { if i == 0 { req.RespondError(srv.Enoent) return } break } wqids[i] = *dir2Qid(st) if (wqids[i].Type & p.QTDIR) > 0 { f, err := dir2Dir(newpath, st, req.Conn.Srv.Upool) if err != nil { req.RespondError(toError(err)) return } if !CheckPerm(f, req.Fid.User, p.DMEXEC) { req.RespondError(srv.Eperm) return } } path = newpath } newfid.path = path req.RespondRwalk(wqids[0:i]) }