コード例 #1
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (sfs *NopSrv) Stat(req *go9p.SrvReq) {
	fid := req.Fid.Aux.(Dispatcher)
	if sfs.Debuglevel > 0 {
		log.Printf("stat %s", fid)
	}
	req.RespondRstat(Fstat(fid))
}
コード例 #2
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (sfs *NopSrv) Open(req *go9p.SrvReq) {
	fid := req.Fid.Aux.(Dispatcher)
	if sfs.Debuglevel > 0 {
		log.Printf("open %s", fid)
	}
	req.RespondRopen(Qid(fid), 0)
}
コード例 #3
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (sfs *NopSrv) Read(req *go9p.SrvReq) {
	fid := req.Fid.Aux.(Dispatcher)
	tc := req.Tc
	rc := req.Rc

	if sfs.Debuglevel > 0 {
		log.Printf("read %T %s %d:%d", fid, fid, tc.Offset, tc.Count)
	}

	buf, err := fid.Read(req)
	if err != nil {
		req.RespondError(toError(err))
		return
	}

	go9p.InitRread(rc, tc.Count)
	count := 0
	switch {
	case tc.Offset > uint64(len(buf)):
		count = 0
	case len(buf[tc.Offset:]) > int(tc.Count):
		count = int(tc.Count)
	default:
		count = len(buf[tc.Offset:])
	}

	copy(rc.Data, buf[tc.Offset:int(tc.Offset)+count])
	go9p.SetRreadCount(rc, uint32(count))
	req.Respond()
}
コード例 #4
0
ファイル: p9.go プロジェクト: flynn/bake
func (fs *fileSystem) readFile(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)

	n, err := aux.file.ReadAt(req.Rc.Data, int64(req.Tc.Offset))
	if err != nil && err != io.EOF {
		req.RespondError(toError(err))
		return
	}

	go9p.SetRreadCount(req.Rc, uint32(n))
	req.Respond()
}
コード例 #5
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (sfs *NopSrv) Attach(req *go9p.SrvReq) {
	if req.Afid != nil {
		req.RespondError(go9p.Enoauth)
		return
	}

	req.Fid.Aux = sfs.Root
	if sfs.Debuglevel > 0 {
		log.Printf("attach")
	}

	req.RespondRattach(Qid(sfs.Root))
}
コード例 #6
0
ファイル: p9.go プロジェクト: flynn/bake
// Attach creates a file handle on the file system.
func (fs *fileSystem) Attach(req *go9p.SrvReq) {
	rootID, filename := split(req.Tc.Aname)
	aux := &Aux{
		rootID: rootID,
		path:   path.Join(fs.path, filename),
	}
	req.Fid.Aux = aux

	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	req.RespondRattach(aux.qid())
}
コード例 #7
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (sfs *NopSrv) Write(req *go9p.SrvReq) {
	fid := req.Fid.Aux.(Dispatcher)
	tc := req.Tc
	if sfs.Debuglevel > 0 {
		log.Printf("write: %f", fid)
	}

	e := fid.Write(req, tc.Data)
	if e != nil {
		req.RespondError(toError(e))
		return
	}

	req.RespondRwrite(uint32(len(tc.Data)))
}
コード例 #8
0
ファイル: p9.go プロジェクト: flynn/bake
// Read reads data from a file handle.
func (fs *fileSystem) Read(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	// Add to readset.
	fs.addToReadset(aux.rootID, aux.path)

	go9p.InitRread(req.Rc, req.Tc.Count)
	if aux.st.IsDir() {
		fs.readDir(req)
		return
	}
	fs.readFile(req)
}
コード例 #9
0
ファイル: p9.go プロジェクト: flynn/bake
// Open opens a local file.
func (fs *fileSystem) Open(req *go9p.SrvReq) {
	// Stat file handle.
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	// Open local file handle.
	file, err := os.OpenFile(aux.path, omode2uflags(req.Tc.Mode), 0)
	if err != nil {
		req.RespondError(toError(err))
		return
	}
	aux.file = file

	// Add to appropriate set.
	if req.Tc.Mode&go9p.OREAD != 0 {
		fs.addToReadset(aux.rootID, aux.path)
	} else if req.Tc.Mode&go9p.OWRITE != 0 {
		fs.addToWriteset(aux.rootID, aux.path)
	} else if req.Tc.Mode&go9p.ORDWR != 0 {
		fs.addToReadset(aux.rootID, aux.path)
		fs.addToWriteset(aux.rootID, aux.path)
	}

	req.RespondRopen(aux.qid(), 0)
}
コード例 #10
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (sfs *NopSrv) Walk(req *go9p.SrvReq) {
	fid := req.Fid.Aux.(Dispatcher)
	tc := req.Tc

	if sfs.Debuglevel > 0 {
		log.Printf("walk %s %s", fid, tc.Wname)
	}

	if req.Newfid.Aux == nil {
		req.Newfid.Aux = fid.Clone()
	}

	if len(tc.Wname) == 0 {
		w := make([]go9p.Qid, 0)
		req.RespondRwalk(w)
	} else {
		nfid, err := fid.Walk(req, tc.Wname[0])
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		req.Newfid.Aux = nfid
		w := []go9p.Qid{*Qid(nfid)}
		req.RespondRwalk(w)
	}
}
コード例 #11
0
ファイル: p9.go プロジェクト: flynn/bake
func (fs *fileSystem) Walk(req *go9p.SrvReq) {
	// Stat the file.
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	// Create a new file handle, if necessary.
	if req.Newfid.Aux == nil {
		req.Newfid.Aux = &Aux{rootID: aux.rootID}
	}

	nfid := req.Newfid.Aux.(*Aux)
	wqids := make([]go9p.Qid, 0, len(req.Tc.Wname))
	newPath := aux.path

	// Append actual files after the root.
	for i, name := range req.Tc.Wname {
		// If we have no root then the first segment is the root ID.
		if nfid.rootID == "" {
			nfid.rootID = name
			if root := (*FileSystem)(fs).Root(nfid.rootID); root == nil {
				req.RespondError(go9p.Enoent)
				return
			}
			wqids = append(wqids, *newRootQid(nfid.rootID))
			continue
		}

		// Otherwise we're already walking a root so continue to traverse the files.
		p := newPath + "/" + name
		st, err := os.Lstat(p)
		if err != nil {
			if i == 0 {
				req.RespondError(go9p.Enoent)
				return
			}
			break
		}

		wqids = append(wqids, *newQid(st))
		newPath = p
	}

	nfid.path = newPath
	req.RespondRwalk(wqids)
}
コード例 #12
0
ファイル: p9.go プロジェクト: flynn/bake
func (fs *fileSystem) readDir(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)

	var n int
	if req.Tc.Offset == 0 {
		// If we got here, it was open. Can't really seek
		// in most cases, just close and reopen it.
		aux.file.Close()

		file, err := os.OpenFile(aux.path, omode2uflags(req.Fid.Omode), 0)
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		aux.file = file

		dirs, e := aux.file.Readdir(-1)
		if e != nil {
			req.RespondError(toError(e))
			return
		}
		aux.dirs = dirs

		aux.dirents = nil
		aux.direntends = nil
		for _, dir := range aux.dirs {
			path := aux.path + "/" + dir.Name()
			st, _ := new9pDir(path, dir, req.Conn.Dotu, req.Conn.Srv.Upool)
			if st == nil {
				continue
			}

			b := go9p.PackDir(st, req.Conn.Dotu)
			aux.dirents = append(aux.dirents, b...)
			n += len(b)
			aux.direntends = append(aux.direntends, n)
		}
	}

	switch {
	case req.Tc.Offset > uint64(len(aux.dirents)):
		n = 0
	case len(aux.dirents[req.Tc.Offset:]) > int(req.Tc.Count):
		n = int(req.Tc.Count)
	default:
		n = len(aux.dirents[req.Tc.Offset:])
	}

	copy(req.Rc.Data, aux.dirents[req.Tc.Offset:int(req.Tc.Offset)+n])

	go9p.SetRreadCount(req.Rc, uint32(n))
	req.Respond()
}
コード例 #13
0
ファイル: p9.go プロジェクト: flynn/bake
func (fs *fileSystem) Stat(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	st, err := new9pDir(aux.path, aux.st, req.Conn.Dotu, req.Conn.Srv.Upool)
	if st == nil {
		req.RespondError(err)
		return
	}

	req.RespondRstat(st)
}
コード例 #14
0
ファイル: p9.go プロジェクト: flynn/bake
func (fs *fileSystem) Remove(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	// Add to writeset.
	fs.addToWriteset(aux.rootID, aux.path)

	if err := os.Remove(aux.path); err != nil {
		req.RespondError(toError(err))
		return
	}

	req.RespondRremove()
}
コード例 #15
0
ファイル: p9.go プロジェクト: flynn/bake
// Write writes data to a file.
func (fs *fileSystem) Write(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	// Add to writeset.
	fs.addToWriteset(aux.rootID, aux.path)

	n, err := aux.file.WriteAt(req.Tc.Data, int64(req.Tc.Offset))
	if err != nil {
		req.RespondError(toError(err))
		return
	}

	req.RespondRwrite(uint32(n))
}
コード例 #16
0
ファイル: p9.go プロジェクト: flynn/bake
// Wstat updates file info.
func (fs *fileSystem) Wstat(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	// Add to writeset.
	fs.addToWriteset(aux.rootID, aux.path)

	dir := &req.Tc.Dir
	if dir.Mode != 0xFFFFFFFF {
		mode := dir.Mode & 0777
		if req.Conn.Dotu {
			if dir.Mode&go9p.DMSETUID > 0 {
				mode |= syscall.S_ISUID
			}
			if dir.Mode&go9p.DMSETGID > 0 {
				mode |= syscall.S_ISGID
			}
		}

		err := os.Chmod(aux.path, os.FileMode(mode))
		if err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	uid, gid := go9p.NOUID, go9p.NOUID
	if req.Conn.Dotu {
		uid = dir.Uidnum
		gid = dir.Gidnum
	}

	// Try to find local uid, gid by name.
	if (dir.Uid != "" || dir.Gid != "") && !req.Conn.Dotu {
		var err error
		uid, err = lookupUser(dir.Uid)
		if err != nil {
			req.RespondError(err)
			return
		}

		gid, err = lookupGroup(dir.Gid)
		if err != nil {
			req.RespondError(err)
			return
		}
	}

	if uid != go9p.NOUID || gid != go9p.NOUID {
		err := os.Chown(aux.path, int(uid), int(gid))
		if err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	if dir.Name != "" {
		// if first char is / it is relative to root, else relative to cwd.
		var destpath string
		if dir.Name[0] == '/' {
			destpath = path.Join(fs.path, dir.Name)
			fmt.Printf("/ results in %s\n", destpath)
		} else {
			auxdir, _ := path.Split(aux.path)
			destpath = path.Join(auxdir, dir.Name)
			fmt.Printf("rel  results in %s\n", destpath)
		}
		err := syscall.Rename(aux.path, destpath)
		fmt.Printf("rename %s to %s gets %v\n", aux.path, destpath, err)
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		aux.path = destpath
	}

	// Set file size, if specified.
	if dir.Length != 0xFFFFFFFFFFFFFFFF {
		if err := os.Truncate(aux.path, int64(dir.Length)); err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	// If either mtime or atime need to be changed, then we must change both.
	if dir.Mtime != ^uint32(0) || dir.Atime != ^uint32(0) {
		mtime := time.Unix(int64(dir.Mtime), 0)
		atime := time.Unix(int64(dir.Atime), 0)

		mtimeChanged := (dir.Mtime == ^uint32(0))
		atimeChanged := (dir.Atime == ^uint32(0))
		if mtimeChanged || atimeChanged {
			st, err := os.Stat(aux.path)
			if err != nil {
				req.RespondError(toError(err))
				return
			} else if mtimeChanged {
				mtime = st.ModTime()
			}
		}
		if err := os.Chtimes(aux.path, atime, mtime); err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	req.RespondRwstat()
}
コード例 #17
0
ファイル: p9.go プロジェクト: flynn/bake
// Create creates a new file.
func (fs *fileSystem) Create(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	path := aux.path + "/" + req.Tc.Name

	var file *os.File
	var err error
	switch {
	case req.Tc.Perm&go9p.DMDIR != 0:
		err = os.Mkdir(path, os.FileMode(req.Tc.Perm&0777))

	case req.Tc.Perm&go9p.DMSYMLINK != 0:
		err = os.Symlink(req.Tc.Ext, path)

	case req.Tc.Perm&go9p.DMLINK != 0:
		n, err := strconv.ParseUint(req.Tc.Ext, 10, 0)
		if err != nil {
			break
		}

		ofid := req.Conn.FidGet(uint32(n))
		if ofid == nil {
			req.RespondError(go9p.Eunknownfid)
			return
		}

		err = os.Link(ofid.Aux.(*Aux).path, path)
		ofid.DecRef()

	case req.Tc.Perm&go9p.DMNAMEDPIPE != 0:
	case req.Tc.Perm&go9p.DMDEVICE != 0:
		req.RespondError(&go9p.Error{"not implemented", go9p.EIO})
		return

	default:
		var mode uint32 = req.Tc.Perm & 0777
		if req.Conn.Dotu {
			if req.Tc.Perm&go9p.DMSETUID > 0 {
				mode |= syscall.S_ISUID
			}
			if req.Tc.Perm&go9p.DMSETGID > 0 {
				mode |= syscall.S_ISGID
			}
		}
		file, err = os.OpenFile(path, omode2uflags(req.Tc.Mode)|os.O_CREATE, os.FileMode(mode))
	}

	if file == nil && err == nil {
		file, err = os.OpenFile(path, omode2uflags(req.Tc.Mode), 0)
	}

	if err != nil {
		req.RespondError(toError(err))
		return
	}

	aux.path = path
	aux.file = file

	// Save file to writeset.
	fs.addToWriteset(aux.rootID, path)

	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	req.RespondRcreate(aux.qid(), 0)
}
コード例 #18
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (*NopSrv) Wstat(req *go9p.SrvReq) {
	//	log.Printf("wstat: %p", req)
	//	req.RespondError(errors.New("wstat: ..."))
	req.RespondRwstat()
}
コード例 #19
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (*NopSrv) Remove(req *go9p.SrvReq) {
	log.Printf("remove: %p", req)
	req.RespondError(errors.New("remove: ..."))
}
コード例 #20
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (*NopSrv) Clunk(req *go9p.SrvReq) {
	req.RespondRclunk()
}
コード例 #21
0
ファイル: nopfs.go プロジェクト: wwaites/nopfs
func (*NopSrv) Create(req *go9p.SrvReq) {
	log.Printf("create: %p", req)
	req.RespondError(errors.New("create: ..."))
}
コード例 #22
0
ファイル: p9.go プロジェクト: flynn/bake
func (fs *fileSystem) Clunk(req *go9p.SrvReq) { req.RespondRclunk() }