Example #1
0
// Walk to the given rid checking out perms when t.ai is not nil.
// Returns also the gid and mode even when no perms are checked.
func (t *Lfs) canWalkTo(rid string, forwhat int) (string, uint64, error) {
	if !t.readattrs || rid == "/Ctl" {
		return dbg.Usr, 0777, nil
	}
	noperm := t.NoPermCheck || t.ai == nil
	elems := zx.Elems(rid)
	fpath := t.path
	pgid := ""
	var pmode uint64
	if len(elems) == 0 {
		elems = append(elems, "/")
	}
	for len(elems) > 0 {
		if noperm {
			// skip to just the final step
			if len(elems) > 1 {
				fpath = zx.Path(t.path, path.Dir(rid))
				elems = elems[len(elems)-1:]
			}
		}
		pd := zx.Dir{
			"name": elems[0],
		}
		fpath = zx.Path(fpath, elems[0])
		elems = elems[1:]

		st, err := os.Stat(fpath)
		if err != nil {
			return "", 0, err
		}
		mode := st.Mode()
		m := int64(mode & 0777)
		pd["mode"] = "0" + strconv.FormatInt(m, 8)
		t.fileAttrs(fpath, pd)
		if !noperm && len(elems) > 0 && !pd.CanWalk(t.ai) {
			return "", 0, dbg.ErrPerm
		}
		if len(elems) == 0 {
			pgid = pd["Gid"]
			pmode = uint64(pd.Int("mode"))
		}
		if !noperm && len(elems) == 0 && forwhat != 0 {
			if !pd.Can(t.ai, forwhat) {
				return "", 0, dbg.ErrPerm
			}
		}
	}
	if pgid == "" {
		pgid = dbg.Usr
	}
	if pmode == 0 {
		pmode = 0775
	}
	return pgid, pmode, nil
}
Example #2
0
// 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
}
Example #3
0
// Compare d with the previous info in zd, and refresh its
// metadata, perhaps invalidating the data. Returns true
// if there is any change in data or metadata.
// this does not can changed(), the caller should do that.
func (zd *Dir) stated(from string, d zx.Dir, err error) (mchanged, dchanged bool, rerr error) {
	pzd := zd.parent
	if zd.path=="/Ctl" || zd.path=="/Chg" {
		return false, false, nil
	}
	if d==nil || d["rm"]!="" {
		if zd.ghost {
			zd.d["rm"] = "y" // safety first, but it's ok
			return false, false, dbg.ErrNotExist
		}
		zd.kill(from)
		if pzd!=nil && zd.epoch==0 {
			pzd.invalData() // cause a re-read.
		}
		return true, true, err
	}
	dchanged = zd.ghost
	zd.ghost = false
	mchanged = dchanged
	if mchanged {
		zd.cprintf(zd.path, "mchanged by data (%s)\n", from)
	} else {
		for k, v := range zd.d {
			nv := d[k]
			if nv != v {
				nv := d[k]
				if len(nv) > 6 {
					nv = nv[:6] + "..."
				}
				zd.cprintf(zd.path, "mchanged %s = %s (%s)\n", k, nv, from)
				mchanged = true
				break
			}
		}
	}
	if !mchanged {
		zd.cprintf("stated", "no changes (%s)\n", from)
		return dchanged, dchanged, nil
	}

	ot, nt := zd.d["type"], d["type"]
	overs, nvers := zd.d.Int("vers"), d.Int("vers")
	if nt==ot && nt!="d" && nvers!=0 && nvers<overs {
		zd.cprintf("stated", "old update ignored v %d (%s)\n", nvers, from)
		return dchanged, dchanged, nil
	}
	switch {
	case ot!=nt && (nt=="d" || ot=="d"):
		// file became dir or dir became file
		zd.child = nil
		dchanged = true
		zd.cprintf(zd.path, "dchanged type %s (%s)\n", nt, from)
	case zd.d["mtime"] != d["mtime"]:
		zd.cprintf(zd.path, "dchanged mtime %s (%s)\n", d["mtime"], from)
		dchanged = true
	case d["Sum"]!="" && zd.d["Sum"]!=d["Sum"]:
		ns := d["Sum"]
		if len(ns) > 6 {
			ns = ns[:6] + "..."
		}
		zd.cprintf(zd.path, "dchanged Sum %s (%s)\n", ns, from)
		dchanged = true
	case nt!="d" && zd.d["size"]!=d["size"]:
		zd.cprintf(zd.path, "dchanged size %s (%s)\n", d["size"], from)
		dchanged = true
	}
	if d["Sum"] == "" {
		d["Sum"] = zd.d["Sum"]
	}
	if d["vers"] == "" {
		d["vers"] = zd.d["vers"]
	}
	zd.d = d
	zd.mode = uint(zd.d.Uint64("mode")&0777)
	zd.refreshMeta()
	if dchanged {
		zd.invalData()
	}
	return mchanged, dchanged, nil
}