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)) }
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) }
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() }
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() }
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)) }
// 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()) }
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))) }
// 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) }
// 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) }
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) } }
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) }
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() }
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) }
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() }
// 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)) }
// 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() }
// 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) }
func (*NopSrv) Wstat(req *go9p.SrvReq) { // log.Printf("wstat: %p", req) // req.RespondError(errors.New("wstat: ...")) req.RespondRwstat() }
func (*NopSrv) Remove(req *go9p.SrvReq) { log.Printf("remove: %p", req) req.RespondError(errors.New("remove: ...")) }
func (*NopSrv) Clunk(req *go9p.SrvReq) { req.RespondRclunk() }
func (*NopSrv) Create(req *go9p.SrvReq) { log.Printf("create: %p", req) req.RespondError(errors.New("create: ...")) }
func (fs *fileSystem) Clunk(req *go9p.SrvReq) { req.RespondRclunk() }