Пример #1
0
// no locks, used only at init time
func (t *Fs) reloadChild(f *mFile) {
	ds, err := zx.GetDir(t.lfs, f.d["path"])
	if err != nil {
		dbg.Warn("%s: reload: %s", t.name, err)
		return
	}
	for _, d := range ds {
		if d["path"] == "/Ctl" || d["path" ] == "/Chg" {
			continue
		}
		cf := &mFile{
			name: d["name"],
			d: zx.Dir{
				"name": d["name"],
				"path": d["path"],
				"spath": d["path"],
				"tpath": t.path,
				"type": d["type"],
				"Wuid": d["Wuid"],
				"Sum": d["Sum"],
			},
		}
		for k, v := range d.UsrAttrs() {
			cf.d[k] = v
		}
		f.child = append(f.child, cf)
		if cf.d["type"] == "d" {
			t.reloadChild(cf)
		}
	}
}
Пример #2
0
func chkdirs(t Fataler, fs zx.Tree, d zx.Dir, recur bool) {
	if d["path"] == "" {
		t.Fatalf("no path in <%s>", d)
	}
	if d["type"] != "d" {
		return
	}
	dents, err := zx.GetDir(fs, d["path"])
	if err != nil {
		t.Fatalf("getdir: %s: %s", d["path"], err)
	}
	if d["size"] != fmt.Sprintf("%d", len(dents)) {
		t.Logf("%s: size %s len(dents) %d", d["path"], d["size"], len(dents))
		t.Logf("d: %s\n", d.Long())
		for _, cd := range dents {
			t.Logf("\t%s\n", cd.Long())
		}
		t.Fatalf("bad dir size")
	}
	if recur {
		for _, cd := range dents {
			chkdirs(t, fs, cd, true)
		}
	}
}
Пример #3
0
/*
	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
}
Пример #4
0
func GetDir(path string) ([]zx.Dir, error) {
	if len(path) > 0 && path[0] == '#' {
		return nil, fmt.Errorf("%s: %s", path, dbg.ErrPerm)
	}
	path = app.AbsPath(path)
	_, trs, spaths, err := app.ResolveTree(path)
	if err != nil {
		return nil, err
	}
	return zx.GetDir(trs[0], spaths[0])
}
Пример #5
0
// read (or re-read) dir data and update children stats.
// The hash attribute of the file is updated with the sha1 for the data,
// but it's not written to the underlying file.
/// zd is locked by caller.
func (zd *Dir) getDir() error {
	zd.zprintf("Lget", "readdir")
	ds, err := zx.GetDir(zd.z.fs, zd.path)
	if err != nil {
		zd.dprintf("get", err)
		return err
	}
	names := []string{}
	nchild := make(map[string]*Dir, len(ds))
	firstread := zd.child == nil
	for i := 0; i < len(ds); i++ {
		cd := ds[i]
		cname := cd["name"]
		if cname=="" || cname=="." || cname==".." || cname==".#zx" {
			continue
		}
		zcd, ok := zd.child[cname]
		if ok && !zcd.ghost {
			zcd.Lock()
			// and must post an update only if zcd changes
			mchg, dchg, _ := zcd.stated("getdir", cd, nil)
			if mchg || dchg {
				zd.z.changed(zcd)
			}
			zcd.Unlock()
			delete(zd.child, cname)
		} else {
			zcd = zd.z.newDir(cd)
			zcd.parent = zd
			zcd.refreshMeta()
			if !firstread {
				zcd.RLock()
				zd.z.changed(zcd)
				zcd.RUnlock()
			}
		}
		if !zcd.ghost {
			nchild[cname] = zcd
			names = append(names, cname)
		}
	}
	for _, zcd := range zd.child {
		zcd.Lock()
		zcd.kill("readdir")
		zd.z.changed(zcd)
		zcd.Unlock()
	}
	zd.child = nchild

	osum := zd.d["Sum"]
	sort.Sort(sort.StringSlice(names))
	h := sha1.New()
	for _, n := range names {
		h.Write([]byte(n))
	}
	sum := h.Sum(nil)
	zd.d["Sum"] = fmt.Sprintf("%040x", sum)
	zd.refreshData()
	if osum != zd.d["Sum"] {
		zd.wstatAttrs("Sum")
	}
	return nil
}
Пример #6
0
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)
}
Пример #7
0
func dump(dir string, t zx.Tree, ec chan bool) {
	defer func() {
		ec <- true
	}()
	name := t.Name()
	data := zx.Path(dir, "data")
	doskip := Skip
	for {
		if doskip {
			waitDumpTime(name)
			doskip = false
			continue
		}
		dbg.Warn("snap %s...", name)
		if err := os.MkdirAll(data, 0750); err != nil {
			dbg.Warn("%s: %s", data, err)
			return
		}
		rd, err := zx.Stat(t, "/")
		if err != nil {
			dbg.Warn("%s: %s", name, err)
			continue
		}
		// make sure it's not empty
		ds, err := zx.GetDir(t, "/")
		if err != nil {
			dbg.Warn("%s: %s", name, err)
			continue
		}
		if len(ds) == 0 {
			dbg.Warn("%s: file system is empty. ignored.", name)
			continue
		}
		s, err := dumpDir(data, name, zx.File{t, rd})
		if err != nil {
			dbg.Warn("%s: %s", name, err)
		}
		ts := time.Now().Format("2006/0102")
		tree := strings.Replace(name, "/", ".", -1)
		tspath0 := zx.Path(dir, tree, ts)
		os.MkdirAll(path.Dir(tspath0), 0755)
		spath := zx.Path(data, s)
		tspath := tspath0
		for i := 1; ; i++ {
			fi, _ := os.Stat(tspath)
			if fi == nil {
				break
			}
			tspath = fmt.Sprintf("%s.%d", tspath0, i)
		}
		os.MkdirAll(path.Dir(tspath), 0755)
		if err := os.Symlink(spath, tspath); err != nil {
			dbg.Warn("%s: %s", name, err)
		}
		dbg.Warn("snap %s %s", tspath, s)
		if Once {
			break
		}
		waitDumpTime(name)
	}
}
Пример #8
0
// 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)
	}

}