func Gets(t Fataler, fss ...zx.Tree) { for i := 0; i < Repeats; i++ { for _, fs := range fss { for _, p := range GetFPaths { printf("getall %s\n", p) dat, err := zx.GetAll(fs, p) if err != nil { t.Fatalf("get %s: %s", p, err) } printf("got %d bytes \n\n", len(dat)) if string(dat) != string(FileData[p]) { printf("got <%s>\nexpected<%s>\n", string(dat), string(FileData[p])) t.Fatalf("%s: bad data", p) } } for _, p := range GetDPaths { printf("getall %s\n", p) dat, err := zx.GetAll(fs, p) if err != nil { t.Fatalf("get %s: %s", p, err) } var d zx.Dir ents := []string{} for len(dat) > 0 { d, dat, err = zx.UnpackDir(dat) if err != nil { t.Fatalf("dir: %s", err) } if d["path"] == "/Ctl" || d["path"] == "/Chg" { continue } ents = append(ents, d.TestFmt()) } if strings.Join(GetDOuts[p], "\n") != strings.Join(ents, "\n") { t.Fatalf("bad dir data for %s", p) } printf("got %d ents (ctl, chg excluded)\n", len(ents)) } for _, p := range BadPaths { dat, err := zx.GetAll(fs, p) if err==nil || len(dat)>0 { t.Fatalf("get %s didn't fail", p) } } printf("\n") } } }
func main() { opts := opt.New("[file]") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) rdonly := false opts.NewFlag("r", "read only", &rdonly) opts.NewFlag("e", "do edits for testing", &doedits) cmd.UnixIO("err") args := opts.Parse() var t *ink.Txt inkout := cmd.Out("ink") if inkout == nil { cmd.UnixIO() } if len(args) == 0 { t = ink.NewTxt("1234", "abc") } else { dat, err := zx.GetAll(cmd.NS(), cmd.AbsPath(args[0])) if err != nil { cmd.Fatal(err) } t = ink.NewTxt(args[0]+" Del", string(dat)) } go edit(t) if rdonly { t.NoEdits() } ink.UsePort("8182") bs := ink.NewButtonSet(&ink.Button{Tag: "One", Name: "one"}, &ink.Button{Tag: "Two", Name: "two"}, &ink.Button{Tag: "B", Name: "b", Value: &bold}, &ink.Button{Tag: "I", Name: "i", Value: &italic}) rs := ink.NewRadioSet(&style, &ink.Button{Tag: "R", Name: "r"}, &ink.Button{Tag: "T", Name: "t"}) go buttons(bs, rs, t) pg := ink.NewPg("/", "Example text editing:", bs, rs, t) pg.Tag = "Clive's iedit" if doedits { go edits(t) } go ink.Serve() if inkout != nil { // TODO: ctlrs must use unique ids sytem-wide, or // controls written won't work because of their ids. inkout <- []byte(`<tt>Hi there, this is HTML</tt>`) var buf bytes.Buffer bs.WriteTo(&buf) inkout <- buf.Bytes() inkout <- []byte("https://localhost:8182") } t.Wait() for rs := range t.Get(0, -1) { cmd.Printf("%s", string(rs)) } }
// zx.GetAll using the app ns and dot. func GetAll(path string) ([]byte, error) { if len(path) > 0 && path[0] == '#' { return nchan.Bytes(Get(path, 0, -1, "")) } path = app.AbsPath(path) _, trs, spaths, err := app.ResolveTree(path) if err != nil { return nil, err } return zx.GetAll(trs[0], spaths[0]) }
func GetCtl(t Fataler, xfs zx.Fs) { fs, ok := xfs.(zx.Getter) if !ok { t.Fatalf("not a getter") } dat, err := zx.GetAll(fs, "/Ctl") if err != nil { t.Fatalf("get /Ctl: %s", err) } Printf("ctl is:\n%s\n", string(dat)) }
func (fs *Cfs) getCtl(off, count int64, pred string, c chan<- []byte, cs *zx.CallStat) (int, error) { var buf bytes.Buffer fmt.Fprintf(&buf, "%s:\n", fs.Name()) users := fs.Users() for _, k := range users { fmt.Fprintf(&buf, "user\t%s\n", k) } fmt.Fprintf(&buf, "%s", fs.Flags) fs.IOstats.Averages() fmt.Fprintf(&buf, "%s\n", fs.IOstats.String()) lctl, _ := zx.GetAll(fs.lfs, "/Ctl") if len(lctl) > 0 { buf.Write(lctl) } rctl, _ := zx.GetAll(fs.rfs, "/Ctl") if len(rctl) > 0 { buf.Write(rctl) } resp := buf.Bytes() o := int(off) if o >= len(resp) { o = len(resp) } resp = resp[o:] n := int(count) if n > len(resp) || n < 0 { n = len(resp) } resp = resp[:n] cs.Send(int64(len(resp))) c <- resp return n, nil }
func EqFiles(t Fataler, path string, fss ...zx.Tree) { dirs := []zx.Dir{} nerrs := 0 for _, fs := range fss { d, err := zx.Stat(fs, path) if err != nil { printf("%s: not there: %s\n", fs.Name(), err) nerrs++ continue } printf("%s: %s\n", fs.Name(), d.LongTestFmt()) dirs = append(dirs, d) } if nerrs > 0 { if nerrs != len(fss) { t.Fatalf("exists only in some") } return } for i := 1; i < len(dirs); i++ { if dirs[i].TestFmt() != dirs[0].TestFmt() { t.Logf("dir%d %s\n", i, dirs[i].TestFmt()) t.Logf("dir0 %s\n", dirs[0].TestFmt()) t.Fatalf("dirs do not match") } } if dirs[0]["type"] == "d" { return } datas := [][]byte{} for _, fs := range fss { dat, err := zx.GetAll(fs, path) if err != nil { t.Fatalf("%s: %s: %s", fs, path, err) } datas = append(datas, dat) } for i := 1; i < len(datas); i++ { if bytes.Compare(datas[i], datas[0]) != 0 { t.Fatalf("data differs") } } }
func Puts(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := fss[0].(zx.RWTree) rd, err := zx.Stat(fs, "/") if err != nil { t.Fatalf("root stat %s", err) } printf("root %s\n", rd.TestFmt()) for z := 0; z < Repeats; z++ { Loop: for nfi, nf := range PutTests { dc := make(chan []byte, 1) nf.data = make([]byte, 0, 32*1024) xd := nf.Dir.Dup() printf("put %s %v\n", nf.Path, xd) nn := nfi + 1 if nf.N != 0 { nn = 2 } xc := fs.Put(nf.Path, xd, 0, dc, "") for i := 0; i < 1000*nn; i++ { msg := []byte(fmt.Sprintf("hi %s %d\n", nf.Path, i)) nf.data = append(nf.data, msg...) if ok := dc <- msg; !ok { err := cerror(dc) if !nf.Fails { t.Fatalf("%s: %s\n", nf.Path, err) } continue Loop } } printf("put %s: sent %d bytes\n", nf.Path, len(nf.data)) close(dc) xd = <-xc if nf.Fails { if xd!=nil || cerror(xc)==nil { t.Fatalf("%s: didn't fail", nf.Path) } continue } if xd==nil || cerror(xc)!=nil { t.Fatalf("%s: %s\n", nf.Path, cerror(xc)) } got := xd.TestFmt() printf("got %s\n", got) if nf.Dir["mtime"] != "" { got += " mtime " + xd["mtime"] } if got != nf.Res { t.Logf("expected %s\n", nf.Res) t.Logf("got %s\n", got) t.Fatalf("%s: bad dir output", nf.Path) } fd, err := zx.Stat(fs, nf.Path) if err != nil { t.Fatalf("stat: %s", err) } got = fd.TestFmt() if nf.Dir["mtime"] != "" { got += " mtime " + fd["mtime"] } if nf.Dir["X"] != "" { got += " X " + fd["X"] } printf("after put: %s\n", got) if nf.Rdir != "" && nf.Rdir != got { t.Logf("expected <%s>", nf.Rdir) t.Fatalf("got <%s>", got) } for _, fs := range fss { dat, err := zx.GetAll(fs, nf.Path) if err != nil { t.Fatalf("couldn't get: %s", err) } if nf.N != 0 && len(dat) != nf.N { t.Fatalf("bad output size: %d", len(dat)) } if nf.N != 0 && len(dat) > len(nf.data) { dat = dat[:len(nf.data)] } if nf.N != 0 && len(dat) < len(nf.data) { nf.data = nf.data[:len(dat)] } if string(dat) != string(nf.data) { t.Fatalf("bad data %d vs %d bytes", len(dat), len(nf.data)) } } } } } func GetCtl(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := fss[0].(zx.RWTree) vals := []bool{false, true} outs := []string{"debug off", "debug on"} for i, v := range vals { d := fs.(zx.Debugger).Debug() *d = v printf("get ctl: (debug %v)\n", v) dat, err := zx.GetAll(fs, "/Ctl") if err != nil { t.Fatalf("get /ctl: %s", err) } ctls := string(dat) printf("<%s>\n\n", ctls) if !strings.Contains(ctls, outs[i]) { t.Fatalf("wrong ctl output") } } } func PutCtl(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := fss[0].(zx.RWTree) vals := []bool{false, true, false, true} ins := []string{"nodebug", "debug", "debug off", "debug on"} outs := []string{"debug off", "debug on", "debug off", "debug on"} for i, v := range vals { printf("put ctl: (debug %v)\n", v) err := zx.PutAll(fs, "/Ctl", nil, []byte(ins[i])) if err != nil { t.Fatalf("put /ctl: %s", err) } printf("get ctl: (debug %v)\n", v) dat, err := zx.GetAll(fs, "/Ctl") if err != nil { t.Fatalf("get /ctl: %s", err) } ctls := string(dat) printf("<%s>\n\n", ctls) if !strings.Contains(ctls, outs[i]) { t.Fatalf("wrong ctl output") } } err := zx.PutAll(fs, "/Ctl", nil, []byte("bad ctl request")) if err == nil { t.Fatalf("bad put did not fail") } printf("put sts %s\n", err) } func PutsBench(b *testing.B, xfs zx.Tree) { fs := xfs.(zx.RWTree) b.StopTimer() var buf [1024]byte copy(buf[0:], "hola") <-fs.Remove("/nfb") b.StartTimer() for bi := 0; bi < b.N; bi++ { dc := make(chan []byte) xc := fs.Put("/nfb", zx.Dir{"mode": "0644"}, 0, dc, "") for i := 0; i < 128; i++ { if ok := dc <- buf[:]; !ok { b.Fatalf("put failed") } } close(dc) if len(<-xc) == 0 { b.Fatalf("put failed") } } } var ( MkdirPaths = []string{"/nd", "/nd/nd2", "/nd/nd22", "/nd/nd23", "/nd3"} BadMkdirPaths = []string{"/", "/nd", "/a"} ) func Mkdirs(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := fss[0].(zx.RWTree) for i := 0; i < Repeats; i++ { for _, p := range MkdirPaths { printf("mkdir %s\n", p) ec := fs.Mkdir(p, zx.Dir{"mode": "0750"}) err := <-ec if i>0 && err==nil { t.Fatalf("could re-mkdir %s", p) } if i==0 && err!=nil { t.Fatalf("%s: %s", p, err) } for _, fs := range fss { d, err := zx.Stat(fs, p) if err!=nil || d["type"]!="d" || d["mode"]!="0750" { t.Fatalf("mkdir not there %v %v", err, d) } } } for _, p := range BadMkdirPaths { printf("mkdir %s\n", p) ec := fs.Mkdir(p, zx.Dir{"mode": "0750"}) err := <-ec if err == nil { t.Fatalf("mkdir %s worked", p) } } } } var ( RemovePaths = []string{"/d", "/e/f", "/e", "/a/a2"} BadRemovePaths = []string{"/", "/xxx", "/a"} ) func Removes(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := fss[0].(zx.RWTree) for i := 0; i < Repeats; i++ { for _, p := range RemovePaths { printf("remove %s\n", p) ec := fs.Remove(p) err := <-ec if i>0 && err==nil { t.Fatalf("could re-remove %s", p) } if i==0 && err!=nil { t.Fatalf("%s: %s", p, err) } for _, fs := range fss { d, err := zx.Stat(fs, p) if err==nil || d!=nil { t.Fatalf("%s still there", p) } } } for _, p := range BadRemovePaths { ec := fs.Remove(p) err := <-ec if err == nil { t.Fatalf("remove %s worked", p) } } } } func MkdirRemoveBench(b *testing.B, xfs zx.Tree) { fs := xfs.(zx.RWTree) b.StopTimer() <-fs.Remove("/mrb") b.StartTimer() for bi := 0; bi < b.N; bi++ { xc := fs.Mkdir("/mrb", zx.Dir{"mode": "0755"}) if <-xc != nil { b.Fatalf("mkdir failed") } xc = fs.Remove("/mrb") if <-xc != nil { b.Fatalf("remove failed") } } } type WstatTest { Path string Dir zx.Dir AppDir bool Res string Fails bool } var WstatTests = []WstatTest{ { Path: "/d", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Res: `path /d name d type d mode 0704 size 0`, }, { Path: "/e/f", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Res: `path /e/f name f type d mode 0704 size 0`, }, { Path: "/e", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Res: `path /e name e type d mode 0704 size 1`, }, { Path: "/a/a2", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Res: `path /a/a2 name a2 type - mode 0704 size 21418`, }, { Path: "/", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Res: `path / name / type d mode 0704 size 0`, }, { Path: "/xxx", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Fails: true, }, { Path: "/a/xxx", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Fails: true, }, { Path: "/dx", Dir: zx.Dir{"mode": "0704", "foo": "bar"}, Fails: true, }, } func Wstats(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := fss[0].(zx.RWTree) for i := 0; i < Repeats; i++ { for _, f := range WstatTests { printf("wstat %s %v\n", f.Path, f.Dir) ec := fs.Wstat(f.Path, f.Dir) err := <-ec if f.Fails { if err == nil { t.Fatalf("%s didn't fail", f.Path) } continue } if !f.Fails && err!=nil { t.Fatalf("%s: %s", f.Path, err) } for _, fs := range fss { d, err := zx.Stat(fs, f.Path) if err != nil { t.Fatalf("stat %s: %s", f.Path, err) } if d["path"] == "/" { d["size"] = "0" // ctl, chg } if d.TestFmt() != f.Res { t.Logf("for %s\n", fs.Name()) t.Logf("expected %s\n", f.Res) t.Logf("got %s\n", d.TestFmt()) t.Fatalf("stat %s: didn't wstat it", f.Path) } } } } } var UsrWstatTests = []WstatTest{ // extra bits in mode { Path: "/a", Dir: zx.Dir{"mode": "07755"}, Res: `path /a name a type d mode 0755 size 3 Gid nemo Uid nemo Wuid nemo`, }, // changing size in a dir is ignored if writing existing attributes. { Path: "/a", Dir: zx.Dir{"size": "5"}, AppDir: true, Res: `path /a name a type d mode 0755 size 3 Gid nemo Uid nemo Wuid nemo`, }, // writing a non user attribute { Path: "/a", Dir: zx.Dir{"foo": "bar"}, Fails: true, }, // writing a ignored non user attribute { Path: "/a", Dir: zx.Dir{"mtime": "0", "foo": "bar"}, Res: `path /a name a type d mode 0755 size 3 Gid nemo Uid nemo Wuid nemo`, }, // Adding a user attribute { Path: "/a", Dir: zx.Dir{"Dir": "X"}, Res: `path /a name a type d mode 0755 size 3 Dir X Gid nemo Uid nemo Wuid nemo`, }, // Same, using the previous dir { Path: "/a", Dir: zx.Dir{"Dir": "X"}, AppDir: true, Res: `path /a name a type d mode 0755 size 3 Dir X Gid nemo Uid nemo Wuid nemo`, }, // Adding a two user attributes { Path: "/a", Dir: zx.Dir{"Dir": "X", "Abc": "A"}, Res: `path /a name a type d mode 0755 size 3 Abc A Dir X Gid nemo Uid nemo Wuid nemo`, }, // Removing a non existing user attribute { Path: "/a", Dir: zx.Dir{"Non": ""}, Res: `path /a name a type d mode 0755 size 3 Abc A Dir X Gid nemo Uid nemo Wuid nemo`, }, // Rewriting a user attribute { Path: "/a", Dir: zx.Dir{"Abc": "B"}, Res: `path /a name a type d mode 0755 size 3 Abc B Dir X Gid nemo Uid nemo Wuid nemo`, }, // Removing a user attribute { Path: "/a", Dir: zx.Dir{"Abc": ""}, Res: `path /a name a type d mode 0755 size 3 Dir X Gid nemo Uid nemo Wuid nemo`, }, // Type change { Path: "/a", Dir: zx.Dir{"type": "x"}, Fails: true, }, // Removing a sys attribute { Path: "/a", Dir: zx.Dir{"type": "", "Dir": "X"}, Fails: true, }, // Trying to change size { Path: "/a", Dir: zx.Dir{"size": "55"}, Fails: true, }, // Bad path { Path: "2", Dir: zx.Dir{"size": "55"}, Fails: true, }, // Truncating a file { Path: "/2", Dir: zx.Dir{"size": "55"}, Res: `path /2 name 2 type - mode 0644 size 55 Gid nemo Uid nemo Wuid nemo`, }, } func UsrWstats(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := fss[0].(zx.RWTree) for i := 0; i < 1; i++ { for _, f := range UsrWstatTests { d := f.Dir.Dup() if f.AppDir { od, err := zx.Stat(fs, f.Path) if err != nil { t.Fatalf("stat %s: %s", f.Path, err) } for k, v := range d { od[k] = v } d = od } printf("wstat %s %s\n", f.Path, d.LongTestFmt()) ec := fs.Wstat(f.Path, d) err := <-ec if f.Fails { if err == nil { t.Fatalf("%s didn't fail", f.Path) } continue } if !f.Fails && err!=nil { t.Fatalf("%s: %s", f.Path, err) } for _, fs := range fss { d, err := zx.Stat(fs, f.Path) if err != nil { t.Fatalf("stat %s: %s", f.Path, err) } printf("result %s %s\n", f.Path, d.LongTestFmt()) if d["foo"] != "" { t.Fatalf("could write foo") } if f.Res == "" { continue } if d["path"] == "/" { d["size"] = "0" // ctl, chg } delete(d, "Sum") ds := strings.Replace(d.LongTestFmt(), "nemo", "none", -1) ds2 := strings.Replace(f.Res, "nemo", "none", -1) if ds != ds2 { t.Logf("for fs %s\n", fs.Name()) t.Logf("expected %s\n", f.Res) t.Logf("got %s\n", d.LongTestFmt()) t.Fatalf("stat %s: didn't wstat it", f.Path) } } } } } func WstatBench(b *testing.B, xfs zx.Tree) { fs := xfs.(zx.RWTree) for bi := 0; bi < b.N; bi++ { xc := <-fs.Wstat("/e", zx.Dir{"mode": "0755"}) if xc != nil { b.Fatalf("wstat failed") } } } var SendOuts = []string{ `/`, `path /1 name 1 type - mode 0644 size 0`, `path /2 name 2 type - mode 0644 size 31658`, `path /a name a type d mode 0755 size 3`, `path /a/a1 name a1 type - mode 0644 size 10154`, `path /a/a2 name a2 type - mode 0644 size 21418`, `path /a/b name b type d mode 0755 size 1`, `path /a/b/c name c type d mode 0755 size 1`, `path /a/b/c/c3 name c3 type - mode 0644 size 44970`, `path /d name d type d mode 0755 size 0`, `path /e name e type d mode 0755 size 1`, `path /e/f name f type d mode 0755 size 0`, } func SendRecv(t Fataler, sfs, rfs zx.RWTree) { dc := make(chan []byte) rf, err := zx.Stat(sfs, "/") if err!=nil || rf==nil { t.Fatalf("stat: %s", err) } zx.DebugSend = testing.Verbose() go func() { err := zx.Send(sfs, rf, dc) close(dc, err) }() err = zx.Recv(rfs, dc) if cerror(dc) != nil { t.Logf("send err %s", cerror(dc)) } if err != nil { t.Fatalf("recv: %s", err) } err = cerror(dc) if err != nil { t.Fatalf("send: %s", err) } fc := rfs.Find("/", "", "/", "/", 0) tot := 0 outs := []string{} for d := range fc { printf("\t`%s`,\n", d.LongTestFmt()) if d["path"] == "/" { outs = append(outs, "/") tot++ continue } if d["path"] == "/" { d["size"] = "0" // get rid of ctl, chg } if d["path"]=="/Ctl" || d["path"]=="/Chg" { continue } tot++ outs = append(outs, d.TestFmt()) } if tot != 12 { t.Fatalf("bad find tot: got %d", tot) } if strings.Join(outs, "\n") != strings.Join(SendOuts, "\n") { t.Fatalf("bad received tree") } } // Check out if fs.Dump() is the same for all trees func SameDump(t Fataler, fss ...zx.Tree) { old := "" oname := "" nname := "" for _, tfs := range fss { var buf bytes.Buffer fs, ok := tfs.(zx.Dumper) if !ok { continue } fs.Dump(&buf) ns := buf.String() toks := strings.SplitN(ns, "\n", 2) if len(toks) > 1 { ns = toks[1] nname = toks[0] } if old == "" { old = ns oname = nname } else if old != ns { t.Logf("%s\n<%s>\n", oname, old) t.Logf("%s\n<%s>\n", nname, ns) i := 0 for i < len(old) && i < len(ns) { if old[i] != ns[i] { break } i++ } t.Logf("suffix1 <%s>\n", old[i:]) t.Logf("suffix2 <%s>\n", ns[i:]) t.Fatalf("trees do not match") } } }
func Gets(t Fataler, xfs zx.Fs) { fs, ok := xfs.(zx.Getter) if !ok { t.Fatalf("not a getter") } for _, p := range Files { data, err := zx.GetAll(fs, p) Printf("get all %s: %d bytes sts %v\n", p, len(data), err) if err != nil { t.Fatalf("get %s: %s", p, err) } if bytes.Compare(FileData[p], data) != 0 { t.Logf("%d get %d data", len(data), len(FileData[p])) t.Fatalf("get %s: bad data", p) } } for _, p := range Files { data, err := get(fs, p, 1024, 10*1024) Printf("get %s 1k 2k: %d bytes sts %v\n", p, len(data), err) if err != nil { t.Fatalf("get %s: %s", p, err) } if bytes.Compare(slice(FileData[p], 1024, 10*1024), data) != 0 { t.Fatalf("get %s: bad data", p) } } for i, p := range Dirs { Printf("get %s\n", p) out := "" gc := fs.Get(p, 0, -1) for b := range gc { _, dir, err := zx.UnpackDir(b) Printf("%s\n", dir.Fmt()) if err != nil { t.Fatalf("get sts %v", err) } out += dir.Fmt() + "\n" } Printf("\n") if i > len(dirs) || dirs[i] != out { t.Logf("dirs: <%s>\n out <%s>\n", dirs, out) t.Fatalf("bad output") } } for i, p := range Dirs { Printf("get %s 2 3\n", p) out := "" gc := fs.Get(p, 2, 3) for b := range gc { _, dir, err := zx.UnpackDir(b) Printf("%s\n", dir.Fmt()) if err != nil { t.Fatalf("get sts %v", err) } out += dir.Fmt() + "\n" } Printf("\n") if i > len(dirs23) || dirs23[i] != out { t.Fatalf("bad dir contents") } if err := cerror(gc); err != nil { t.Fatalf("err %v", err) } } for _, p := range BadPaths[1:] { data, err := zx.GetAll(fs, p) Printf("get %s: %s\n", p, err) if err == nil || len(data) > 0 { t.Fatalf("could get") } } }
func dumpDir(dir, name string, rf zx.File) (string, error) { dprintf("dump dir %s %s %s\n", dir, name, rf.D["path"]) ds := []zx.Dir{} istmp := rf.D["name"] == "tmp" if !istmp { var err error ds, err = zx.GetDir(rf.T, rf.D["path"]) if err != nil { dbg.Warn("dumpdir: %s: %s", rf.D["path"], err) return "", err } } else { vprintf("%s: temp %s\n", os.Args[0], name) } dhash := []string{} nds := []zx.Dir{} for _, d := range ds { if d["name"] == "" { dbg.Warn("dumpdir: %s: no name", rf.D["path"]) } if d["name"] == "NODUMP" { nds = []zx.Dir{} dbg.Warn("dumpdir: %s: no dump", rf.D["path"]) break } if d["name"] == "FROZEN" { vprintf("%s: XXX frozen %s\n", os.Args[0], name) /* dir is frozen and the FROZEN contains * the dump path for dir. */ data, err := zx.GetAll(rf.T, d["path"]) if err != nil { return "", err } s := string(data) if len(strings.Split(s, "/")) != 3 { return "", fmt.Errorf("wrong contents in %s", d["path"]) } vprintf("%s: frozen %s\n", os.Args[0], name) return strings.TrimSpace(s), nil } if excluded(d["name"]) { dprintf("dump ignored %s\n", d["path"]) continue } if t := d["type"]; t != "d" && t != "-" { dbg.Warn("dump ignored %s type '%s'\n", d["path"], t) continue } nds = append(nds, d) } ds = nds for _, d := range ds { dspath := zx.Path(name, d["name"]) df, err := zx.Walk(rf.T, rf.D, d["name"]) if dspath == name { panic("zx dump bug") } if err != nil { dbg.Warn("walk: %s: %s", df["path"], err) dhash = append(dhash, "") dhash = append(dhash, "") continue } var s string var e error switch d["type"] { case "d": s, e = dumpDir(dir, dspath, zx.File{rf.T, df}) case "-": s, e = dumpFile(dir, dspath, zx.File{rf.T, df}) default: panic("dump dir type bug") } if e == nil { dhash = append(dhash, d["name"]) dhash = append(dhash, s) } else { dbg.Warn("%s: %s", df["path"], e) } if err == nil && e != nil { err = e dhash = append(dhash, "") dhash = append(dhash, "") } } dval := strings.Join(dhash, "\n") h := sha1.New() h.Write([]byte(dval)) sum := h.Sum(nil) s := fmt.Sprintf("%02x/%02x/%036x", sum[0], sum[1], sum[2:]) dprintf("dump dir %s %s\n", name, s) dfpath := zx.Path(dir, s) fi, _ := os.Stat(dfpath) if fi != nil { return s, nil } vprintf("%s: new %s\n", os.Args[0], name) return s, newDumpDir(dir, dfpath, rf, ds, dhash) }
func rget(t Fataler, fs zx.RWTree, fname string) { zx.GetAll(fs, fname) }
// Check that perms are actually checked in old files and dirs func RWXPerms(t Fataler, fss ...zx.Tree) { if len(fss) == 0 { t.Fatalf("no fs given") } fs := authfs(t, fss[0].(zx.RWTree)) if <-fs.Mkdir("/chkd", zx.Dir{"mode": "0777", "Gid": "gid1"}) != nil { t.Fatalf("couldn't mkdir /chkd gid") } if <-fs.Mkdir("/chkd/o", zx.Dir{"mode": "0777", "Gid": "gid1"}) != nil { t.Fatalf("couldn't mkdir /chkd gid") } // Check out dirs rfn := func(fs zx.RWTree) error { _, err := zx.GetDir(fs, "/chkd") return err } out := ugo(t, fs, "/chkd", 4, rfn) printf("dir rd ugo: %s\n", out) if out != "yyyyynynnnnn" { t.Fatalf("dir read perms are %s", out) } wfn := func(fs zx.RWTree) error { err := <-fs.Mkdir("/chkd/x", zx.Dir{"mode": "0777"}) if err != nil { return err } return <-fs.Remove("/chkd/x") } out = ugo(t, fs, "/chkd", 2, wfn) printf("dir wr ugo: %s\n", out) if out != "yyyyynynnnnn" { t.Fatalf("dir write perms are %s", out) } xfn := func(fs zx.RWTree) error { _, err := zx.GetDir(fs, "/chkd/o") return err } out = ugo(t, fs, "/chkd", 1, xfn) printf("dir ex ugo: %s\n", out) if out != "yyyyynynnnnn" { t.Fatalf("dir exec perms are %s", out) } // Check out files if err := zx.PutAll(fs, "/chkf", zx.Dir{"mode": "0777"}, []byte("hi")); err != nil { t.Fatalf("put: %s", err) } if err := <-fs.Wstat("/chkf", zx.Dir{"Gid": "gid1"}); err != nil { t.Fatalf("wstat: %s", err) } rfn = func(fs zx.RWTree) error { _, err := zx.GetAll(fs, "/chkf") return err } out = ugo(t, fs, "/chkf", 4, rfn) printf("file rd ugo: %s\n", out) if out != "yyyyynynnnnn" { t.Fatalf("file read perms are %s", out) } wfn = func(fs zx.RWTree) error { return zx.PutAll(fs, "/chkf", nil, []byte("there")) } out = ugo(t, fs, "/chkf", 2, wfn) printf("file wr ugo: %s\n", out) if out != "yyyyynynnnnn" { t.Fatalf("file write perms are %s", out) } // We can't check out exec perms, because the underlying OS has // its own idea of who can exec the file. // see who can change modes. m := 0 wfn = func(fs zx.RWTree) error { m++ return <-fs.Wstat("/chkf", zx.Dir{"mode": fmt.Sprintf("0%o", m)}) } out = ugo(t, fs, "/chkf", 2, wfn) printf("file wstat ugo: %s\n", out) if out != "ynnynnynnynn" { t.Fatalf("file wstat perms are %s", out) } }