예제 #1
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	
}
예제 #2
0
// locks/unlocks f's data
func (f *mFile) getDir(off, count int64, dc chan<- []byte, cs *zx.CallStat) error {
	f.clk.Lock()
	ds := make([]*mFile, len(f.child))
	copy(ds, f.child)
	f.clk.Unlock()
	nd := 0
	ctlsent := false
Dloop:
	for i := 0; i < len(ds); {
		if off > 0 {
			off--
			if !ctlsent && f.name =="/" {
				ctlsent = true
			} else {
				i++
			}
			continue
		}
		switch count {
		case zx.All:
			break
		case 0:
			break Dloop
		default:
			count--
		}
		if !ctlsent && f.name=="/" {
			ctlsent = true
			nd++
			d := ctldir.Dup()
			d["tpath"] = f.d["tpath"]
			d.Send(dc)
			nd++ // but not i++
			continue
		}
		ds[i].mlk.Lock()
		d := ds[i].d.Dup()
		ds[i].mlk.Unlock()
		cs.Send(0)
		if _, err := d.Send(dc); err != nil {
			return err
		}
		nd++
		i++
	}
	return nil
}
예제 #3
0
func (t *Fs) getCtl(off, count int64, dc chan<- []byte, cs *zx.CallStat) error {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "%s:\n", t.Name())
	fmt.Fprintf(&buf, "%s", t.Flags)
	t.IOstats.Averages()
	fmt.Fprintf(&buf, "%s\n", t.IOstats.String())

	resp := buf.Bytes()
	o := int(off)
	if o >= len(resp) {
		o = len(resp)
	}
	resp = resp[o:]
	n := int(count)
	if n>len(resp) || n<0 {
		n = len(resp)
	}
	resp = resp[:n]
	cs.Send(int64(len(resp)))
	dc <- resp
	return nil
}
예제 #4
0
func (fs *Cfs) getCtl(off, count int64, pred string, c chan<- []byte, cs *zx.CallStat) (int, error) {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "%s:\n", fs.Name())

	users := fs.Users()
	for _, k := range users {
		fmt.Fprintf(&buf, "user\t%s\n", k)
	}

	fmt.Fprintf(&buf, "%s", fs.Flags)

	fs.IOstats.Averages()
	fmt.Fprintf(&buf, "%s\n", fs.IOstats.String())

	lctl, _ := zx.GetAll(fs.lfs, "/Ctl")
	if len(lctl) > 0 {
		buf.Write(lctl)
	}

	rctl, _ := zx.GetAll(fs.rfs, "/Ctl")
	if len(rctl) > 0 {
		buf.Write(rctl)
	}
	resp := buf.Bytes()
	o := int(off)
	if o >= len(resp) {
		o = len(resp)
	}
	resp = resp[o:]
	n := int(count)
	if n > len(resp) || n < 0 {
		n = len(resp)
	}
	resp = resp[:n]
	cs.Send(int64(len(resp)))
	c <- resp
	return n, nil
}
예제 #5
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
}
예제 #6
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
}
예제 #7
0
func (t *Rfs) getrpc(rid string, msg *Msg) <-chan []byte {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan []byte, 10)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sget, len(raw))
		reqc <- raw
		close(reqc)
		some := false
		for rep := range repc {
			cs.Send(int64(len(rep)))
			if ok := c <- rep; !ok {
				close(repc, cerror(c))
				break
			}
			some = true
			t.dprintf("get %s: ok\n", rid)
		}
		if !some {
			c <- nil
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("get %s: %s\n", rid, err)
		} else {
			t.dprintf("get %s: ok\n", rid)
		}
		close(c, err)
	}()
	return c
}

func (t *Rfs) Get(rid string, off, count int64, pred string) <-chan []byte {
	t.dprintf("get %s %d %d %q\n", rid, off, count, pred)
	msg := &Msg{Op: Tget, Rid: rid, Off: off, Count: count, Pred: pred}
	return t.getrpc(rid, msg)
}

func (t *Rfs) putrpc(rid string, msg *Msg, dc <-chan []byte) chan zx.Dir {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan zx.Dir, 1)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sput, len(raw))
		reqc <- raw
		nm := 0
		tot := 0
		for m := range dc {
			nm++
			cs.Recv(int64(len(m)))
			if ok := reqc <- m; !ok {
				err := cerror(reqc)
				close(dc, err)
				close(c, err)
				cs.End(err != nil)
				return
			}
			if len(m) == 0 {
				break
			}
			tot += len(m)
		}
		close(reqc, cerror(dc))
		rep := <-repc
		var err error
		var d zx.Dir
		if len(rep) == 0 {
			err = cerror(repc)
		} else {
			d, _, err = zx.UnpackDir(rep)
			if err==nil && d==nil {
				err = errors.New("null dir in put reply")
			}
		}
		cs.End(err != nil)
		if err == nil {
			t.dprintf("put %s: %s\n", rid, d)
			c <- d
		} else {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("put %s: %s\n", rid, err)
		}
		close(c, err)
	}()
	return c
}

func (t *Rfs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir {
	t.dprintf("put %s %v %d '%s'\n", rid, d, off, pred)
	msg := &Msg{Op: Tput, Rid: rid, D: d, Off: off, Pred: pred}
	return t.putrpc(rid, msg, dc)
}

func (t *Rfs) errrpc(rid, op string, msg *Msg, k int) chan error {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan error, 1)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		var cs *zx.CallStat
		if k >= 0 {
			cs = t.IOstats.NewCallSize(k, len(raw))
		}
		reqc <- raw
		close(reqc)
		<-repc
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("%s %s: %s\n", op, rid, err)
		} else {
			t.dprintf("%s %s: ok\n", op, rid)
		}
		c <- err
		close(c, err)
		cs.End(err != nil)
	}()
	return c
}

func (t *Rfs) Fsys(name string) <-chan error {
	t.dprintf("fsys %s\n", name)
	msg := &Msg{Op: Tfsys, Rid: name}
	return t.errrpc(name, "fsys", msg, -1)
}

func (t *Rfs) Mkdir(rid string, d zx.Dir) chan error {
	msg := &Msg{Op: Tmkdir, Rid: rid, D: d}
	t.dprintf("mkdir %s %v\n", rid, d)
	return t.errrpc(rid, "mkdir", msg, zx.Smkdir)
}

func (t *Rfs) Move(from, to string) chan error {
	t.dprintf("move %s %s \n", from, to)
	msg := &Msg{Op: Tmove, Rid: from, To: to}
	return t.errrpc(from, "move", msg, zx.Smove)
}

func (t *Rfs) Remove(rid string) chan error {
	t.dprintf("remove %s\n", rid)
	msg := &Msg{Op: Tremove, Rid: rid}
	return t.errrpc(rid, "remove", msg, zx.Sremove)
}

func (t *Rfs) RemoveAll(rid string) chan error {
	t.dprintf("removeall %s\n", rid)
	msg := &Msg{Op: Tremoveall, Rid: rid}
	return t.errrpc(rid, "removeall", msg, zx.Sremoveall)
}

func (t *Rfs) Wstat(rid string, d zx.Dir) chan error {
	t.dprintf("wstat %s %v\n", rid, d)
	msg := &Msg{Op: Twstat, Rid: rid, D: d}
	return t.errrpc(rid, "wstat", msg, zx.Swstat)
}

func (t *Rfs) Find(rid, pred, spref, dpref string, depth int) <-chan zx.Dir {
	t.dprintf("find %s '%s' '%s' '%s' %d\n", rid, pred, spref, dpref, depth)
	dc := make(chan zx.Dir)
	msg := &Msg{Op: Tfind, Rid: rid, Pred: pred, Spref: spref, Dpref: dpref, Depth: depth}
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sfind, len(raw))
		reqc <- raw
		close(reqc)
		some := false
		for rep := range repc {
			cs.Send(int64(len(rep)))
			d, _, _ := zx.UnpackDir(rep)
			if d != nil {
				d["addr"] = t.addr
				d["proto"] = "zx"
			}
			if ok := dc <- d; !ok {
				close(repc, cerror(dc))
				break
			}
			some = true
			t.dprintf(rid, "find", "<- %v\n", d)
		}
		if !some {
			dc <- nil
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(dc, err)
		cs.End(err != nil)
	}()
	return dc

}

func (t *Rfs) FindGet(rid, pred, spref, dpref string, depth int) <-chan zx.DirData {
	t.dprintf("findget %s '%s' '%s' '%s' %d\n", rid, pred, spref, dpref, depth)
	dc := make(chan zx.DirData)
	msg := &Msg{Op: Tfindget, Rid: rid, Pred: pred, Spref: spref, Dpref: dpref, Depth: depth}
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sfind, len(raw))
		reqc <- raw
		close(reqc)
		for rep := range repc {
			cs.Send(int64(len(rep)))
			d, _, _ := zx.UnpackDir(rep)
			if d != nil {
				d["addr"] = t.addr
				d["proto"] = "zx"
			}
			res := zx.DirData{Dir: d}
			var datc chan []byte
			if d["err"]=="" && d["type"]=="-" {
				datc = make(chan []byte)
				res.Datac = datc
			}
			if ok := dc <- res; !ok {
				close(repc, cerror(dc))
				break
			}
			t.dprintf(rid, "find", "<- %v\n", d)
			if datc != nil {
				for rep := range repc {
					if len(rep) == 0 {
						break
					}
					if ok := datc <- rep; !ok {
						continue
					}
				}
				close(datc, cerror(repc))
			}
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(dc, err)
	}()
	return dc

}