Пример #1
0
func (c *ClientConn) readfile(fc *plan9.Fcall, ref *fileRef) *plan9.Fcall {
	size, err := c.explorer.Sizeof(ref.Path)
	if err != nil {
		return c.unexpectedErr(fc, err)
	}
	if size > 0 && fc.Offset >= size {
		// trying to reading past the end of file.
		// return count == 0 to signal EOF to client
		fc.Count = 0
		return fc
	}
	fc.Data = allocBuffer(min(int(c.iounit), int(fc.Count), int(size)))
	defer discardBuffer(fc.Data)
	n, err := c.explorer.Read(fc.Data, fc.Offset, ref.Path)
	if err == io.EOF {
		if n == 0 {
			// returned EOF without reading anything, should return fc.Count = 0
			discardBuffer(fc.Data)
			fc.Data = nil
			err = nil
			return fc
		} else {
			// was able to read som data from the file, should return the count
			// but not the error. The next call to read will trigger the EOF
			err = nil
		}
	}
	if err != nil {
		return c.unexpectedErr(fc, err)
	}
	fc.Count = uint32(n)
	fc.Data = fc.Data[:fc.Count]
	return fc
}
Пример #2
0
func (c *ClientConn) attach(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rattach
	fc.Iounit = c.iounit
	fref, _ := c.createFileRef(c.explorer.Root(), FTDIR, 0)
	fc.Qid = fref.Qid
	c.bindFid(fc.Fid, fc.Qid.Path)
	return fc
}
Пример #3
0
func (c *ClientConn) walk(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rwalk
	fref, has := c.fidRef(fc.Fid)
	if !has {
		return c.invalidFidErr(fc)
	}
	if _, has := c.fidRef(fc.Newfid); has {
		return c.fidUsedErr(fc)
	}
	current := fref.Path
	for idx, name := range fc.Wname {
		var ft FileType
		if current == 0 {
			return c.fileNotFoundErr(fc)
		}
		if ff, ok := c.explorer.(FileFinder); ok {
			f, err := ff.FindInDir(current, name)
			if err != nil {
				return c.unexpectedErr(fc, err)
			}
			current = f.Path
		} else {
			childs, err := c.explorer.ListDir(current)
			if err != nil {
				return c.unexpectedErr(fc, err)
			}
			idx, have := childs.FindExact(name)
			if !have {
				return c.fileNotFoundErr(fc)
			}
			current = childs[idx].Path
		}
		ref, err := c.createFileRef(current, ft, 0)
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		fc.Wqid = append(fc.Wqid, ref.Qid)

		// if the last match isn't a directory, there is no need to find
		// another part of the path
		//
		// so, just break here
		if ft == FTFILE && idx != len(fc.Wname)-1 {
			return c.fileNotFoundErr(fc)
		}
	}
	if len(fc.Wqid) == 0 {
		// newfid and fid will map to the same file
		if fc.Newfid != fc.Fid {
			c.bindFid(fc.Newfid, fref.Path)
		}
	} else {
		// make a bind between the last qid and the new fid
		c.bindFid(fc.Newfid, fc.Wqid[len(fc.Wqid)-1].Path)
	}
	return fc
}
Пример #4
0
func (c *ClientConn) write(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rwrite
	if fref, have := c.fidRef(fc.Fid); have {
		n, err := c.explorer.Write(fref.Path, fc.Data, fc.Offset)
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		fc.Count = uint32(n)
		return fc
	}
	return c.invalidFidErr(fc)
}
Пример #5
0
func (c *ClientConn) open(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Ropen
	if fref, has := c.fidRef(fc.Fid); has {
		err := c.explorer.Open(fref.Path, FileMode(fc.Mode))
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		fc.Iounit = c.iounit
		fc.Qid = fref.Qid
		return fc
	}
	return c.invalidFidErr(fc)
}
Пример #6
0
func (c *ClientConn) read(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rread
	if fref, has := c.fidRef(fc.Fid); has {
		if fref.IsDir() {
			return c.readdir(fc, fref)
		}
		return c.readfile(fc, fref)
	}
	return c.invalidFidErr(fc)
}
Пример #7
0
func (c *ClientConn) readdir(fc *plan9.Fcall, ref *fileRef) *plan9.Fcall {
	// if the call have an offset, return 0
	// since all readdir call's will return the full directory
	if fc.Offset > 0 {
		fc.Count = 0
		return fc
	}
	childs, err := c.explorer.ListDir(ref.Path)
	if err != nil {
		return c.unexpectedErr(fc, err)
	}
	tmpBuf := allocBuffer(int(c.iounit))
	out := bytes.NewBuffer(tmpBuf[:0])
	defer discardBuffer(tmpBuf)
	for _, id := range childs {
		stat, err := c.explorer.Stat(id.Path)
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		dir := plan9.Dir{
			Qid:    plan9.Qid{Type: uint8(stat.Type), Vers: stat.Version, Path: id.Path},
			Mode:   plan9.Perm(stat.Mode),
			Atime:  stat.Atime,
			Mtime:  stat.Mtime,
			Length: stat.Size,
			Uid:    stat.Uname,
			Gid:    stat.Gname,
			Name:   stat.Name,
		}
		buf, err := dir.Bytes()
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		_, err = out.Write(buf)
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
	}
	fc.Count = uint32(len(fc.Data))
	fc.Data = out.Bytes()
	return fc
}
Пример #8
0
func (c *ClientConn) clunk(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rclunk
	oldpath, had := c.unbindFid(fc.Fid)
	if had {
		err := c.explorer.Close(oldpath)
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
	}
	return fc
}
Пример #9
0
func (c *ClientConn) create(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rcreate
	if fref, have := c.fidRef(fc.Fid); have {
		file := File{Name: fc.Name}
		file.Type = FileType(fc.Mode)
		path, err := c.explorer.Create(fref.Path, file, uint32(fc.Perm))
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		cref, err := c.createFileRef(path, file.Type, 0)
		if err != nil {
			return c.unexpectedErr(fc, err)
		}
		fc.Iounit = c.iounit
		fc.Qid = cref.Qid
		c.unbindFid(fc.Fid)
		c.bindFid(fc.Fid, cref.Path)
		return fc
	}
	return c.invalidFidErr(fc)
}
Пример #10
0
func (c *ClientConn) process(fc *plan9.Fcall, out chan *plan9.Fcall) {
	println(">>>\t", fc.String())
	switch fc.Type {
	case plan9.Tversion:
		fc = c.version(fc)
	case plan9.Tattach:
		fc = c.attach(fc)
	case plan9.Twalk:
		fc = c.walk(fc)
	case plan9.Topen:
		fc = c.open(fc)
	case plan9.Tread:
		fc = c.read(fc)
	case plan9.Tclunk:
		fc = c.clunk(fc)
	case plan9.Tcreate:
		fc = c.create(fc)
	case plan9.Twrite:
		fc = c.write(fc)
	case plan9.Tauth:
		fc = noauth(fc)
	default:
		println("!!!\t", fc.String())
		fc = nil
	}
	if fc != nil {
		println("<<<\t", fc.String())
	}
	out <- fc
}
Пример #11
0
func (c *ClientConn) unexpectedErr(fc *plan9.Fcall, err error) *plan9.Fcall {
	fc.Type = plan9.Rerror
	fc.Ename = err.Error()
	return fc
}
Пример #12
0
func (c *ClientConn) fidUsedErr(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rerror
	fc.Ename = "fid in use"
	return fc
}
Пример #13
0
func (c *ClientConn) fileNotFoundErr(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rerror
	fc.Ename = "file not found"
	return fc
}
Пример #14
0
func (c *ClientConn) invalidFidErr(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rerror
	fc.Ename = "fid not found"
	return fc
}
Пример #15
0
func (c *ClientConn) version(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rversion
	fc.Version = "9P2000"
	return fc
}
Пример #16
0
func noauth(fc *plan9.Fcall) *plan9.Fcall {
	fc.Type = plan9.Rerror
	fc.Ename = "no auth requried"
	return fc
}