예제 #1
0
func (t *Fs) wstat(rid string, d zx.Dir) error {
	f, err := t.walk(rid)
	if err != nil {
		return err
	}
	ud := d.UsrAttrs()
	d, err = f.Stat()
	if err != nil {
		return err
	}
	ai := t.ai
	if t.NoPermCheck {
		ai = nil
	}
	if !t.WstatAll || t.ai != nil {
		if err := d.CanWstat(ai, ud); err != nil {
			return err
		}
	}
	if wsf, ok := f.(Wstater); !ok {
		if _, ok := f.(Putter); !ok {
			return fmt.Errorf("%s: %s", rid, dbg.ErrPerm)
		}
		// ignore wstats if there's Put so that echo > file works.
		return nil
	} else {
		return wsf.Wstat(ud)
	}
}
예제 #2
0
// does not check attributes that indicate that data changed.
func metaChanged(d0, d1 zx.Dir) bool {
	ud0 := d0.UsrAttrs()
	ud1 := d1.UsrAttrs()
	for _, k := range ignoredAttrs {
		delete(ud0, k)
		delete(ud1, k)
	}
	return !zx.EqDir(ud0, ud1)
}
예제 #3
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
}
예제 #4
0
func (t *Fs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir {
	d = d.UsrAttrs()
	t.dprintf("put %s %v %d '%s'\n", rid, d, off, pred)
	cs := t.IOstats.NewCall(zx.Sput)
	c := make(chan zx.Dir, 1)
	go func() {
		cs.Sending()
		rid, err := zx.AbsPath(rid)
		var nd zx.Dir
		if err == nil && rid == "/" {
			err = fmt.Errorf("/: %s", dbg.ErrPerm)
		}
		if err == nil && rid == "/Ctl" {
			xerr := t.putCtl(dc)
			if xerr == nil {
				nd = zx.Dir{"size": "0", "Sum": zx.Zsum()}
				nd.SetTime("mtime", time.Now())
			}
			err = xerr
		} else if err == nil {
			err = t.put(rid, d, off, dc, pred)
			if err == nil {
				nd, err = t.stat(rid)
			}
		}
		if err == nil {
			rd := zx.Dir{"size": nd["size"], "mtime": nd["mtime"], "Sum": nd["Sum"]}
			t.dprintf("put %s: %s\n", rid, rd)
			c <- rd
		} else {
			t.dprintf("put %s: %s\n", rid, err)
			close(dc, err)
		}
		close(c, err)
		cs.End(err != nil)
	}()
	return c
}
예제 #5
0
func (t *Fs) wstat(rid string, d zx.Dir) error {
	f, _, err := t.walk(rid, nil)
	if err != nil {
		return err
	}
	f.mlk.Lock()
	defer f.mlk.Unlock()
	ai := t.ai
	if t.NoPermCheck {
		ai = nil
	}
	ud := d.UsrAttrs()
	if !t.WstatAll || t.ai != nil  {
		if err := f.d.CanWstat(ai, d); err != nil {
			return err
		}
	} else {
		if d["Wuid"] != "" {
			ud["Wuid"] = d["Wuid"]
		}
	}
	return f.wstat(ud)
}
예제 #6
0
func (t *Fs) mkdir(rid string, d zx.Dir) error {
	d = d.UsrAttrs()
	pf, err := t.walk(path.Dir(rid))
	if err != nil {
		return err
	}
	pd, err := pf.Stat()
	if pd["type"] != "d" {
		return fmt.Errorf("%s: %s", pd["path"], dbg.ErrNotDir)
	}
	wpf, ok := pf.(Mkdirer)
	if !ok {
		return fmt.Errorf("%s: %s", pd["path"], dbg.ErrPerm)
	}
	_, err = wpf.Walk(path.Base(rid))
	if err == nil {
		return fmt.Errorf("%s: %s", pd["path"], dbg.ErrExists)
	}
	if !t.NoPermCheck && !pd.CanWrite(t.ai) {
		return fmt.Errorf("%s: %s", rid, dbg.ErrPerm)
	}
	return wpf.Mkdir(path.Base(rid), d)
	return fmt.Errorf("%s: %s", rid, dbg.ErrPerm)
}
예제 #7
0
func (t *Fs) Mkdir(rid string, d zx.Dir) chan error {
	t.dprintf("mkdir %s %v\n", rid, d)
	cs := t.IOstats.NewCall(zx.Smkdir)
	c := make(chan error, 1)
	rid, err := zx.AbsPath(rid)
	if rid == "/" || rid=="/Ctl" {
		err = dbg.ErrExists
	}
	var f *mFile
	var left []string
	if err == nil {
		f, left, err = t.walk(rid, nil)
	}
	if err == nil {
		err = fmt.Errorf("'%s': %s", rid, dbg.ErrExists)
	} else if len(left) == 1 {
		err = nil
	}
	if err != nil {
		cs.End(true)
		t.dprintf("mkdir %s: %s\n", rid, err)
		c <- err
		close(c, err)
		return c
	}
	ud := d.UsrAttrs()
	delete(ud, "size")
	noinherit := false
	if m := ud["Mode"]; m != "" {
		ud["mode"] = m
		delete(ud, "Mode")
		noinherit = true
	}
	if ud["mode"] == "" {
		ud["mode"] = "0775"
	}
	if (!t.WstatAll || t.ai != nil) && !noinherit {
		f.mlk.Lock()
		ud["type"] = "d"
		ud.Inherit(f.d.Mode())
		delete(ud, "type")
		f.mlk.Unlock()
	}
	u := dbg.Usr
	if t.ai != nil {
		u = t.ai.Uid
	}
	nf := &mFile {
		name: left[0],
		d: zx.Dir{
			"mode": ud["mode"],
			"name": left[0],
			"path": rid,
			"spath": rid,
			"tpath": f.t.path,
			"Uid": u,
			"Gid": f.d["Gid"],
			"Wuid": u,
			"type": "d",
			"size": "0",
			"proto": "proc",
		},
		child: []*mFile{},
		t: t,
	}
	if DoSum {
		nf.d["Sum"] = zx.Zsum()
	}
	f.mlk.Lock()
	if !t.noPerms() && !f.d.CanWrite(t.ai) {
		err = fmt.Errorf("%s: %s", f, dbg.ErrPerm)
	}
	ai := t.ai
	if t.NoPermCheck {
		ai = nil
	}
	if err == nil && (!t.WstatAll || t.ai != nil)  {
		err = nf.d.CanWstat(ai, ud)
	}
	if err != nil {
		f.mlk.Unlock()
		cs.End(true)
		t.dprintf("mkdir %s: %s\n", rid, err)
		c <- err
		close(c, err)
		return c
	}
	f.mlk.Unlock()
	f.mlk.Lock()
	f.clk.Lock()
	f.attach(nf)
	f.clk.Unlock()
	f.mlk.Unlock()
	f = nf
	f.mlk.Lock()
	if t.WstatAll && t.ai == nil && d["Wuid"] != "" {
		ud["Wuid"] = d["Wuid"]
	}
	err = f.wstat(ud)
	f.mlk.Unlock()
	cs.End(err != nil)
	if err != nil {
		t.dprintf("mkdir %s: %s\n", rid, err)
	}
	c <- err
	close(c, err)
	return c
}
예제 #8
0
func (t *Fs) put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) (zx.Dir, int64, int64, error) {
	noinherit := false
	if m := d["Mode"]; m != "" {
		d["mode"] = m
		delete(d, "Mode")
		noinherit = true
	}
	var pf *mFile
	f, left, err := t.walk(rid, &pf)
	if err != nil && !dbg.IsNotExist(err) || len(left) > 1|| d["mode"] == "" && err != nil {
		return nil, 0, 0, err
	}
	pmode := uint64(0755)
	if pf != nil {
		pf.mlk.Lock()
		pmode = pf.d.Mode()
		pf.mlk.Unlock()
	}
	app := false
	f.mlk.Lock()
	if err == nil && f.d["type"] == "d" || d["type"] == "d" {
		err = fmt.Errorf("%s: %s", f, dbg.ErrIsDir)
		f.mlk.Unlock()
		return nil, 0, 0, err
	}
	if !t.noPerms() && !f.d.CanWrite(t.ai) {
		err = fmt.Errorf("%s: %s", f, dbg.ErrPerm)
		f.mlk.Unlock()
		return nil, 0, 0, err
	}
	u := dbg.Usr
	if t.ai != nil {
		u = t.ai.Uid
	}
	if d == nil {
		d = zx.Dir{}
	}
	ai := t.ai
	if t.NoPermCheck {
		ai = nil
	}
	if d["mode"] == "" || err == nil {	// truncate or rewrite
		if err := t.matchDir(rid, f.d, pred); err != nil {
			f.mlk.Unlock()
			return nil, 0, 0, err
		}
		if !t.WstatAll || t.ai != nil {
			if err := f.d.CanWstat(ai, d); err != nil {
				f.mlk.Unlock()
				return nil, 0, 0, err
			}
		}
	} else {
		if err := t.matchDir(rid, nil, pred); err != nil {
			f.mlk.Unlock()
			return nil, 0, 0, err
		}
	}
	if d["mode"] == "" {
		if off < 0 {
			off = 0
			app = true
		}
		if t.WstatAll && t.ai == nil && d["Wuid"] != "" {
			f.d["Wuid"] = d["Wuid"]
		} else {
			f.d["Wuid"] = u
		}
		if d["size"] != "" {
			f.data.Truncate(d.Int64("size"))
			f.d["size"] = strconv.FormatInt(int64(f.data.Len()), 10)
		}
	} else if err == nil {
		// truncate existing file
		if !noinherit && (!t.WstatAll || t.ai != nil) {
			d.Inherit(pmode)
		}
		f.data.Truncate(d.Int64("size"))
		f.d["size"] = strconv.FormatInt(int64(f.data.Len()), 10)
		if t.WstatAll && t.ai == nil && d["Wuid"] != "" {
			f.d["Wuid"] = d["Wuid"]
		} else {
			f.d["Wuid"] = u
		}
	} else {
		// create a new file
		nf := &mFile {
			name: left[0],
			d: zx.Dir{
				"mode": d["mode"],
				"name": left[0],
				"path": rid,
				"spath": rid,
				"tpath": f.d["tpath"],
				"Uid": u,
				"Gid": f.d["Gid"],
				"Wuid": u,
				"type": "-",
				"size": "0",
				"proto": "proc",
			},
			data: &bufs.Blocks{Mutex: &sync.Mutex{}},
			t: t,
		}
		if !t.WstatAll || t.ai != nil  {
			if !noinherit {
				nf.d.Inherit(pmode)
				d["mode"] = nf.d["mode"]
			}
			if err := f.d.CanWstat(ai, d); err != nil {
				f.mlk.Unlock()
				return nil, 0, 0, err
			}
		} else if d["Wuid"] != "" {
			f.d["Wuid"] = d["Wuid"]
		}
		nf.data.Truncate(d.Int64("size"))
		nf.d["size"] = strconv.FormatInt(int64(nf.data.Len()), 10)
		f.clk.Lock()
		f.attach(nf)
		f.clk.Unlock()
		f.mlk.Unlock()
		f = nf
		f.mlk.Lock()
	}
	if app {
		off = int64(f.data.Len())
	}
	delete(d, "size")
	f.wstat(d.UsrAttrs())
	f.mlk.Unlock()

	n, err := f.data.RecvAtFrom(off, dc)

	f.mlk.Lock()
	defer f.mlk.Unlock()
	if DoSum {
		sum := f.data.Sum()
		f.d["Sum"] = sum
	}
	size := f.data.Len()
	f.d["size"] = strconv.Itoa(size)
	if d["mtime"] == "" {
		f.d.SetTime("mtime", time.Now())
	}
	return f.d.Dup(), 1, int64(n), err
}