minikube/third_party/go9p/srv_fcall.go

435 lines
8.0 KiB
Go

// Copyright 2009 The Go9p Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package go9p
import "runtime"
func (srv *Srv) version(req *SrvReq) {
tc := req.Tc
conn := req.Conn
if tc.Msize < IOHDRSZ {
req.RespondError(&Error{"msize too small", EINVAL})
return
}
if tc.Msize < conn.Msize {
conn.Msize = tc.Msize
}
conn.Dotu = tc.Version == "9P2000.u" && srv.Dotu
ver := "9P2000"
if conn.Dotu {
ver = "9P2000.u"
}
/* make sure that the responses of all current requests will be ignored */
conn.Lock()
for tag, r := range conn.reqs {
if tag == NOTAG {
continue
}
for rr := r; rr != nil; rr = rr.next {
rr.Lock()
rr.status |= reqFlush
rr.Unlock()
}
}
conn.Unlock()
req.RespondRversion(conn.Msize, ver)
}
func (srv *Srv) auth(req *SrvReq) {
tc := req.Tc
conn := req.Conn
if tc.Afid == NOFID {
req.RespondError(Eunknownfid)
return
}
req.Afid = conn.FidNew(tc.Afid)
if req.Afid == nil {
req.RespondError(Einuse)
return
}
var user User = nil
if tc.Unamenum != NOUID || conn.Dotu {
user = srv.Upool.Uid2User(int(tc.Unamenum))
} else if tc.Uname != "" {
user = srv.Upool.Uname2User(tc.Uname)
}
if runtime.GOOS != "windows" {
if user == nil {
req.RespondError(Enouser)
return
}
}
req.Afid.User = user
req.Afid.Type = QTAUTH
if aop, ok := (srv.ops).(AuthOps); ok {
aqid, err := aop.AuthInit(req.Afid, tc.Aname)
if err != nil {
req.RespondError(err)
} else {
aqid.Type |= QTAUTH // just in case
req.RespondRauth(aqid)
}
} else {
req.RespondError(Enoauth)
}
}
func (srv *Srv) authPost(req *SrvReq) {
if req.Rc != nil && req.Rc.Type == Rauth {
req.Afid.IncRef()
}
}
func (srv *Srv) attach(req *SrvReq) {
tc := req.Tc
conn := req.Conn
if tc.Fid == NOFID {
req.RespondError(Eunknownfid)
return
}
req.Fid = conn.FidNew(tc.Fid)
if req.Fid == nil {
req.RespondError(Einuse)
return
}
if tc.Afid != NOFID {
req.Afid = conn.FidGet(tc.Afid)
if req.Afid == nil {
req.RespondError(Eunknownfid)
}
}
var user User = nil
if tc.Unamenum != NOUID || conn.Dotu {
user = srv.Upool.Uid2User(int(tc.Unamenum))
} else if tc.Uname != "" {
user = srv.Upool.Uname2User(tc.Uname)
}
if runtime.GOOS != "windows" {
if user == nil {
req.RespondError(Enouser)
return
}
}
req.Fid.User = user
if aop, ok := (srv.ops).(AuthOps); ok {
err := aop.AuthCheck(req.Fid, req.Afid, tc.Aname)
if err != nil {
req.RespondError(err)
return
}
}
(srv.ops).(SrvReqOps).Attach(req)
}
func (srv *Srv) attachPost(req *SrvReq) {
if req.Rc != nil && req.Rc.Type == Rattach {
req.Fid.Type = req.Rc.Qid.Type
req.Fid.IncRef()
}
}
func (srv *Srv) flush(req *SrvReq) {
conn := req.Conn
tag := req.Tc.Oldtag
PackRflush(req.Rc)
conn.Lock()
r := conn.reqs[tag]
if r != nil {
req.flushreq = r.flushreq
r.flushreq = req
}
conn.Unlock()
if r == nil {
// there are no requests with that tag
req.Respond()
return
}
r.Lock()
status := r.status
if (status & (reqWork | reqSaved)) == 0 {
/* the request is not worked on yet */
r.status |= reqFlush
}
r.Unlock()
if (status & (reqWork | reqSaved)) == 0 {
r.Respond()
} else {
if op, ok := (srv.ops).(FlushOp); ok {
op.Flush(r)
}
}
}
func (srv *Srv) walk(req *SrvReq) {
conn := req.Conn
tc := req.Tc
fid := req.Fid
/* we can't walk regular files, only clone them */
if len(tc.Wname) > 0 && (fid.Type&QTDIR) == 0 {
req.RespondError(Enotdir)
return
}
/* we can't walk open files */
if fid.opened {
req.RespondError(Ebaduse)
return
}
if tc.Fid != tc.Newfid {
req.Newfid = conn.FidNew(tc.Newfid)
if req.Newfid == nil {
req.RespondError(Einuse)
return
}
req.Newfid.User = fid.User
req.Newfid.Type = fid.Type
} else {
req.Newfid = req.Fid
req.Newfid.IncRef()
}
(req.Conn.Srv.ops).(SrvReqOps).Walk(req)
}
func (srv *Srv) walkPost(req *SrvReq) {
rc := req.Rc
if rc == nil || rc.Type != Rwalk || req.Newfid == nil {
return
}
n := len(rc.Wqid)
if n > 0 {
req.Newfid.Type = rc.Wqid[n-1].Type
} else {
req.Newfid.Type = req.Fid.Type
}
// Don't retain the fid if only a partial walk succeeded
if n != len(req.Tc.Wname) {
return
}
if req.Newfid.fid != req.Fid.fid {
req.Newfid.IncRef()
}
}
func (srv *Srv) open(req *SrvReq) {
fid := req.Fid
tc := req.Tc
if fid.opened {
req.RespondError(Eopen)
return
}
if (fid.Type&QTDIR) != 0 && tc.Mode != OREAD {
req.RespondError(Eperm)
return
}
fid.Omode = tc.Mode
(req.Conn.Srv.ops).(SrvReqOps).Open(req)
}
func (srv *Srv) openPost(req *SrvReq) {
if req.Fid != nil {
req.Fid.opened = req.Rc != nil && req.Rc.Type == Ropen
}
}
func (srv *Srv) create(req *SrvReq) {
fid := req.Fid
tc := req.Tc
if fid.opened {
req.RespondError(Eopen)
return
}
if (fid.Type & QTDIR) == 0 {
req.RespondError(Enotdir)
return
}
/* can't open directories for other than reading */
if (tc.Perm&DMDIR) != 0 && tc.Mode != OREAD {
req.RespondError(Eperm)
return
}
/* can't create special files if not 9P2000.u */
if (tc.Perm&(DMNAMEDPIPE|DMSYMLINK|DMLINK|DMDEVICE|DMSOCKET)) != 0 && !req.Conn.Dotu {
req.RespondError(Eperm)
return
}
fid.Omode = tc.Mode
(req.Conn.Srv.ops).(SrvReqOps).Create(req)
}
func (srv *Srv) createPost(req *SrvReq) {
if req.Rc != nil && req.Rc.Type == Rcreate && req.Fid != nil {
req.Fid.Type = req.Rc.Qid.Type
req.Fid.opened = true
}
}
func (srv *Srv) read(req *SrvReq) {
tc := req.Tc
fid := req.Fid
if tc.Count+IOHDRSZ > req.Conn.Msize {
req.RespondError(Etoolarge)
return
}
if (fid.Type & QTAUTH) != 0 {
var n int
rc := req.Rc
err := InitRread(rc, tc.Count)
if err != nil {
req.RespondError(err)
return
}
if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
n, err = op.AuthRead(fid, tc.Offset, rc.Data)
if err != nil {
req.RespondError(err)
return
}
SetRreadCount(rc, uint32(n))
req.Respond()
} else {
req.RespondError(Enotimpl)
}
return
}
if (fid.Type & QTDIR) != 0 {
if tc.Offset == 0 {
fid.Diroffset = 0
} else if tc.Offset != fid.Diroffset {
fid.Diroffset = tc.Offset
}
}
(req.Conn.Srv.ops).(SrvReqOps).Read(req)
}
func (srv *Srv) readPost(req *SrvReq) {
if req.Rc != nil && req.Rc.Type == Rread && (req.Fid.Type&QTDIR) != 0 {
req.Fid.Diroffset += uint64(req.Rc.Count)
}
}
func (srv *Srv) write(req *SrvReq) {
fid := req.Fid
tc := req.Tc
if (fid.Type & QTAUTH) != 0 {
tc := req.Tc
if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
n, err := op.AuthWrite(req.Fid, tc.Offset, tc.Data)
if err != nil {
req.RespondError(err)
} else {
req.RespondRwrite(uint32(n))
}
} else {
req.RespondError(Enotimpl)
}
return
}
if !fid.opened || (fid.Type&QTDIR) != 0 || (fid.Omode&3) == OREAD {
req.RespondError(Ebaduse)
return
}
if tc.Count+IOHDRSZ > req.Conn.Msize {
req.RespondError(Etoolarge)
return
}
(req.Conn.Srv.ops).(SrvReqOps).Write(req)
}
func (srv *Srv) clunk(req *SrvReq) {
fid := req.Fid
if (fid.Type & QTAUTH) != 0 {
if op, ok := (req.Conn.Srv.ops).(AuthOps); ok {
op.AuthDestroy(fid)
req.RespondRclunk()
} else {
req.RespondError(Enotimpl)
}
return
}
(req.Conn.Srv.ops).(SrvReqOps).Clunk(req)
}
func (srv *Srv) clunkPost(req *SrvReq) {
if req.Rc != nil && req.Rc.Type == Rclunk && req.Fid != nil {
req.Fid.DecRef()
}
}
func (srv *Srv) remove(req *SrvReq) { (req.Conn.Srv.ops).(SrvReqOps).Remove(req) }
func (srv *Srv) removePost(req *SrvReq) {
if req.Rc != nil && req.Fid != nil {
req.Fid.DecRef()
}
}
func (srv *Srv) stat(req *SrvReq) { (req.Conn.Srv.ops).(SrvReqOps).Stat(req) }
func (srv *Srv) wstat(req *SrvReq) {
/*
fid := req.Fid
d := &req.Tc.Dir
if d.Type != uint16(0xFFFF) || d.Dev != uint32(0xFFFFFFFF) || d.Version != uint32(0xFFFFFFFF) ||
d.Path != uint64(0xFFFFFFFFFFFFFFFF) {
req.RespondError(Eperm)
return
}
if (d.Mode != 0xFFFFFFFF) && (((fid.Type&QTDIR) != 0 && (d.Mode&DMDIR) == 0) ||
((d.Type&QTDIR) == 0 && (d.Mode&DMDIR) != 0)) {
req.RespondError(Edirchange)
return
}
*/
(req.Conn.Srv.ops).(SrvReqOps).Wstat(req)
}