func ch(d, nd zx.Dir) error { if nd["mode"] != "" { nd = nd.Dup() chmod(d, nd["mode"]) } _, err := cmd.Wstat(d["path"], nd) return err }
/* Execute the part of the ns.Find operation that evaluates p at the tree rooted at d (considering that its level is the one indicated). Found entries are sent through the given channel, which is closed only upon errors. This is useful to implement ns.Find when writting services. */ func (p *Pred) FindAt(fs zx.Sender, d zx.Dir, c chan<- zx.Dir, lvl int) { match, pruned, err := p.EvalAt(d, lvl) if err != nil { close(c, err) return } if pruned { nd := d.Dup() nd["err"] = "pruned" c <- nd return } if d["rm"] != "" { return } var ds []zx.Dir if d["type"] == "d" { ds, err = zx.GetDir(fs, d["path"]) } if err != nil { nd := d.Dup() nd["err"] = err.Error() c <- nd return } if match { if ok := c <- d; !ok { return } } for i := 0; i < len(ds); i++ { cd := ds[i] if cd["rm"] != "" { continue } p.FindAt(fs, cd, c, lvl+1) } } func Find(fs zx.Tree, path, pred string) <-chan zx.Dir { c := make(chan zx.Dir) go func() { d, err := zx.Stat(fs, path) if d == nil { close(c, err) return } x, err := New(pred) if err != nil { close(c, err) return } x.FindAt(fs, d, c, 0) close(c) }() return c }
// NB: Attributes that the user can't set are always ignored. // If the user has no permissioin to set an attribute, that's an error. // Setting an attribute to an empty string removes it. // Uid, Gid, and Wuid can't be removed. // Meta locking done by caller, might lock data on truncations func (f *mFile) wstat(d zx.Dir) error { if len(d) == 0 { return nil } d = d.Dup() sum := "" if f.d["type"] != "d" { if _, ok := d["size"]; ok { sz := d.Int64("size") if sz < 0 { sz = 0 } f.data.Truncate(sz) d["size"] = strconv.FormatInt(sz, 10) if DoSum { sum = f.data.Sum() } } } else { delete(d, "size") } if _, ok := d["mode"]; ok { mode := d.Int("mode")&0777 d["mode"] = "0" + strconv.FormatInt(int64(mode), 8) } if _, ok := d["mtime"]; ok { d.SetTime("mtime", d.Time("mtime")) } if sum != "" { f.d["Sum"] = sum } ud := d.UsrAttrs() if d["Wuid"] != "" { ud["Wuid"] = d["Wuid"] } for k, v := range ud { if v == "" { delete(f.d, k) } else { f.d[k] = v } } return nil }
func (t *Fs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir { d = d.Dup() t.dprintf("put %s %v %d '%s'\n", rid, d, off, pred) cs := t.IOstats.NewCall(zx.Sput) c := make(chan zx.Dir, 1) go func() { cs.Sending() rid, err := zx.AbsPath(rid) var nm, n int64 var nd zx.Dir if err == nil && rid == "/Ctl" { nc, xerr := t.putCtl(dc) if xerr == nil { nd = zx.Dir{"size": "0"} if DoSum { nd["Sum"] = zx.Zsum() } nd.SetTime("mtime", time.Now()) nm = 1 n = int64(nc) } err = xerr } else if err == nil { nd, nm, n, err = t.put(rid, d, off, dc, pred) cs.Sends(nm, n) } if err == nil { rd := zx.Dir{"size": nd["size"], "mtime": nd["mtime"]} if nd["Sum"] != "" { rd["Sum"] = nd["Sum"] } t.dprintf("put %s: %s (wrote %d)\n", rid, rd, n) c <- rd } else { t.dprintf("put %s: %s\n", rid, err) close(dc, err) } close(c, err) cs.End(err != nil) }() return c }
// See the Binder.Mount operation. func (ns *Tree) Mount(fname string, d zx.Dir, flag Flag) <-chan error { c := make(chan error, 1) go func() { name, err := zx.AbsPath(fname) if err==nil && d==nil { err = errors.New("no mounted dir") } if err != nil { c <- err close(c, err) return } d = d.Dup() delete(d, "mtime") delete(d, "size") d["path"] = name d["name"] = path.Base(name) ns.lk.Lock() defer ns.lk.Unlock() c <- ns.mount(d, flag) close(c, err) }() return c }
// 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 }