func (t *Fs) Wstat(rid string, d zx.Dir) chan error { t.dprintf("wstat %s %v\n", rid, d) c := make(chan error, 1) rid, err := zx.AbsPath(rid) if err != nil { c <- err close(c, err) return c } cs := t.IOstats.NewCall(zx.Swstat) if rid == "/Ctl" { close(c) cs.End(false) return c } err = t.wstat(rid, d) if err == nil { t.dprintf("wstat %s: ok\n", rid) } else { t.dprintf("wstat %s: %s\n", rid, err) } c <- err close(c, err) cs.End(err != nil) return c }
func (t *Fs) get(rid string, off, count int64, dc chan<- []byte, cs *zx.CallStat) error { rid, err := zx.AbsPath(rid) if err != nil { return err } if rid == "/Ctl" { return t.getCtl(off, count, dc, cs) } f, _, err := t.walk(rid, nil) if err == nil && !t.NoPermCheck { f.mlk.Lock() if !f.d.CanRead(t.ai) { err = dbg.ErrPerm } f.mlk.Unlock() } if err != nil { return err } f.mlk.Lock() if f.d["type"] == "d" { f.mlk.Unlock() return f.getDir(off, count, dc, cs) } f.mlk.Unlock() cs.Sending() n, nm, err := f.data.SendTo(off, count, dc) cs.Sends(int64(nm), n) return err }
func (fs *Cfs) stat(rid string) (zx.Dir, error) { rid, err := zx.AbsPath(rid) if err != nil { return nil, err } if rid == "/Ctl" { d := ctldir.Dup() d["tpath"] = fs.tpath return d, nil } if rid == "/Chg" { d := chgdir.Dup() d["tpath"] = fs.tpath return d, nil } f, _, err := fs.walk(rid, RO) if err != nil { return nil, err } f.unlockc(RO) nocattrs(f.d) /* do not add /Chg to the count, it's hidden now if id == "/" { // adjust size for /Chg nd["size"] = strconv.Itoa(f.d.Int("size") + 1) } */ return f.d, nil }
func (t *Fs) remove(rid string, all bool) error { rid, err := zx.AbsPath(rid) if err != nil { return err } if rid == "/" || rid == "/Ctl" { return fmt.Errorf("%s: %s", rid, dbg.ErrPerm) } pf, err := t.walk(path.Dir(rid)) if err != nil { return err } pd, err := pf.Stat() if err != nil { return err } pfrm, ok := pf.(Remover) if !ok { return fmt.Errorf("%s: %s", pd["path"], dbg.ErrPerm) } if !t.NoPermCheck && !pd.CanWrite(t.ai) { return fmt.Errorf("%s: %s", pd["path"], dbg.ErrPerm) } nm := path.Base(rid) f, err := pfrm.Walk(nm) if err != nil { return err } return pfrm.Remove(f, nm, all) }
func (t *Lfs) stat(rid string) (zx.Dir, error) { rid, err := zx.AbsPath(rid) if err != nil { return nil, err } if rid == "/Ctl" { d := ctldir.Dup() d["tpath"] = t.path return d, nil } path := zx.Path(t.path, rid) st, err := os.Stat(path) if err != nil { return nil, err } nd := 0 sum := "" if st.IsDir() { nd, sum = dirsz(path) if rid == "/" { nd++ } } d := zx.NewDir(st, nd) if t.readattrs { t.fileAttrs(path, d) } if sum != "" { d["Sum"] = sum } d["tpath"] = t.path d["path"] = rid d["spath"] = rid d["proto"] = "lfs" if rid == "/" { d["name"] = "/" } if d["Uid"] == "" { d["Uid"] = dbg.Usr } if d["Gid"] == "" { d["Gid"] = dbg.Usr } if d["Wuid"] == "" { d["Wuid"] = dbg.Usr } return d, nil }
func (t *Fs) walk(rid string) (File, error) { rid, err := zx.AbsPath(rid) if err != nil { return nil, err } if rid == "/" { return t.root, nil } if rid == "/Ctl" { return nil, nil } els := zx.Elems(rid) f := t.root p := "/" var d zx.Dir for _, e := range els { t.Dprintf("walk %s %s...\n", f, e) d, err = f.Stat() if err != nil { t.Dprintf("\tstat: %s\n", f, err) return nil, err } if d["type"] != "d" { t.Dprintf("\tnot dir\n") return nil, fmt.Errorf("%s: %s", p, dbg.ErrNotDir) } if !t.NoPermCheck && !d.CanWalk(t.ai) { t.Dprintf("\tno perm\n") return nil, fmt.Errorf("%s: %s", p, dbg.ErrPerm) } wf, ok := f.(Walker) if !ok { t.Dprintf("\tnot walker\n") return nil, fmt.Errorf("%s: %s: %s", p, e, dbg.ErrNotExist) } f, err = wf.Walk(e) if err != nil { t.Dprintf("\twalk: %s\n", err) return nil, err } p = zx.Path(p, e) t.Dprintf("walked %s\n", f) } return f, nil }
func (t *Fs) stat(rid string) (zx.Dir, error) { rid, err := zx.AbsPath(rid) if err != nil { return nil, err } if rid == "/Ctl" { cd := ctldir.Dup() cd["tpath"] = t.path return cd, nil } f, _, err := t.walk(rid, nil) if err != nil { return nil, err } f.mlk.Lock() defer f.mlk.Unlock() return f.d.Dup(), nil }
func (t *Fs) Mkdir(rid string, d zx.Dir) chan error { t.dprintf("mkdir %s %v\n", rid, d) cs := t.IOstats.NewCall(zx.Smkdir) rid, err := zx.AbsPath(rid) if rid=="/Ctl" || rid == "/" { err = dbg.ErrExists } else { err = t.mkdir(rid, d) } c := make(chan error, 1) cs.End(err != nil) if err != nil { t.dprintf("mkdir %s: %s\n", rid, err) } c <- err close(c, err) return c }
/* See the Binder.Unmount operation. */ func (ns *Tree) Unmount(fname string, d zx.Dir) <-chan error { c := make(chan error, 1) go func() { name := "" var err error if fname != "" { name, err = zx.AbsPath(fname) if err != nil { close(c, err) return } } ns.lk.Lock() defer ns.lk.Unlock() c <- ns.unmount(name, d) close(c, err) }() return c }
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 }
func (t *Fs) remove(rid string, all bool, cs *zx.CallStat) chan error { c := make(chan error, 1) rid, err := zx.AbsPath(rid) if rid=="/Ctl" || rid == "/" { t.dprintf("remove %s: %s\n", rid, dbg.ErrPerm) err := fmt.Errorf("%s: %s", rid, dbg.ErrPerm) c <- err close(c, err) cs.End(true) return c } f, _, err := t.walk(rid, nil) if f != nil { f.mlk.Lock() } if err == nil && !all && f.d["type"] == "d" && len(f.child) > 0 { err = errors.New("directory is not empty") } if err == nil && !t.noPerms() && !f.d.CanWrite(t.ai) { err = dbg.ErrPerm } if f != nil { if err == nil { f.d["rm"] = "y" } f.mlk.Unlock() } if err != nil { t.dprintf("remove %s: %s\n", rid, err) c <- err close(c, err) cs.End(true) return c } t.detach(f) t.dprintf("remove %s: ok\n", rid) close(c) cs.End(false) return c }
func (t *Fs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir { d = d.UsrAttrs() 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 nd zx.Dir if err == nil && rid == "/" { err = fmt.Errorf("/: %s", dbg.ErrPerm) } if err == nil && rid == "/Ctl" { xerr := t.putCtl(dc) if xerr == nil { nd = zx.Dir{"size": "0", "Sum": zx.Zsum()} nd.SetTime("mtime", time.Now()) } err = xerr } else if err == nil { err = t.put(rid, d, off, dc, pred) if err == nil { nd, err = t.stat(rid) } } if err == nil { rd := zx.Dir{"size": nd["size"], "mtime": nd["mtime"], "Sum": nd["Sum"]} t.dprintf("put %s: %s\n", rid, rd) c <- rd } else { t.dprintf("put %s: %s\n", rid, err) close(dc, err) } close(c, err) cs.End(err != nil) }() return c }
// Resolve a name and return the prefix path, the array of mount points for it and the server paths // for each mount point. // The path must be absolute. func (ns *Tree) Resolve(name string) (pref string, mnts []zx.Dir, spaths []string, err error) { path, err := zx.AbsPath(name) if err != nil { return "", nil, nil, err } ns.dprintf("resolve %s\n", path) ns.lk.RLock() defer ns.lk.RUnlock() var p *prefix for _, np := range ns.pref { if zx.HasPrefix(path, np.name) { ns.dprintf("\thasprefix %s %s\n", path, np.name) p = np } } if p == nil { ns.dprintf("\tno prefixes\n") return "", nil, nil, dbg.ErrNotExist } suff := zx.Suffix(path, p.name) mnts = make([]zx.Dir, 0, len(p.mnt)) spaths = []string{} for _, d := range p.mnt { if isfinder(d) || suff=="" || suff=="/" { mnts = append(mnts, d.Dup()) spath := zx.Path(suff, d["spath"]) spaths = append(spaths, spath) ns.dprintf("\ts='%s' d=%s\n", spath, d) } else { ns.dprintf("\tskip %s\n", d) } } if len(mnts) == 0 { ns.dprintf("\tno prefixes left\n") return "", nil, nil, dbg.ErrNotExist } return p.name, mnts, spaths, nil }
// 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 }
func (t *Lfs) Stat(rid string) chan zx.Dir { t.dprintf("stat %s\n", rid) cs := t.IOstats.NewCall(zx.Sstat) c := make(chan zx.Dir, 1) rid, err := zx.AbsPath(rid) var d zx.Dir if err == nil { d, err = t.stat(rid) } if err==nil && t.ai!=nil && !t.NoPermCheck { _, _, err = t.canWalkTo(rid, 0) } if err != nil { t.dprintf("stat %s: %s\n", rid, err) close(c, err) cs.End(true) return c } t.dprintf("stat %s: ok\n", rid) c <- d close(c) cs.End(false) return c }
func (t *Lfs) get(rid string, off, count int64, dc chan<- []byte, cs *zx.CallStat) (int64, error) { rid, err := zx.AbsPath(rid) if err != nil { return 0, err } if rid == "/Ctl" { return t.getCtl(off, count, dc, cs) } path := zx.Path(t.path, rid) fd, err := os.Open(path) if err==nil && t.ai!=nil && !t.NoPermCheck { _, _, err = t.canWalkTo(rid, 0444) } if err != nil { return 0, err } defer fd.Close() st, err := fd.Stat() if err != nil { return 0, err } if off!=0 && !st.IsDir() { if _, err := fd.Seek(off, 0); err != nil { return 0, err } } if st.IsDir() { ds, err := ioutil.ReadDir(path) nd := 0 tot := 0 ctlsent := false var xds map[string]zx.Dir if t.readattrs { xds, _ = t.dirAttrs(path) } Dloop: for i := 0; i < len(ds); { if off > 0 { off-- if !ctlsent && rid=="/" { ctlsent = true } else { i++ } continue } switch count { case zx.All: break case 0: break Dloop default: count-- } if !ctlsent && rid=="/" { ctlsent = true nd++ d := ctldir n, _ := d.Send(dc) nd++ // but not i++ tot += n continue } fi := ds[i] if fi.Name() == afname { if i == len(ds)-1 { break } ds = append(ds[:i], ds[i+1:]...) fi = ds[i] } cpath := zx.Path(path, fi.Name()) n := 0 sum := "" if fi.IsDir() { n, sum = dirsz(cpath) } d := zx.NewDir(fi, n) d["path"] = zx.Path(rid, fi.Name()) d["spath"] = d["path"] d["tpath"] = t.path if t.readattrs { if xd, ok := xds[fi.Name()]; ok { for k, v := range xd { if zx.IsUpper(k) { d[k] = v } } } else { d["Uid"] = dbg.Usr d["Gid"] = dbg.Usr } } if sum != "" { d["Sum"] = sum } cs.Send(0) n, err := d.Send(dc) if err != nil { return int64(tot), err } nd++ i++ tot += n } return int64(tot), err } if count == zx.All { cs.Sending() nm, n, err := nchan.ReadBytesFrom(fd, dc) cs.Sends(nm, n) return n, err } rr := io.LimitReader(fd, count) cs.Sending() nm, n, err := nchan.ReadBytesFrom(rr, dc) cs.Sends(nm, n) return n, err }
func (t *Fs) move(from, to string) error { from, ferr := zx.AbsPath(from) if ferr != nil { return ferr } if from == "/" || from == "/Ctl" { return fmt.Errorf("%s: %s", from, dbg.ErrPerm) } to, terr := zx.AbsPath(to) if terr != nil { return terr } if to == "/" || to == "/Ctl" { return fmt.Errorf("%s: %s", from, dbg.ErrPerm) } if inconsistent(from, to) { return fmt.Errorf("%s: inconsistent move", from) } pfromf, err := t.walk(path.Dir(from)) if err != nil { return err } pfrommv, ok := pfromf.(Mover) if !ok { return fmt.Errorf("%s: %s", from, dbg.ErrPerm) } pfd, err := pfromf.Stat() if err != nil { return err } if !t.NoPermCheck && !pfd.CanWrite(t.ai) { return fmt.Errorf("%s: %s", pfd["path"], dbg.ErrPerm) } var fromf File fromf, err = pfrommv.Walk(path.Base(from)) if err != nil { return err } pto, err := t.walk(path.Dir(to)) if err != nil { return err } ptd, err := pto.Stat() if err != nil { return err } if !t.NoPermCheck && !ptd.CanWrite(t.ai) { return fmt.Errorf("%s: %s", ptd["path"], dbg.ErrPerm) } ptow, ok := pto.(Walker) if !ok { return fmt.Errorf("%s: %s", ptd["path"], dbg.ErrPerm) } tof, err := ptow.Walk(path.Base(to)) if err == nil { tod, err := tof.Stat() if tod["type"] == "d" { return fmt.Errorf("%s: %s", to, dbg.ErrIsDir) } return err } return pfrommv.Move(fromf, path.Base(from), pto, path.Base(to)) }
// 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 }
func (t *Fs) Move(from, to string) chan error { t.dprintf("move %s %s \n", from, to) cs := t.IOstats.NewCall(zx.Smove) c := make(chan error, 1) from, ferr := zx.AbsPath(from) to, terr := zx.AbsPath(to) var pfrom, pto *mFile var leftto []string var err error var fd, pd *mFile if ferr != nil { err = ferr } else if terr != nil { err = terr } else if from == to { c <- nil close(c) cs.End(false) return c } if err == nil { fd, _, err = t.walk(path.Dir(from), nil) } if err == nil && !t.noPerms() { fd.mlk.Lock() if !fd.d.CanWrite(t.ai) { err = fmt.Errorf("%s: %s", fd, dbg.ErrPerm) } fd.mlk.Unlock() } if err == nil { pd, _, err = t.walk(path.Dir(to), nil) } var pdpath, pdspath string if err == nil { pd.mlk.Lock() if !t.noPerms() && !pd.d.CanWrite(t.ai) { err = fmt.Errorf("%s: %s", pd, dbg.ErrPerm) } pdpath = pd.d["path"] pdspath = pd.d["spath"] pd.mlk.Unlock() } if err != nil { goto Fail } if from=="/Ctl" || to=="/Ctl" || from == "/" || to == "/" { err = dbg.ErrPerm } else if pfrom, _, ferr = t.walk(from, nil); ferr != nil { err = ferr } else if inconsistent(from, to) { err = errors.New("inconsistent move") } else if pto, leftto, terr = t.walk(to, nil); terr != nil && !dbg.IsNotExist(terr) { err = terr } else if len(leftto) > 1 { err = terr } else if len(leftto) == 0 && pto.d["type"] == "d" { err = fmt.Errorf("%s: %s", pto, dbg.ErrExists) } else if len(leftto) == 0 && pto.d["type"] != pfrom.d["type"] { // race: no lock in types err = fmt.Errorf("%s: incosistent move", pfrom) } Fail: if err != nil { c <- err t.dprintf("move %s: %s\n", from, err) close(c, err) cs.End(true) return c } t.detach(pfrom) pfrom.mlk.Lock() pfrom.name= path.Base(to) pfrom.d["name"] = pfrom.name pfrom.d["path"] = zx.Path(pdpath, pfrom.name) pfrom.d["spath"] = zx.Path(pdspath, pfrom.name) pfrom.mlk.Unlock() pfrom.moved() pd.mlk.Lock() pd.clk.Lock() pd.attach(pfrom) pd.clk.Unlock() pd.mlk.Unlock() t.dprintf("move %s: ok\n", from) close(c) cs.End(false) return c }
// 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) } }
func (t *Fs) Mkdir(rid string, d zx.Dir) chan error { t.dprintf("mkdir %s %v\n", rid, d) cs := t.IOstats.NewCall(zx.Smkdir) c := make(chan error, 1) rid, err := zx.AbsPath(rid) if rid == "/" || rid=="/Ctl" { err = dbg.ErrExists } var f *mFile var left []string if err == nil { f, left, err = t.walk(rid, nil) } if err == nil { err = fmt.Errorf("'%s': %s", rid, dbg.ErrExists) } else if len(left) == 1 { err = nil } if err != nil { cs.End(true) t.dprintf("mkdir %s: %s\n", rid, err) c <- err close(c, err) return c } ud := d.UsrAttrs() delete(ud, "size") noinherit := false if m := ud["Mode"]; m != "" { ud["mode"] = m delete(ud, "Mode") noinherit = true } if ud["mode"] == "" { ud["mode"] = "0775" } if (!t.WstatAll || t.ai != nil) && !noinherit { f.mlk.Lock() ud["type"] = "d" ud.Inherit(f.d.Mode()) delete(ud, "type") f.mlk.Unlock() } u := dbg.Usr if t.ai != nil { u = t.ai.Uid } nf := &mFile { name: left[0], d: zx.Dir{ "mode": ud["mode"], "name": left[0], "path": rid, "spath": rid, "tpath": f.t.path, "Uid": u, "Gid": f.d["Gid"], "Wuid": u, "type": "d", "size": "0", "proto": "proc", }, child: []*mFile{}, t: t, } if DoSum { nf.d["Sum"] = zx.Zsum() } f.mlk.Lock() if !t.noPerms() && !f.d.CanWrite(t.ai) { err = fmt.Errorf("%s: %s", f, dbg.ErrPerm) } ai := t.ai if t.NoPermCheck { ai = nil } if err == nil && (!t.WstatAll || t.ai != nil) { err = nf.d.CanWstat(ai, ud) } if err != nil { f.mlk.Unlock() cs.End(true) t.dprintf("mkdir %s: %s\n", rid, err) c <- err close(c, err) return c } f.mlk.Unlock() f.mlk.Lock() f.clk.Lock() f.attach(nf) f.clk.Unlock() f.mlk.Unlock() f = nf f.mlk.Lock() if t.WstatAll && t.ai == nil && d["Wuid"] != "" { ud["Wuid"] = d["Wuid"] } err = f.wstat(ud) f.mlk.Unlock() cs.End(err != nil) if err != nil { t.dprintf("mkdir %s: %s\n", rid, err) } c <- err close(c, err) return c }