コード例 #1
0
ファイル: ops.go プロジェクト: Christopheraburns/clive
// Walk to rid, and return it r/wlocked (unless there's an error) with at least its meta updated.
func (fs *Cfs) walk(rid string, isrlock bool) (f *cFile, left []string, e error) {
	fs.dprintf("walk %s...\n", rid)
	els := zx.Elems(rid)
	left = els
	defer func() {
		if e != nil {
			fs.dprintf("walkerr %s left %v\n", rid, left)
		} else {
			fs.dprintf("walked %s left %v\n", rid, left)
		}
		if e == nil && len(left) > 0 {
			panic("cfs walk: left and no error")
		}
	}()
	path := "/"
	for {
		isr := len(els) > 0 || isrlock
		nf, err := fs.cwalk(path, isr)
		if err != nil {
			return f, left, err
		}
		left = els
		f = nf
		if len(els) > 0 {
			path = zx.Path(path, els[0])
			els = els[1:]
		}
		if len(left) == 0 {
			if err := f.needMeta(isr); err != nil {
				// lock has been released
				if dbg.IsNotExist(err) {
					// discovered in needMeta that the file is gone
					// we raced, so try again
					f, left, err = fs.walk(rid, isrlock)
				}
				return f, left, err
			}
			return f, left, nil
		}
		if err := f.needData(isr, nil); err != nil {
			// lock has been released
			if dbg.IsNotExist(err) {
				// discovered in needMeta that the file is gone
				// we raced, so try again
				f, left, err = fs.walk(rid, isrlock)
			}
			return f, left, err
		}
		if !fs.NoPermCheck && !f.d.CanWalk(fs.ai) {
			f.unlockc(isr)
			return f, left, fmt.Errorf("%s: %s", f, dbg.ErrPerm)
		}
		f.unlockc(isr)
	}
}
コード例 #2
0
ファイル: sync.go プロジェクト: Christopheraburns/clive
func (c *FileInfo) syncDel() {
	if c.path == "" || c.path == "/" {
		panic("sync: DEL /")
		return
	}
	// There's a potential problem if a file was created remotelly
	// since we removed a subtree locally, but it's a race anyway.
	err := <- c.rfs.RemoveAll(c.path)
	if err != nil && !dbg.IsNotExist(err) {
		c.dprintf("%s: sync del: %s\n", c.path, err)
		c.state = CUnread
	}
	c.wasdel = false
}
コード例 #3
0
ファイル: vfs.go プロジェクト: Christopheraburns/clive
func (t *Fs) put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) error {
	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.(Walker)
	if !ok {
		return fmt.Errorf("%s: %s", pd["path"], dbg.ErrPerm)
	}
	f, err := wpf.Walk(path.Base(rid))
	if err != nil && !dbg.IsNotExist(err) {
		return err
	}
	if err != nil {
		if err := t.matchDir(rid, nil, pred); err != nil {
			return err
		}
		if !t.NoPermCheck && !pd.CanWrite(t.ai) {
			return fmt.Errorf("%s: %s", rid, dbg.ErrPerm)
		}
		if putf, ok := pf.(Putter); ok {
			return putf.Put(path.Base(rid), d, off, dc)
		}
		return fmt.Errorf("%s: %s", pd["path"], dbg.ErrPerm)
	} else {
		d, err := f.Stat()
		if err != nil {
			return err
		}
		if d["type"] == "d" {
			return fmt.Errorf("%s: %s", rid, dbg.ErrIsDir)
		}
		if err := t.matchDir(rid, d, pred); err != nil {
			return err
		}
		if !t.NoPermCheck && !d.CanWrite(t.ai) {
			return fmt.Errorf("%s: %s", rid, dbg.ErrPerm)
		}
		if putf, ok := f.(Putter); ok {
			return putf.Put("", d, off, dc)
		}
		return fmt.Errorf("%s: %s", d["path"], dbg.ErrPerm)
	}
}
コード例 #4
0
ファイル: vfs.go プロジェクト: Christopheraburns/clive
func (t *Fs) match(d zx.Dir, err error, rid, fpred string) error {
	if fpred == "" {
		return nil
	}
	if err != nil {
		if dbg.IsNotExist(err) {
			d = zx.Dir{
				"path": rid,
				"name": path.Base(rid),
				"type": "-",
			}
			return t.matchDir(rid, d, fpred)
		}
		return err
	}
	return t.matchDir(rid, d, fpred)
}
コード例 #5
0
ファイル: lfs.go プロジェクト: Christopheraburns/clive
func (t *Lfs) match(rid string, fpred string) error {
	if fpred == "" {
		return nil
	}
	d, err := t.stat(rid)
	if err != nil {
		if dbg.IsNotExist(err) {
			d := zx.Dir{
				"path": rid,
				"name": path.Base(rid),
				"type": "-",
			}
			return t.matchDir(d, fpred)
		}
		return err
	}
	return t.matchDir(d, fpred)
}
コード例 #6
0
ファイル: mfs.go プロジェクト: Christopheraburns/clive
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
}
コード例 #7
0
ファイル: mfs.go プロジェクト: Christopheraburns/clive
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
}