Exemplo n.º 1
0
func (t *Fs) Wstat(rid string, d zx.Dir) chan error {
	t.dprintf("wstat %s %v\n", rid, d)
	c := make(chan error, 1)
	rid, err := zx.AbsPath(rid)
	if err != nil {
		c <- err
		close(c, err)
		return c
	}
	cs := t.IOstats.NewCall(zx.Swstat)
	if rid == "/Ctl" {
		close(c)
		cs.End(false)
		return c
	}
	err = t.wstat(rid, d)
	if err == nil {
		t.dprintf("wstat %s: ok\n", rid)
	} else {
		t.dprintf("wstat %s: %s\n", rid, err)
	}
	c <- err
	close(c, err)
	cs.End(err != nil)
	return c
}
Exemplo n.º 2
0
func (t *Fs) get(rid string, off, count int64, dc chan<- []byte, cs *zx.CallStat) error {
	rid, err := zx.AbsPath(rid)
	if err != nil {
		return err
	}
	if rid == "/Ctl" {
		return t.getCtl(off, count, dc, cs)
	}

	f, _, err := t.walk(rid, nil)
	if err == nil && !t.NoPermCheck {
		f.mlk.Lock()
		if !f.d.CanRead(t.ai) {
			err = dbg.ErrPerm
		}
		f.mlk.Unlock()
	}
	if err != nil {
		return err
	}
	f.mlk.Lock()
	if f.d["type"] == "d" {
		f.mlk.Unlock()
		return f.getDir(off, count, dc, cs)
	}
	f.mlk.Unlock()
	cs.Sending()
	n, nm, err := f.data.SendTo(off, count, dc)
	cs.Sends(int64(nm), n)
	return err	
}
Exemplo n.º 3
0
func (fs *Cfs) stat(rid string) (zx.Dir, error) {
	rid, err := zx.AbsPath(rid)
	if err != nil {
		return nil, err
	}
	if rid == "/Ctl" {
		d := ctldir.Dup()
		d["tpath"] = fs.tpath
		return d, nil
	}
	if rid == "/Chg" {
		d := chgdir.Dup()
		d["tpath"] = fs.tpath
		return d, nil
	}
	f, _, err := fs.walk(rid, RO)
	if err != nil {
		return nil, err
	}
	f.unlockc(RO)

	nocattrs(f.d)

	/* do not add /Chg to the count, it's hidden now
		if id == "/" {	// adjust size for /Chg
			nd["size"] = strconv.Itoa(f.d.Int("size") + 1)
		}
	*/
	return f.d, nil
}
Exemplo n.º 4
0
func (t *Fs) remove(rid string, all bool) error {
	rid, err := zx.AbsPath(rid)
	if err != nil {
		return err
	}
	if rid == "/" || rid == "/Ctl" {
		return fmt.Errorf("%s: %s", rid, dbg.ErrPerm)
	}
	pf, err := t.walk(path.Dir(rid))
	if err != nil {
		return err
	}
	pd, err := pf.Stat()
	if err != nil {
		return err
	}
	pfrm, ok := pf.(Remover)
	if !ok {
		return fmt.Errorf("%s: %s", pd["path"], dbg.ErrPerm)
	}
	if !t.NoPermCheck && !pd.CanWrite(t.ai) {
		return fmt.Errorf("%s: %s", pd["path"], dbg.ErrPerm)
	}
	nm := path.Base(rid)
	f, err := pfrm.Walk(nm)
	if err != nil {
		return err
	}
	return pfrm.Remove(f, nm, all)
}
Exemplo n.º 5
0
func (t *Lfs) stat(rid string) (zx.Dir, error) {
	rid, err := zx.AbsPath(rid)
	if err != nil {
		return nil, err
	}
	if rid == "/Ctl" {
		d := ctldir.Dup()
		d["tpath"] = t.path
		return d, nil
	}
	path := zx.Path(t.path, rid)
	st, err := os.Stat(path)
	if err != nil {
		return nil, err
	}
	nd := 0
	sum := ""
	if st.IsDir() {
		nd, sum = dirsz(path)
		if rid == "/" {
			nd++
		}
	}
	d := zx.NewDir(st, nd)
	if t.readattrs {
		t.fileAttrs(path, d)
	}
	if sum != "" {
		d["Sum"] = sum
	}
	d["tpath"] = t.path
	d["path"] = rid
	d["spath"] = rid
	d["proto"] = "lfs"
	if rid == "/" {
		d["name"] = "/"
	}
	if d["Uid"] == "" {
		d["Uid"] = dbg.Usr
	}
	if d["Gid"] == "" {
		d["Gid"] = dbg.Usr
	}
	if d["Wuid"] == "" {
		d["Wuid"] = dbg.Usr
	}
	return d, nil
}
Exemplo n.º 6
0
func (t *Fs) walk(rid string) (File, error) {
	rid, err := zx.AbsPath(rid)
	if err != nil {
		return nil, err
	}
	if rid == "/" {
		return t.root, nil
	}
	if rid == "/Ctl" {
		return nil, nil
	}
	els := zx.Elems(rid)
	f := t.root
	p := "/"
	var d zx.Dir
	for _, e := range els {
		t.Dprintf("walk %s %s...\n", f, e)
		d, err = f.Stat()
		if err != nil {
			t.Dprintf("\tstat: %s\n", f, err)
			return nil, err
		}
		if d["type"] != "d" {
			t.Dprintf("\tnot dir\n")
			return nil, fmt.Errorf("%s: %s", p, dbg.ErrNotDir)
		}
		if !t.NoPermCheck && !d.CanWalk(t.ai) {
			t.Dprintf("\tno perm\n")
			return nil, fmt.Errorf("%s: %s", p, dbg.ErrPerm)
		}
		wf, ok := f.(Walker)
		if !ok {
			t.Dprintf("\tnot walker\n")
			return nil, fmt.Errorf("%s: %s: %s", p, e, dbg.ErrNotExist)
		}
		f, err = wf.Walk(e)
		if err != nil {
			t.Dprintf("\twalk: %s\n", err)
			return nil, err
		}
		p = zx.Path(p, e)
		t.Dprintf("walked %s\n", f)
	}
	return f, nil
}
Exemplo n.º 7
0
func (t *Fs) stat(rid string) (zx.Dir, error) {
	rid, err := zx.AbsPath(rid)
	if err != nil {
		return nil, err
	}
	if rid == "/Ctl" {
		cd := ctldir.Dup()
		cd["tpath"] = t.path
		return cd, nil
	}
	f, _, err := t.walk(rid, nil)
	if err != nil {
		return nil, err
	}
	f.mlk.Lock()
	defer f.mlk.Unlock()
	return f.d.Dup(), nil
}
Exemplo n.º 8
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)
	rid, err := zx.AbsPath(rid)
	if rid=="/Ctl" || rid == "/" {
		err = dbg.ErrExists
	} else {
		err = t.mkdir(rid, d)
	}
	c := make(chan error, 1)
	cs.End(err != nil)
	if err != nil {
		t.dprintf("mkdir %s: %s\n", rid, err)
	}
	c <- err
	close(c, err)
	return c
}
Exemplo n.º 9
0
/*
	See the Binder.Unmount operation.
*/
func (ns *Tree) Unmount(fname string, d zx.Dir) <-chan error {
	c := make(chan error, 1)
	go func() {
		name := ""
		var err error
		if fname != "" {
			name, err = zx.AbsPath(fname)
			if err != nil {
				close(c, err)
				return
			}
		}
		ns.lk.Lock()
		defer ns.lk.Unlock()
		c <- ns.unmount(name, d)
		close(c, err)
	}()
	return c
}
Exemplo n.º 10
0
func (t *Fs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir {
	d = d.Dup()
	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 nm, n int64
		var nd zx.Dir
		if err == nil && rid == "/Ctl" {
			nc, xerr := t.putCtl(dc)
			if xerr == nil {
				nd = zx.Dir{"size": "0"}
				if DoSum {
					nd["Sum"] = zx.Zsum()
				}
				nd.SetTime("mtime", time.Now())
				nm = 1
				n = int64(nc)
			}
			err = xerr
		} else if err == nil {
			nd, nm, n, err = t.put(rid, d, off, dc, pred)
			cs.Sends(nm, n)
		}
		if err == nil {
			rd := zx.Dir{"size": nd["size"], "mtime": nd["mtime"]}
			if nd["Sum"] != "" {
				rd["Sum"] = nd["Sum"]
			}
			t.dprintf("put %s: %s (wrote %d)\n", rid, rd, n)
			c <- rd
		} else {
			t.dprintf("put %s: %s\n", rid, err)
			close(dc, err)
		}
		close(c, err)
		cs.End(err != nil)
	}()
	return c
}
Exemplo n.º 11
0
func (t *Fs) remove(rid string, all bool, cs *zx.CallStat) chan error {
	c := make(chan error, 1)
	rid, err := zx.AbsPath(rid)
	if rid=="/Ctl" || rid == "/" {
		t.dprintf("remove %s: %s\n", rid, dbg.ErrPerm)
		err := fmt.Errorf("%s: %s", rid, dbg.ErrPerm)
		c <- err
		close(c, err)
		cs.End(true)
		return c
	}
	f, _, err := t.walk(rid, nil)
	if f != nil {
		f.mlk.Lock()
	}
	if err == nil && !all && f.d["type"] == "d" && len(f.child) > 0 {
		err = errors.New("directory is not empty")
	}
	if err == nil && !t.noPerms() && !f.d.CanWrite(t.ai) {
		err = dbg.ErrPerm
	}
	if f != nil {
		if err == nil {
			f.d["rm"] = "y"
		}
		f.mlk.Unlock()
	}
	if err != nil {
		t.dprintf("remove %s: %s\n", rid, err)
		c <- err
		close(c, err)
		cs.End(true)
		return c
	}
	t.detach(f)
	t.dprintf("remove %s: ok\n", rid)
	close(c)
	cs.End(false)
	return c
}
Exemplo n.º 12
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
}
Exemplo n.º 13
0
// Resolve a name and return the prefix path, the array of mount points for it and the server paths
// for each mount point.
// The path must be absolute.
func (ns *Tree) Resolve(name string) (pref string, mnts []zx.Dir, spaths []string, err error) {
	path, err := zx.AbsPath(name)
	if err != nil {
		return "", nil, nil, err
	}
	ns.dprintf("resolve %s\n", path)
	ns.lk.RLock()
	defer ns.lk.RUnlock()
	var p *prefix
	for _, np := range ns.pref {
		if zx.HasPrefix(path, np.name) {
			ns.dprintf("\thasprefix %s %s\n", path, np.name)
			p = np
		}
	}
	if p == nil {
		ns.dprintf("\tno prefixes\n")
		return "", nil, nil, dbg.ErrNotExist
	}
	suff := zx.Suffix(path, p.name)
	mnts = make([]zx.Dir, 0, len(p.mnt))
	spaths = []string{}
	for _, d := range p.mnt {
		if isfinder(d) || suff=="" || suff=="/" {
			mnts = append(mnts, d.Dup())
			spath := zx.Path(suff, d["spath"])
			spaths = append(spaths, spath)
			ns.dprintf("\ts='%s' d=%s\n", spath, d)
		} else {
			ns.dprintf("\tskip %s\n", d)
		}
	}
	if len(mnts) == 0 {
		ns.dprintf("\tno prefixes left\n")
		return "", nil, nil, dbg.ErrNotExist
	}
	return p.name, mnts, spaths, nil
}
Exemplo n.º 14
0
// See the Binder.Mount operation.
func (ns *Tree) Mount(fname string, d zx.Dir, flag Flag) <-chan error {
	c := make(chan error, 1)
	go func() {
		name, err := zx.AbsPath(fname)
		if err==nil && d==nil {
			err = errors.New("no mounted dir")
		}
		if err != nil {
			c <- err
			close(c, err)
			return
		}
		d = d.Dup()
		delete(d, "mtime")
		delete(d, "size")
		d["path"] = name
		d["name"] = path.Base(name)
		ns.lk.Lock()
		defer ns.lk.Unlock()
		c <- ns.mount(d, flag)
		close(c, err)
	}()
	return c
}
Exemplo n.º 15
0
func (t *Lfs) Stat(rid string) chan zx.Dir {
	t.dprintf("stat %s\n", rid)
	cs := t.IOstats.NewCall(zx.Sstat)
	c := make(chan zx.Dir, 1)
	rid, err := zx.AbsPath(rid)
	var d zx.Dir
	if err == nil {
		d, err = t.stat(rid)
	}
	if err==nil && t.ai!=nil && !t.NoPermCheck {
		_, _, err = t.canWalkTo(rid, 0)
	}
	if err != nil {
		t.dprintf("stat %s: %s\n", rid, err)
		close(c, err)
		cs.End(true)
		return c
	}
	t.dprintf("stat %s: ok\n", rid)
	c <- d
	close(c)
	cs.End(false)
	return c
}
Exemplo n.º 16
0
func (t *Lfs) get(rid string, off, count int64, dc chan<- []byte, cs *zx.CallStat) (int64, error) {
	rid, err := zx.AbsPath(rid)
	if err != nil {
		return 0, err
	}
	if rid == "/Ctl" {
		return t.getCtl(off, count, dc, cs)
	}
	path := zx.Path(t.path, rid)
	fd, err := os.Open(path)
	if err==nil && t.ai!=nil && !t.NoPermCheck {
		_, _, err = t.canWalkTo(rid, 0444)
	}
	if err != nil {
		return 0, err
	}
	defer fd.Close()
	st, err := fd.Stat()
	if err != nil {
		return 0, err
	}
	if off!=0 && !st.IsDir() {
		if _, err := fd.Seek(off, 0); err != nil {
			return 0, err
		}
	}
	if st.IsDir() {
		ds, err := ioutil.ReadDir(path)
		nd := 0
		tot := 0
		ctlsent := false
		var xds map[string]zx.Dir
		if t.readattrs {
			xds, _ = t.dirAttrs(path)
		}
	Dloop:
		for i := 0; i < len(ds); {
			if off > 0 {
				off--
				if !ctlsent && rid=="/" {
					ctlsent = true
				} else {
					i++
				}
				continue
			}
			switch count {
			case zx.All:
				break
			case 0:
				break Dloop
			default:
				count--
			}
			if !ctlsent && rid=="/" {
				ctlsent = true
				nd++
				d := ctldir
				n, _ := d.Send(dc)
				nd++ // but not i++
				tot += n
				continue
			}
			fi := ds[i]
			if fi.Name() == afname {
				if i == len(ds)-1 {
					break
				}
				ds = append(ds[:i], ds[i+1:]...)
				fi = ds[i]
			}
			cpath := zx.Path(path, fi.Name())
			n := 0
			sum := ""
			if fi.IsDir() {
				n, sum = dirsz(cpath)
			}
			d := zx.NewDir(fi, n)
			d["path"] = zx.Path(rid, fi.Name())
			d["spath"] = d["path"]
			d["tpath"] = t.path
			if t.readattrs {
				if xd, ok := xds[fi.Name()]; ok {
					for k, v := range xd {
						if zx.IsUpper(k) {
							d[k] = v
						}
					}
				} else {
					d["Uid"] = dbg.Usr
					d["Gid"] = dbg.Usr
				}
			}
			if sum != "" {
				d["Sum"] = sum
			}
			cs.Send(0)
			n, err := d.Send(dc)
			if err != nil {
				return int64(tot), err
			}
			nd++
			i++
			tot += n
		}
		return int64(tot), err
	}
	if count == zx.All {
		cs.Sending()
		nm, n, err := nchan.ReadBytesFrom(fd, dc)
		cs.Sends(nm, n)
		return n, err
	}
	rr := io.LimitReader(fd, count)
	cs.Sending()
	nm, n, err := nchan.ReadBytesFrom(rr, dc)
	cs.Sends(nm, n)
	return n, err
}
Exemplo n.º 17
0
func (t *Fs) move(from, to string) error {
	from, ferr := zx.AbsPath(from)
	if ferr != nil {
		return ferr
	}
	if from == "/" || from == "/Ctl" {
		return fmt.Errorf("%s: %s", from, dbg.ErrPerm)
	}
	to, terr := zx.AbsPath(to)
	if terr != nil {
		return terr
	}
	if to == "/" || to == "/Ctl" {
		return fmt.Errorf("%s: %s", from, dbg.ErrPerm)
	}
	if inconsistent(from, to) {
		return fmt.Errorf("%s: inconsistent move", from)
	}
	pfromf, err := t.walk(path.Dir(from))
	if err != nil {
		return err
	}
	pfrommv, ok := pfromf.(Mover)
	if !ok {
		return fmt.Errorf("%s: %s", from, dbg.ErrPerm)
	}
	pfd, err := pfromf.Stat()
	if err != nil {
		return err
	}
	if !t.NoPermCheck && !pfd.CanWrite(t.ai) {
		return fmt.Errorf("%s: %s", pfd["path"], dbg.ErrPerm)
	}
	var fromf File
	fromf, err = pfrommv.Walk(path.Base(from))
	if err != nil {
		return err
	}

	pto, err := t.walk(path.Dir(to))
	if err != nil {
		return err
	}
	ptd, err := pto.Stat()
	if err != nil {
		return err
	}
	if !t.NoPermCheck && !ptd.CanWrite(t.ai) {
		return fmt.Errorf("%s: %s", ptd["path"], dbg.ErrPerm)
	}
	ptow, ok := pto.(Walker)
	if !ok {
		return fmt.Errorf("%s: %s", ptd["path"], dbg.ErrPerm)
	}
	tof, err := ptow.Walk(path.Base(to))
	if err == nil {
		tod, err := tof.Stat()
		if tod["type"] == "d" {
			return fmt.Errorf("%s: %s", to, dbg.ErrIsDir)
		}
		return err
	}
	return pfrommv.Move(fromf, path.Base(from), pto, path.Base(to))
}
Exemplo n.º 18
0
// d is a dup and can be changed.
func (t *Fs) find(f File, d zx.Dir, p *pred.Pred, spref, dpref string, lvl int,
	c chan<- zx.Dir, ai *auth.Info) {
	match, pruned, err := p.EvalAt(d, lvl)
	t.dprintf("find  at %v\n\t%v\n\t%v %v %v\n\n", d, p, match, pruned, err)
	if pruned {
		if !match {
			d["err"] = "pruned"
		}
		c <- d
		return
	}
	if d["type"] == "d" && err == nil {
		if !t.NoPermCheck && !d.CanWalk(ai) {
			err = dbg.ErrPerm
		}
	}
	if err != nil {
		d["err"] = err.Error()
		c <-d
		return
	}
	if d["rm"] != "" {
		return
	}
	if match {
		if ok := c <- d; !ok {
			return
		}
	}
	if d["type"] != "d" || f == nil {
		return
	}
	wf, ok := f.(Walker)
	if !ok {
		return
	}
	ns, err := wf.Getdir()
	if err != nil {
		return
	}
	sort.Sort(sort.StringSlice(ns))
	if d["name"] == "/" {
		cd := ctldir.Dup()
		if spref != dpref {
			cpath := cd["path"]
			suff := zx.Suffix(cpath, spref)
			cd["path"] = zx.Path(dpref, suff)
		}
		t.find(nil, cd, p, spref, dpref, lvl+1, c, ai)
	}
	for _, cnm := range ns {
		cf, err := wf.Walk(cnm)
		if err != nil {
			continue
		}
		cp := zx.Path(d["path"], cnm)
		cd, err := t.statf(cf, cp)
		if err != nil || cd["rm"] != "" {
			continue
		}
		cd = cd.Dup()
		if spref != dpref {
			cpath := cd["path"]
			suff := zx.Suffix(cpath, spref)
			cd["path"] = zx.Path(dpref, suff)
		}
		t.find(cf, cd, p, spref, dpref, lvl+1, c, ai)
	}
}

func (t *Fs) Find(rid, fpred, spref, dpref string, depth int) <-chan zx.Dir {
	t.dprintf("find %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	cs := t.IOstats.NewCall(zx.Sfind)
	dc := make(chan zx.Dir)
	go func() {
		rid, err := zx.AbsPath(rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		f, err := t.walk(rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		p, err := pred.New(fpred)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		d, err := t.statf(f, rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		d = d.Dup()
		if spref != dpref {
			suff := zx.Suffix(rid, spref)
			d["path"] = zx.Path(dpref, suff)
		}
		t.find(f, d, p, spref, dpref, depth, dc, t.ai)
		cs.End(err != nil)
		t.dprintf("find %s: ok\n", rid)
		close(dc)
	}()
	return dc
}

// used only by findget
func (t *Fs) get(rid string, datac chan<- []byte) error {
	f, err := t.walk(rid)
	if err != nil {
		return err
	}
	gf, ok := f.(Getter)
	if !ok {
		return nil
	}
	return gf.Get(0, -1, datac)
}

func (t *Fs) FindGet(rid, fpred, spref, dpref string, depth int) <-chan zx.DirData {
	t.dprintf("findget %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	gc := make(chan zx.DirData)
	cs := t.IOstats.NewCall(zx.Sfindget)
	go func() {
		dc := t.Find(rid, fpred, spref, dpref, depth) // BUG: will stat a Sfind
		for d := range dc {
			g := zx.DirData{Dir: d}
			var datac chan []byte
			if d["err"] == "" && !t.NoPermCheck &&
				d["type"] != "d" && !d.CanRead(t.ai) {
				d["err"] = dbg.ErrPerm.Error()
				
			}
			if d["err"]=="" && d["type"]!="d" {
				datac = make(chan []byte)
				g.Datac = datac
			}
			if ok := gc <- g; !ok {
				close(dc, cerror(gc))
				break
			}
			if datac != nil {
				err := t.get(d["spath"], datac)
				close(datac, err)
			}
		}
		err := cerror(dc)
		cs.End(err != nil)
		if err != nil {
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(gc, err)
	}()
	return gc
}
Exemplo n.º 19
0
func (t *Fs) Move(from, to string) chan error {
	t.dprintf("move %s %s \n", from, to)
	cs := t.IOstats.NewCall(zx.Smove)
	c := make(chan error, 1)
	from, ferr := zx.AbsPath(from)
	to, terr := zx.AbsPath(to)
	var pfrom, pto *mFile
	var leftto []string
	var err error
	var fd, pd *mFile
	if ferr != nil {
		err = ferr
	} else if terr != nil {
		err = terr
	} else if from == to {
		c <- nil
		close(c)
		cs.End(false)
		return c
	}
	if err == nil {
		fd, _, err = t.walk(path.Dir(from), nil)
	}
	if err == nil && !t.noPerms() {
		fd.mlk.Lock()
		if !fd.d.CanWrite(t.ai) {
			err = fmt.Errorf("%s: %s", fd, dbg.ErrPerm)
		}
		fd.mlk.Unlock()
	}
	if err == nil {
		pd, _, err = t.walk(path.Dir(to), nil)
	}
	var pdpath, pdspath string
	if err == nil {
		pd.mlk.Lock()
		if !t.noPerms() && !pd.d.CanWrite(t.ai) {
			err = fmt.Errorf("%s: %s", pd, dbg.ErrPerm)
		}
		pdpath = pd.d["path"]
		pdspath = pd.d["spath"]
		pd.mlk.Unlock()
	}
	if err != nil {
		goto Fail
	}

	if from=="/Ctl" || to=="/Ctl" || from == "/" || to == "/" {
		err = dbg.ErrPerm
	} else if pfrom, _, ferr = t.walk(from, nil); ferr != nil {
		err = ferr
	} else if inconsistent(from, to) {
		err = errors.New("inconsistent move")
	} else if pto, leftto, terr = t.walk(to, nil); terr != nil && !dbg.IsNotExist(terr) {
		err = terr
	} else if len(leftto) > 1 {
		err = terr
	} else if len(leftto) == 0 && pto.d["type"] == "d" {
		err = fmt.Errorf("%s: %s", pto, dbg.ErrExists)
	} else if len(leftto) == 0 && pto.d["type"] != pfrom.d["type"] { // race: no lock in types
		err = fmt.Errorf("%s: incosistent move", pfrom)
	}
Fail:	if err != nil {
		c <- err
		t.dprintf("move %s: %s\n", from, err)
		close(c, err)
		cs.End(true)
		return c
	}
	t.detach(pfrom)
	pfrom.mlk.Lock()
	pfrom.name= path.Base(to)
	pfrom.d["name"] = pfrom.name
	pfrom.d["path"] = zx.Path(pdpath, pfrom.name)
	pfrom.d["spath"] = zx.Path(pdspath, pfrom.name)
	pfrom.mlk.Unlock()
	pfrom.moved()
	pd.mlk.Lock()
	pd.clk.Lock()
	pd.attach(pfrom)
	pd.clk.Unlock()
	pd.mlk.Unlock()
	t.dprintf("move %s: ok\n", from)
	close(c)
	cs.End(false)
	return c
}
Exemplo n.º 20
0
// d is a dup and can be changed.
func (f *mFile) find(d zx.Dir, p *pred.Pred, spref, dpref string, lvl int, c chan<- zx.Dir, ai *auth.Info) {
	match, pruned, err := p.EvalAt(d, lvl)
	f.dprintf("find  at %d %s\n\t%v\n\t%v %v %v\n\n",
		lvl, d.Long(), p, match, pruned, err)
	if pruned {
		if !match {
			d["err"] = "pruned"
		}
		c <- d
		return
	}
	if d["type"] == "d" && err == nil {
		f.mlk.Lock()
		if !f.t.NoPermCheck && !f.d.CanWalk(ai) {
			err = dbg.ErrPerm
		}
		f.mlk.Unlock()
	}
	if err != nil {
		d["err"] = err.Error()
		c <-d
		return
	}
	if d["rm"] != "" {
		return
	}
	if match {
		if ok := c <- d; !ok {
			return
		}
	}
	if d["type"] != "d" {
		return
	}
	f.clk.Lock()
	child := make([]*mFile, len(f.child))
	copy(child, f.child)
	f.clk.Unlock()
	if f.name == "/" {
		nc := []*mFile{
			&mFile{name: "Ctl", d: ctldir.Dup(), t: f.t},
		}
		nc[0].d["tpath"] = f.t.path
		child = append(nc, child...)
	}
	for _, cf := range child {
		cf.mlk.Lock()
		cd := cf.d.Dup()
		cf.mlk.Unlock()
		// fmt.Printf("child %s\n", cd)
		if cd["rm"] != "" {
			continue
		}
		if spref != dpref {
			cpath := cd["path"]
			suff := zx.Suffix(cpath, spref)
			cd["path"] = zx.Path(dpref, suff)
		}
		cf.find(cd, p, spref, dpref, lvl+1, c, ai)
	}
}

func (t *Fs) Find(rid, fpred, spref, dpref string, depth int) <-chan zx.Dir {
	t.dprintf("find %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	cs := t.IOstats.NewCall(zx.Sfind)
	dc := make(chan zx.Dir)
	go func() {
		rid, err := zx.AbsPath(rid)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		f, _, err := t.walk(rid, nil)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		p, err := pred.New(fpred)
		if err != nil {
			cs.End(err != nil)
			t.dprintf("find %s: %s\n", rid, err)
			close(dc, err)
			return
		}
		cs.Sending()
		f.mlk.Lock()
		d := f.d.Dup()
		f.mlk.Unlock()
		if spref != dpref {
			suff := zx.Suffix(rid, spref)
			d["path"] = zx.Path(dpref, suff)
		}
		f.find(d, p, spref, dpref, depth, dc, t.ai)
		cs.End(err != nil)
		t.dprintf("find %s: ok\n", rid)
		close(dc)
	}()
	return dc
}

func (t *Fs) FindGet(rid, fpred, spref, dpref string, depth int) <-chan zx.DirData {
	t.dprintf("findget %s '%s' '%s' '%s' %d\n", rid, fpred, spref, dpref, depth)
	gc := make(chan zx.DirData)
	cs := t.IOstats.NewCall(zx.Sfindget)
	go func() {
		dc := t.Find(rid, fpred, spref, dpref, depth) // BUG: will stat a Sfind
		for d := range dc {
			g := zx.DirData{Dir: d}
			var datac chan []byte
			if d["err"]=="" && d["type"]=="-" {
				datac = make(chan []byte)
				g.Datac = datac
			}
			if ok := gc <- g; !ok {
				close(dc, cerror(gc))
				break
			}
			if datac != nil {
				err := t.get(d["spath"], 0, zx.All, datac, nil)
				close(datac, err)
			}
		}
		err := cerror(dc)
		cs.End(err != nil)
		if err != nil {
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(gc, err)
	}()
	return gc
}

func (t *Fs) Dump(w io.Writer) {
	if t == nil {
		fmt.Fprintf(w, "<nil tree>\n")
		return
	}
	fmt.Fprintf(w, "tree [%s] path %s\n", t.name, t.path)
	t.root.Dump(w, 0)
	fmt.Fprintf(w, "\n")
}

func (f *mFile) Dump(w io.Writer, lvl int) {
	tabs := strings.Repeat("    ", lvl)
	if f == nil {
		fmt.Fprintf(w, "%s<nil file>\n", tabs)
		return
	}
	d := f.d.Dup()
	if d["path"] == "/" {
		d["size"] = "0"
	}
	fmt.Fprintf(w, "%s%s\n", tabs, d.TestFmt())
	if d["type"] != "d"  {
		fmt.Fprintf(w, "%s  %d bytes\n", tabs, f.data.Len())
		return
	}
	for _, c := range f.child {
		c.Dump(w, lvl+1)
	}
	
}
Exemplo n.º 21
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
}