func (fid *Fid) Stat() (*plan9.Dir, error) { checkSeq(nil, fid) tx := &plan9.Fcall{Type: plan9.Tstat, Fid: fid.fid} rx, err := fid.c.rpc(tx) if err != nil { return nil, err } return plan9.UnmarshalDir(rx.Stat) }
func (sq *seq9p) fcall2result(rxc <-chan *plan9.Fcall, resultc chan<- seq.Result) { defer func() { sq.replyEOF = true sq.putfids() close(resultc) sq.c.w.Unlock() }() for { rx := <-rxc sq.c.w.Lock() if rx == nil { sq.err = sq.c.getErr() return } rq := sq.q.Get() if rx.Type != rq.tx.Type+1 && rx.Type != plan9.Rerror { // TODO what do we do here panic(fmt.Sprintf("mismatched replies; sent %v; got %v", rq.tx, rx)) } var result seq.Result switch rx.Type { case plan9.Rbegin: case plan9.Rend: return case plan9.Rerror: switch op := rq.op.(type) { case seq.CloneReq: newfid := (*Fid)(op.F.(*file9p)) newfid.flags &^= fPending newfid.seq = nil sq.putfid(newfid) newfid.Close() } sq.err = errors.New(rx.Ename) return case plan9.Rwalk: switch len(rx.Wqid) { case 0: nfid := (*Fid)(rq.op.(seq.CloneReq).F.(*file9p)) nfid.qid = rq.fid.qid nfid.mode = rq.fid.mode nfid.flags |= fAlloc nfid.flags &^= fPending nfid.offset = rq.fid.offset result = seq.CloneResult{} case 1: rq.fid.qid = rx.Wqid[0] result = seq.WalkResult{rx.Wqid[0]} default: panic("unexpected Rwalk qid count") } case plan9.Ropen: rq.fid.mode = rq.op.(seq.OpenReq).Mode rq.fid.flags |= fOpen rq.fid.qid = rx.Qid result = seq.OpenResult{rx.Qid} case plan9.Rnonseq: sq.putfid(rq.fid) result = seq.NonseqResult{} case plan9.Rcreate: rq.fid.mode = rq.op.(seq.CreateReq).Mode rq.fid.flags |= fOpen rq.fid.qid = rx.Qid result = seq.CreateResult{rx.Qid} case plan9.Rwrite: result = seq.WriteResult{int(rx.Count)} // TODO: check overflow? case plan9.Rread: data := rq.op.(seq.ReadReq).Data copy(data, rx.Data) result = seq.ReadResult{len(rx.Data)} case plan9.Rstat: d, err := plan9.UnmarshalDir(rx.Stat) if err != nil { // TODO try to recover here panic("bad dir structure from server") } result = seq.StatResult{*d} case plan9.Rwstat: result = seq.WstatResult{} case plan9.Rremove: rq.fid.flags &^= fAlloc sq.putfid(rq.fid) rq.fid.Close() result = seq.RemoveResult{} case plan9.Rclunk: rq.fid.flags &^= fAlloc sq.putfid(rq.fid) rq.fid.Close() result = seq.ClunkResult{} default: // TODO ensure sanity checked before it gets here. panic(fmt.Sprintf("unexpected rmessage: %v", rx)) } //log.Printf("fcall2result %#v (rq %#v)\n", result, rq) sq.c.w.Unlock() if result != nil { resultc <- result } } }