func (s *Session) handleTwalk(cx context.Context, msg styxproto.Twalk, file file) bool { newfid := msg.Newfid() // Cannot use "opened" (ready for IO) fids for walking; see walk(5) // in 9P manual. However, 9pfuse does this, so we'll allow it. //if file.rwc != nil { // s.conn.Rerror(msg.Tag(), "walk on opened fid") // s.conn.Flush() // return true //} // newfid must be unused or equal to fid if newfid != msg.Fid() { if _, ok := s.conn.sessionFid.Get(newfid); ok { s.conn.clearTag(msg.Tag()) s.conn.Rerror(msg.Tag(), "Twalk: fid %x already in use", newfid) s.conn.Flush() return true } } // NOTE(droyo) The clone usage of Twalk is hidden from the user // of the styx package; we assume that all clients who have procured // a fid for a file are permitted to clone that fid, and may do so without // side effects. if msg.Nwname() == 0 { if newfid != msg.Fid() { s.files.Put(newfid, file) s.conn.sessionFid.Put(newfid, s) s.IncRef() } s.conn.clearTag(msg.Tag()) s.conn.Rwalk(msg.Tag()) s.conn.Flush() return true } // see walk.go for more details elem := make([]string, 0, msg.Nwname()) for i := 0; i < cap(elem); i++ { elem = append(elem, string(msg.Wname(i))) } walker := newWalker(s, cx, msg, file.name, elem...) for i := range elem { fullpath := path.Join(file.name, strings.Join(elem[:i+1], "/")) s.requests <- Twalk{ index: i, walk: walker, reqInfo: newReqInfo(cx, s, msg, fullpath), } } return true }