Example #1
0
// d is a dup and can be changed.
func (f *mFile) find(d zx.Dir, p *pred.Pred, spref, dpref string, lvl int, c chan<- zx.Dir, ai *auth.Info) {
	match, pruned, err := p.EvalAt(d, lvl)
	f.dprintf("find  at %d %s\n\t%v\n\t%v %v %v\n\n",
		lvl, d.Long(), p, match, pruned, err)
	if pruned {
		if !match {
			d["err"] = "pruned"
		}
		c <- d
		return
	}
	if d["type"] == "d" && err == nil {
		f.mlk.Lock()
		if !f.t.NoPermCheck && !f.d.CanWalk(ai) {
			err = dbg.ErrPerm
		}
		f.mlk.Unlock()
	}
	if err != nil {
		d["err"] = err.Error()
		c <-d
		return
	}
	if d["rm"] != "" {
		return
	}
	if match {
		if ok := c <- d; !ok {
			return
		}
	}
	if d["type"] != "d" {
		return
	}
	f.clk.Lock()
	child := make([]*mFile, len(f.child))
	copy(child, f.child)
	f.clk.Unlock()
	if f.name == "/" {
		nc := []*mFile{
			&mFile{name: "Ctl", d: ctldir.Dup(), t: f.t},
		}
		nc[0].d["tpath"] = f.t.path
		child = append(nc, child...)
	}
	for _, cf := range child {
		cf.mlk.Lock()
		cd := cf.d.Dup()
		cf.mlk.Unlock()
		// fmt.Printf("child %s\n", cd)
		if cd["rm"] != "" {
			continue
		}
		if spref != dpref {
			cpath := cd["path"]
			suff := zx.Suffix(cpath, spref)
			cd["path"] = zx.Path(dpref, suff)
		}
		cf.find(cd, p, spref, dpref, lvl+1, c, ai)
	}
}

func (t *Fs) Find(rid, fpred, spref, dpref string, depth int) <-chan zx.Dir {
	t.dprintf("find %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	cs := t.IOstats.NewCall(zx.Sfind)
	dc := make(chan zx.Dir)
	go func() {
		rid, err := zx.AbsPath(rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		f, _, err := t.walk(rid, nil)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		p, err := pred.New(fpred)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		cs.Sending()
		f.mlk.Lock()
		d := f.d.Dup()
		f.mlk.Unlock()
		if spref != dpref {
			suff := zx.Suffix(rid, spref)
			d["path"] = zx.Path(dpref, suff)
		}
		f.find(d, p, spref, dpref, depth, dc, t.ai)
		cs.End(err != nil)
		t.dprintf("find %s: ok\n", rid)
		close(dc)
	}()
	return dc
}

func (t *Fs) FindGet(rid, fpred, spref, dpref string, depth int) <-chan zx.DirData {
	t.dprintf("findget %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	gc := make(chan zx.DirData)
	cs := t.IOstats.NewCall(zx.Sfindget)
	go func() {
		dc := t.Find(rid, fpred, spref, dpref, depth) // BUG: will stat a Sfind
		for d := range dc {
			g := zx.DirData{Dir: d}
			var datac chan []byte
			if d["err"]=="" && d["type"]=="-" {
				datac = make(chan []byte)
				g.Datac = datac
			}
			if ok := gc <- g; !ok {
				close(dc, cerror(gc))
				break
			}
			if datac != nil {
				err := t.get(d["spath"], 0, zx.All, datac, nil)
				close(datac, err)
			}
		}
		err := cerror(dc)
		cs.End(err != nil)
		if err != nil {
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(gc, err)
	}()
	return gc
}

func (t *Fs) Dump(w io.Writer) {
	if t == nil {
		fmt.Fprintf(w, "<nil tree>\n")
		return
	}
	fmt.Fprintf(w, "tree [%s] path %s\n", t.name, t.path)
	t.root.Dump(w, 0)
	fmt.Fprintf(w, "\n")
}

func (f *mFile) Dump(w io.Writer, lvl int) {
	tabs := strings.Repeat("    ", lvl)
	if f == nil {
		fmt.Fprintf(w, "%s<nil file>\n", tabs)
		return
	}
	d := f.d.Dup()
	if d["path"] == "/" {
		d["size"] = "0"
	}
	fmt.Fprintf(w, "%s%s\n", tabs, d.TestFmt())
	if d["type"] != "d"  {
		fmt.Fprintf(w, "%s  %d bytes\n", tabs, f.data.Len())
		return
	}
	for _, c := range f.child {
		c.Dump(w, lvl+1)
	}
	
}
Example #2
0
func (t *Rfs) getrpc(rid string, msg *Msg) <-chan []byte {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan []byte, 10)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sget, len(raw))
		reqc <- raw
		close(reqc)
		some := false
		for rep := range repc {
			cs.Send(int64(len(rep)))
			if ok := c <- rep; !ok {
				close(repc, cerror(c))
				break
			}
			some = true
			t.dprintf("get %s: ok\n", rid)
		}
		if !some {
			c <- nil
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("get %s: %s\n", rid, err)
		} else {
			t.dprintf("get %s: ok\n", rid)
		}
		close(c, err)
	}()
	return c
}

func (t *Rfs) Get(rid string, off, count int64, pred string) <-chan []byte {
	t.dprintf("get %s %d %d %q\n", rid, off, count, pred)
	msg := &Msg{Op: Tget, Rid: rid, Off: off, Count: count, Pred: pred}
	return t.getrpc(rid, msg)
}

func (t *Rfs) putrpc(rid string, msg *Msg, dc <-chan []byte) chan zx.Dir {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan zx.Dir, 1)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sput, len(raw))
		reqc <- raw
		nm := 0
		tot := 0
		for m := range dc {
			nm++
			cs.Recv(int64(len(m)))
			if ok := reqc <- m; !ok {
				err := cerror(reqc)
				close(dc, err)
				close(c, err)
				cs.End(err != nil)
				return
			}
			if len(m) == 0 {
				break
			}
			tot += len(m)
		}
		close(reqc, cerror(dc))
		rep := <-repc
		var err error
		var d zx.Dir
		if len(rep) == 0 {
			err = cerror(repc)
		} else {
			d, _, err = zx.UnpackDir(rep)
			if err==nil && d==nil {
				err = errors.New("null dir in put reply")
			}
		}
		cs.End(err != nil)
		if err == nil {
			t.dprintf("put %s: %s\n", rid, d)
			c <- d
		} else {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("put %s: %s\n", rid, err)
		}
		close(c, err)
	}()
	return c
}

func (t *Rfs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir {
	t.dprintf("put %s %v %d '%s'\n", rid, d, off, pred)
	msg := &Msg{Op: Tput, Rid: rid, D: d, Off: off, Pred: pred}
	return t.putrpc(rid, msg, dc)
}

func (t *Rfs) errrpc(rid, op string, msg *Msg, k int) chan error {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan error, 1)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		var cs *zx.CallStat
		if k >= 0 {
			cs = t.IOstats.NewCallSize(k, len(raw))
		}
		reqc <- raw
		close(reqc)
		<-repc
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("%s %s: %s\n", op, rid, err)
		} else {
			t.dprintf("%s %s: ok\n", op, rid)
		}
		c <- err
		close(c, err)
		cs.End(err != nil)
	}()
	return c
}

func (t *Rfs) Fsys(name string) <-chan error {
	t.dprintf("fsys %s\n", name)
	msg := &Msg{Op: Tfsys, Rid: name}
	return t.errrpc(name, "fsys", msg, -1)
}

func (t *Rfs) Mkdir(rid string, d zx.Dir) chan error {
	msg := &Msg{Op: Tmkdir, Rid: rid, D: d}
	t.dprintf("mkdir %s %v\n", rid, d)
	return t.errrpc(rid, "mkdir", msg, zx.Smkdir)
}

func (t *Rfs) Move(from, to string) chan error {
	t.dprintf("move %s %s \n", from, to)
	msg := &Msg{Op: Tmove, Rid: from, To: to}
	return t.errrpc(from, "move", msg, zx.Smove)
}

func (t *Rfs) Remove(rid string) chan error {
	t.dprintf("remove %s\n", rid)
	msg := &Msg{Op: Tremove, Rid: rid}
	return t.errrpc(rid, "remove", msg, zx.Sremove)
}

func (t *Rfs) RemoveAll(rid string) chan error {
	t.dprintf("removeall %s\n", rid)
	msg := &Msg{Op: Tremoveall, Rid: rid}
	return t.errrpc(rid, "removeall", msg, zx.Sremoveall)
}

func (t *Rfs) Wstat(rid string, d zx.Dir) chan error {
	t.dprintf("wstat %s %v\n", rid, d)
	msg := &Msg{Op: Twstat, Rid: rid, D: d}
	return t.errrpc(rid, "wstat", msg, zx.Swstat)
}

func (t *Rfs) Find(rid, pred, spref, dpref string, depth int) <-chan zx.Dir {
	t.dprintf("find %s '%s' '%s' '%s' %d\n", rid, pred, spref, dpref, depth)
	dc := make(chan zx.Dir)
	msg := &Msg{Op: Tfind, Rid: rid, Pred: pred, Spref: spref, Dpref: dpref, Depth: depth}
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sfind, len(raw))
		reqc <- raw
		close(reqc)
		some := false
		for rep := range repc {
			cs.Send(int64(len(rep)))
			d, _, _ := zx.UnpackDir(rep)
			if d != nil {
				d["addr"] = t.addr
				d["proto"] = "zx"
			}
			if ok := dc <- d; !ok {
				close(repc, cerror(dc))
				break
			}
			some = true
			t.dprintf(rid, "find", "<- %v\n", d)
		}
		if !some {
			dc <- nil
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(dc, err)
		cs.End(err != nil)
	}()
	return dc

}

func (t *Rfs) FindGet(rid, pred, spref, dpref string, depth int) <-chan zx.DirData {
	t.dprintf("findget %s '%s' '%s' '%s' %d\n", rid, pred, spref, dpref, depth)
	dc := make(chan zx.DirData)
	msg := &Msg{Op: Tfindget, Rid: rid, Pred: pred, Spref: spref, Dpref: dpref, Depth: depth}
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sfind, len(raw))
		reqc <- raw
		close(reqc)
		for rep := range repc {
			cs.Send(int64(len(rep)))
			d, _, _ := zx.UnpackDir(rep)
			if d != nil {
				d["addr"] = t.addr
				d["proto"] = "zx"
			}
			res := zx.DirData{Dir: d}
			var datc chan []byte
			if d["err"]=="" && d["type"]=="-" {
				datc = make(chan []byte)
				res.Datac = datc
			}
			if ok := dc <- res; !ok {
				close(repc, cerror(dc))
				break
			}
			t.dprintf(rid, "find", "<- %v\n", d)
			if datc != nil {
				for rep := range repc {
					if len(rep) == 0 {
						break
					}
					if ok := datc <- rep; !ok {
						continue
					}
				}
				close(datc, cerror(repc))
			}
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(dc, err)
	}()
	return dc

}
Example #3
0
// d is a dup and can be changed.
func (t *Fs) find(f File, d zx.Dir, p *pred.Pred, spref, dpref string, lvl int,
	c chan<- zx.Dir, ai *auth.Info) {
	match, pruned, err := p.EvalAt(d, lvl)
	t.dprintf("find  at %v\n\t%v\n\t%v %v %v\n\n", d, p, match, pruned, err)
	if pruned {
		if !match {
			d["err"] = "pruned"
		}
		c <- d
		return
	}
	if d["type"] == "d" && err == nil {
		if !t.NoPermCheck && !d.CanWalk(ai) {
			err = dbg.ErrPerm
		}
	}
	if err != nil {
		d["err"] = err.Error()
		c <-d
		return
	}
	if d["rm"] != "" {
		return
	}
	if match {
		if ok := c <- d; !ok {
			return
		}
	}
	if d["type"] != "d" || f == nil {
		return
	}
	wf, ok := f.(Walker)
	if !ok {
		return
	}
	ns, err := wf.Getdir()
	if err != nil {
		return
	}
	sort.Sort(sort.StringSlice(ns))
	if d["name"] == "/" {
		cd := ctldir.Dup()
		if spref != dpref {
			cpath := cd["path"]
			suff := zx.Suffix(cpath, spref)
			cd["path"] = zx.Path(dpref, suff)
		}
		t.find(nil, cd, p, spref, dpref, lvl+1, c, ai)
	}
	for _, cnm := range ns {
		cf, err := wf.Walk(cnm)
		if err != nil {
			continue
		}
		cp := zx.Path(d["path"], cnm)
		cd, err := t.statf(cf, cp)
		if err != nil || cd["rm"] != "" {
			continue
		}
		cd = cd.Dup()
		if spref != dpref {
			cpath := cd["path"]
			suff := zx.Suffix(cpath, spref)
			cd["path"] = zx.Path(dpref, suff)
		}
		t.find(cf, cd, p, spref, dpref, lvl+1, c, ai)
	}
}

func (t *Fs) Find(rid, fpred, spref, dpref string, depth int) <-chan zx.Dir {
	t.dprintf("find %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	cs := t.IOstats.NewCall(zx.Sfind)
	dc := make(chan zx.Dir)
	go func() {
		rid, err := zx.AbsPath(rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		f, err := t.walk(rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		p, err := pred.New(fpred)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		d, err := t.statf(f, rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		d = d.Dup()
		if spref != dpref {
			suff := zx.Suffix(rid, spref)
			d["path"] = zx.Path(dpref, suff)
		}
		t.find(f, d, p, spref, dpref, depth, dc, t.ai)
		cs.End(err != nil)
		t.dprintf("find %s: ok\n", rid)
		close(dc)
	}()
	return dc
}

// used only by findget
func (t *Fs) get(rid string, datac chan<- []byte) error {
	f, err := t.walk(rid)
	if err != nil {
		return err
	}
	gf, ok := f.(Getter)
	if !ok {
		return nil
	}
	return gf.Get(0, -1, datac)
}

func (t *Fs) FindGet(rid, fpred, spref, dpref string, depth int) <-chan zx.DirData {
	t.dprintf("findget %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	gc := make(chan zx.DirData)
	cs := t.IOstats.NewCall(zx.Sfindget)
	go func() {
		dc := t.Find(rid, fpred, spref, dpref, depth) // BUG: will stat a Sfind
		for d := range dc {
			g := zx.DirData{Dir: d}
			var datac chan []byte
			if d["err"] == "" && !t.NoPermCheck &&
				d["type"] != "d" && !d.CanRead(t.ai) {
				d["err"] = dbg.ErrPerm.Error()
				
			}
			if d["err"]=="" && d["type"]!="d" {
				datac = make(chan []byte)
				g.Datac = datac
			}
			if ok := gc <- g; !ok {
				close(dc, cerror(gc))
				break
			}
			if datac != nil {
				err := t.get(d["spath"], datac)
				close(datac, err)
			}
		}
		err := cerror(dc)
		cs.End(err != nil)
		if err != nil {
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(gc, err)
	}()
	return gc
}