Пример #1
0
func (c *ClientConn) walk(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rwalk
	fref, has := c.fidRef(fc.Fid)
	if !has {
		return c.invalidFidErr(fc)
	}
	if _, has := c.fidRef(fc.Newfid); has {
		return c.fidUsedErr(fc)
	}
	current := fref.Path
	for idx, name := range fc.Wname {
		var ft FileType
		if current == 0 {
			return c.fileNotFoundErr(fc)
		}
		if ff, ok := c.explorer.(FileFinder); ok {
			f, err := ff.FindInDir(current, name)
			if err != nil {
				return c.unexpectedErr(fc, err)
			}
			current = f.Path
		} else {
			childs, err := c.explorer.ListDir(current)
			if err != nil {
				return c.unexpectedErr(fc, err)
			}
			idx, have := childs.FindExact(name)
			if !have {
				return c.fileNotFoundErr(fc)
			}
			current = childs[idx].Path
		}
		ref, err := c.createFileRef(current, ft, 0)
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		fc.Wqid = append(fc.Wqid, ref.Qid)

		// if the last match isn't a directory, there is no need to find
		// another part of the path
		//
		// so, just break here
		if ft == FTFILE && idx != len(fc.Wname)-1 {
			return c.fileNotFoundErr(fc)
		}
	}
	if len(fc.Wqid) == 0 {
		// newfid and fid will map to the same file
		if fc.Newfid != fc.Fid {
			c.bindFid(fc.Newfid, fref.Path)
		}
	} else {
		// make a bind between the last qid and the new fid
		c.bindFid(fc.Newfid, fc.Wqid[len(fc.Wqid)-1].Path)
	}
	return fc
}