func (ch Chg) applyMeta(lfs zx.RWTree) error { nd := ch.D.UsrAttrs() for _, k := range ignoredPutAttrs { delete(nd, k) } ec := lfs.Wstat(ch.D["path"], nd) return <-ec }
func (ch Chg) applyData(lfs zx.RWTree, rfs zx.Tree) error { nd := ch.D.UsrAttrs() for _, k := range ignoredPutAttrs { delete(nd, k) } datc := rfs.Get(ch.D["path"], 0, zx.All, "") dc := lfs.Put(ch.D["path"], nd, 0, datc, "") <-dc return cerror(dc) }
func (ch Chg) applyAdd(lfs zx.RWTree, rfs zx.Tree, pred string, ec chan<- error) error { var err error gc := rfs.FindGet(ch.D["path"], pred, "", "", 0) for g := range gc { dprintf("get %s\n", g) d := g.Dir if d == nil { break } for _, k := range ignoredPutAttrs { delete(d, k) } if d["err"] != "" { e := errors.New(d["err"]) perr(ec, e) dprintf("%s: %s\n", d["path"], d["err"]) if err == nil { err = e } continue } if g.Datac == nil && d["type"] != "d" { g.Datac = nchan.Null } if d["type"] == "d" { e := <-lfs.Mkdir(d["path"], d) if e != nil { perr(ec, e) if err == nil { err = e } } continue } dc := lfs.Put(d["path"], d, 0, g.Datac, "") <-dc if e := cerror(dc); e != nil { dprintf("%s: put: %s\n", d["path"], e) perr(ec, e) if err == nil { err = e } } } close(gc) if e := cerror(gc); e != nil { dprintf("get: %s\n", e) perr(ec, e) if err == nil { err = e } } return err }
// Make some changes in the test zx tree. // - Touch /a/a1 // - Chmod /a/a2 // - Remove /a/b/c /a/b/c/c3 // - Create /a/n /a/n/m /a/n/m/m1 func MkZXChgs(t Fataler, fs zx.RWTree) { TouchZX(fs, "/a/a1") if err := <- fs.Wstat("/a/a2", zx.Dir{"mode": "0750"}); err != nil { t.Fatalf("chmod: %s", err) } if err := <-fs.RemoveAll("/a/b/c"); err != nil { t.Fatalf("rm: %s", err) } <-fs.Mkdir("/a", zx.Dir{"mode": "0750"}) <-fs.Mkdir("/a/n", zx.Dir{"mode": "0750"}) if err := <-fs.Mkdir("/a/n/m", zx.Dir{"mode": "0750"}); err != nil { t.Fatalf("mkdir: %s", err) } err := zx.PutAll(fs, "/a/n/m/m1", zx.Dir{"mode": "0640"}, []byte("a new file\n")) if err != nil { t.Fatalf("new file: %s", err) } TouchZX(fs, "/a/n/m/m1") TouchZX(fs, "/a/n/m") TouchZX(fs, "/a/n") TouchZX(fs, "/a") }
// Make some changes in the test zx tree, another version. // - Remove /2 // - Create /2/n2 // - Truncate /1 func MkZXChgs2(t Fataler, fs zx.RWTree) { if err := <-fs.Remove("/2"); err != nil { t.Fatalf("rm: %s", err) } <-fs.Mkdir("/2", zx.Dir{"mode": "0750"}) if err := <-fs.Mkdir("/2/n2", zx.Dir{"mode": "0750"}); err != nil { t.Fatalf("mkdir: %s", err) } TouchZX(fs, "/2/n2") TouchZX(fs, "/2") if err := <-fs.Wstat("/1", zx.Dir{"size": "50"}); err != nil { t.Fatalf("truncate: %s", err) } TouchZX(fs, "/1") }
// see if fn has errors (permissions) or not for the given path and 1,2,4 perm. bit. // returns xxxxxxxxxxxx where x is y or n // for ugo and masks 777 770 700 000 // Expected result is always yyyyynynnnnn func ugo(t Fataler, fs zx.RWTree, p string, bit uint, fn func(zx.RWTree) error) string { err := <-fs.Wstat(p, zx.Dir{"mode": "0777"}) if err != nil { t.Fatalf("wstat: %s", err) } defer func() { // so we can later remove it <-fs.Wstat(p, zx.Dir{"mode": "0755"}) }() // /chkd is nemo gid1 usrs := []usr{ usr{who: "uid", ai: &auth.Info{Uid: dbg.Usr, SpeaksFor: dbg.Usr, Ok: true, Gids: map[string]bool{}}}, usr{who: "gid", ai: &auth.Info{Uid: "gid1", SpeaksFor: dbg.Usr, Ok: true, Gids: map[string]bool{}}}, usr{who: "oid", ai: &auth.Info{Uid: "other", SpeaksFor: dbg.Usr, Ok: true, Gids: map[string]bool{}}}, } shift := uint(0) m := uint(0777) out := "" for i := 0; i < 4; i++ { printf("mode %o\n", m) err := <-fs.Wstat(p, zx.Dir{"mode": fmt.Sprintf("0%o", m)}) if err != nil { t.Fatalf("wstat: %s", err) } for _, u := range usrs { if err := fn(authfor(t, fs, u.ai)); err != nil { out += "n" printf("%s can't for %o\n", u.who, m) } else { out += "y" printf("%s can for %o\n", u.who, m) } } m &^= (bit << shift) shift += 3 } return out }
// set a fake mtime that can be predicted. func TouchZX(fs zx.RWTree, path string) error { d := zx.Dir{} d.SetTime("mtime", time.Unix(xt/1e9, xt%1e9)) xt += 1e9 return <-fs.Wstat(path, d) }
func (ch Chg) applyDel(lfs zx.RWTree) error { return <-lfs.RemoveAll(ch.D["path"]) }
func rmove(t Fataler, fs zx.RWTree, fname string) { <-fs.Move(fname, fname+"o") <-fs.Move(fname+"o", fname) }
func rwstat(t Fataler, fs zx.RWTree, fname string) { <-fs.Wstat(fname, zx.Dir{"mode": "0700", "Foo": "Bar"}) }
func rmkdir(t Fataler, fs zx.RWTree, fname string) { <-fs.Mkdir(fname, zx.Dir{"mode": "0755"}) }
func rremove(t Fataler, fs zx.RWTree, fname string) { <-fs.Remove(fname) }
func mkfs(addr string, quiet bool) (zx.Tree, func(), error) { if len(addr) == 0 { dbg.Warn("missing address") opts.Usage() dbg.Fatal("usage") } dbp := &fs.Debug var m, fs zx.RWTree var fsst *zx.IOstats var err error var lflags, flags *zx.Flags if _, err = os.Stat(addr); err == nil { fs, flags, fsst, err = mklfs(addr) } else { fs, flags, fsst, err = mkrfs(addr) } if err != nil { return nil, nil, err } switch { case nocache: dbg.Warn("%s: uncached", addr) if xaddr != "" { rfs.Server(fs, xaddr) } fn := func() {} if sflag { fn = func() { fsst.Averages() dbg.Warn("%s iostats:\n%s\n", fs.Name(), fsst) } } return fs, fn, nil case lfscache != "": dbg.Warn("%s: lfs cache %s", addr, lfscache) m, lflags, err = dcache() case mlfscache != "": dbg.Warn("%s: mdfs cache %s", addr, mlfscache) m, lflags, err = mdcache() default: dbg.Warn("%s: mfs cache", addr) m, lflags, err = mcache() } if err != nil { return nil, nil, err } cfs.Debug = zxdebug xfs, err := cfs.New("cfs", m, fs, rflag) if err != nil { return nil, nil, fmt.Errorf("cfs: %s", err) } xfs.Flags.Add("rdebug", &flags.Dbg) if lflags != nil { xfs.Flags.Add("ldebug", &lflags.Dbg) } xfs.Flags.Add("fdebug", &zxfs.Debug) xfs.Flags.Add("vdebug", dbp) xfs.Flags.Set("verbsync", !quiet) st := &zx.IOstats{} xfs.IOstats = st if xaddr != "" { rfs.Server(xfs, xaddr) } fn := func() {} if sflag { fn = func() { st.Averages() dbg.Warn("%s iostats:\n%s\n", xfs.Name(), st) fsst.Averages() dbg.Warn("%s iostats:\n%s\n", fs.Name(), fsst) } } return xfs, fn, nil }