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
}