commit 162030d36b2f4a9de344d0bb83ddc04e5ebf548c
parent a65b8e19365e83970ee05585c3673a05931710b0
Author: Matsuda Kenji <info@mtkn.jp>
Date: Fri, 15 Sep 2023 08:51:07 +0900
add mkdir
Diffstat:
| M | diskfs/file.go | | | 21 | ++++++++++++--------- |
| M | server.go | | | 103 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
2 files changed, 65 insertions(+), 59 deletions(-)
diff --git a/diskfs/file.go b/diskfs/file.go
@@ -185,9 +185,16 @@ func (f *File) Create(name string, uid string,
}
ospath := path.Join(f.fs.rootPath, f.path, name)
- osfile, err := os.Create(ospath)
- if err != nil {
- return nil, fmt.Errorf("create: %v", err)
+ if perm&lib9p.DMDIR != 0 {
+ if err := os.Mkdir(ospath, lib9p.Mode9ToFSMode(perm)); err != nil {
+ return nil, fmt.Errorf("mkdir: %v", err)
+ }
+ } else {
+ osfile, err := os.Create(ospath)
+ if err != nil {
+ return nil, fmt.Errorf("create: %v", err)
+ }
+ osfile.Close()
}
usr, err := user.Lookup(uid)
@@ -206,18 +213,14 @@ func (f *File) Create(name string, uid string,
if err != nil {
return nil, fmt.Errorf("convert gid: %v", err)
}
- if err := osfile.Chown(u, g); err != nil {
+ if err := os.Chown(ospath, u, g); err != nil {
return nil, fmt.Errorf("set owner and group: %v", err)
}
- if err := osfile.Chmod(lib9p.Mode9ToFSMode(perm)); err != nil {
+ if err := os.Chmod(ospath, lib9p.Mode9ToFSMode(perm)); err != nil {
return nil, fmt.Errorf("set file mode: %v", err)
}
- if err := osfile.Close(); err != nil {
- return nil, fmt.Errorf("close: %v", err)
- }
-
file, err := openFile(f.fs, path.Join(f.path, name), mode)
if err != nil {
return nil, fmt.Errorf("open new file: %v", err)
diff --git a/server.go b/server.go
@@ -15,7 +15,13 @@ func Chatty() {
chatty9P = true
}
-var EDupTag = fmt.Errorf("duplicate tag")
+var (
+ ErrBotch = fmt.Errorf("botch the rock")
+ ErrPerm = fmt.Errorf("permission denied")
+ ErrOperation = fmt.Errorf("operation not supported")
+ ErrDupTag = fmt.Errorf("duplicate tag")
+ ErrUnknownFid = fmt.Errorf("unknown fid")
+)
type Server struct {
fs FS
@@ -60,7 +66,7 @@ func (s *Server) getReq() (*Req, error) {
if chatty9P {
fmt.Fprintf(os.Stderr, "<-- %v\n", r.ifcall)
}
- return r, EDupTag
+ return r, ErrDupTag
}
r.srv = s
@@ -111,17 +117,13 @@ func sAuth(s *Server, r *Req) {
respond(r, fmt.Errorf("authentication not implemented"))
}
-func rAuth(r *Req, err error) {
- if err != nil {
- rError(r, err)
- }
-}
+func rAuth(r *Req, err error) {}
func sAttach(s *Server, r *Req) {
ifcall := r.ifcall.(*TAttach)
fid, err := s.fPool.alloc(ifcall.Fid())
if err != nil {
- respond(r, fmt.Errorf("duplicate fid"))
+ respond(r, ErrUnknownFid)
return
}
@@ -134,33 +136,31 @@ func sAttach(s *Server, r *Req) {
fid.File = f
fid.Uid = ifcall.UName()
- fid.OMode = OREAD
+ fid.OMode = OREAD // TODO: right?
+
info, err := fid.File.Stat()
if err != nil {
log.Printf("Stat %s, %v", fid.File, err)
+ s.fPool.delete(ifcall.Fid())
respond(r, fmt.Errorf("internal error"))
return
}
- Stat := info.Sys().(*Stat)
- fid.Qid = Stat.Qid
+ fid.Qid = info.Qid()
- ofcall := &RAttach{
+ r.ofcall = &RAttach{
tag: ifcall.Tag(),
qid: fid.Qid,
}
- r.ofcall = ofcall
-
respond(r, nil)
}
func rAttach(r *Req, err error) {}
func rError(r *Req, err error) {
- ofcall := &RError{
+ r.ofcall = &RError{
tag: r.ifcall.Tag(),
ename: err,
}
- r.ofcall = ofcall
}
func sFlush(s *Server, r *Req) {}
@@ -170,7 +170,7 @@ func sWalk(s *Server, r *Req) {
ifcall := r.ifcall.(*TWalk)
oldFid, ok := s.fPool.lookup(ifcall.Fid())
if !ok {
- respond(r, fmt.Errorf("unknown fid"))
+ respond(r, ErrUnknownFid)
return
}
_, ok = s.fPool.lookup(ifcall.NewFid())
@@ -212,14 +212,12 @@ func sWalk(s *Server, r *Req) {
respond(r, fmt.Errorf("internal error"))
return
}
- Stat := info.Sys().(*Stat)
- newFid.Qid = Stat.Qid
+ newFid.Qid = info.Qid()
- ofcall := &RWalk{
+ r.ofcall = &RWalk{
tag: r.ifcall.Tag(),
qid: wqids,
}
- r.ofcall = ofcall
respond(r, nil)
}
@@ -228,27 +226,27 @@ func rWalk(r *Req, err error) {
func sOpen(s *Server, r *Req) {
ifcall := r.ifcall.(*TOpen)
- fidNum := ifcall.Fid()
- fidStruct, ok := s.fPool.lookup(fidNum)
+ fid, ok := s.fPool.lookup(ifcall.Fid())
if !ok {
- respond(r, fmt.Errorf("unknown fid"))
+ respond(r, ErrUnknownFid)
return
}
- if fidStruct.OMode != -1 {
- respond(r, fmt.Errorf("already open"))
+ if fid.OMode != -1 {
+ respond(r, ErrBotch)
return
}
- // TODO: this if Statement is from plan9's lib9p.
- // I don't understand this.
- if fidStruct.Qid.Type == QTDIR && ifcall.Mode() & ^ORCLOSE != OREAD {
+ // Write attempt to a directory is prohibitted by the protocol.
+ // See open(5).
+ // In plan9 implementation, ifcall.Mode() is ANDed with ^ORCLOSE,
+ // but ORCLOSE is also prohibitted by the protocol...
+ if fid.Qid.Type == QTDIR && ifcall.Mode() != OREAD {
respond(r, fmt.Errorf("is a directory"))
return
}
var p fs.FileMode
- switch ifcall.Mode() {
+ switch ifcall.Mode() & 3 {
default:
- respond(r, fmt.Errorf("invalid mode"))
- return
+ panic("invalid mode")
case OREAD:
p = AREAD
case OWRITE:
@@ -261,24 +259,30 @@ func sOpen(s *Server, r *Req) {
if ifcall.Mode()&OTRUNC != 0 {
p |= AWRITE
}
- if fidStruct.Qid.Type&QTDIR != 0 && p != AREAD {
- respond(r, fmt.Errorf("permission denied"))
+ if fid.Qid.Type&QTDIR != 0 && p != AREAD {
+ respond(r, ErrPerm)
return
}
- if !hasPerm(fidStruct.File, fidStruct.Uid, p) {
+ if !hasPerm(fid.File, fid.Uid, p) {
respond(r, fmt.Errorf("permission denied"))
return
}
- if ifcall.Mode()&ORCLOSE != 0 {
- panic("ORCLOSE not implemented")
+ parent, err := fid.File.Parent()
+ if err != nil {
+ respond(r, fmt.Errorf("open parent"))
+ return
+ }
+ if ifcall.Mode()&ORCLOSE != 0 && !hasPerm(parent, fid.Uid, AWRITE) {
+ respond(r, ErrPerm)
+ return
}
- fidStruct.OMode = ifcall.Mode()
+ fid.OMode = ifcall.Mode()
r.ofcall = &ROpen{
tag: ifcall.Tag(),
- qid: fidStruct.Qid,
+ qid: fid.Qid,
iounit: s.MSize - 23,
}
respond(r, nil)
@@ -290,7 +294,7 @@ func sCreate(s *Server, r *Req) {
fid, ok := s.fPool.lookup(ifcall.Fid())
if !ok {
- respond(r, fmt.Errorf("unknown fid"))
+ respond(r, ErrUnknownFid)
return
}
dir := fid.File
@@ -304,19 +308,19 @@ func sCreate(s *Server, r *Req) {
return
}
if !hasPerm(dir, fid.Uid, AWRITE) {
- respond(r, fmt.Errorf("permission denied"))
+ respond(r, ErrPerm)
return
}
cfdir, ok := fid.File.(CreaterFile)
if !ok {
- respond(r, fmt.Errorf("operation not supported"))
+ respond(r, ErrOperation)
return
}
perm := ifcall.Perm()
dirperm := FSModeTo9Mode(dirstat.Mode())
- if perm & DMDIR == 0 {
+ if perm&DMDIR == 0 {
perm &= ^FileMode(0666) | (dirperm & FileMode(0666))
} else {
perm &= ^FileMode(0777) | (dirperm & FileMode(0777))
@@ -340,12 +344,11 @@ func sCreate(s *Server, r *Req) {
fid.Qid = fi.Qid()
fid.OMode = ifcall.Mode()
- ofcall := new(RCreate)
- ofcall.tag = ifcall.Tag()
- ofcall.qid = fi.Qid()
- ofcall.iounit = s.MSize - 23
-
- r.ofcall = ofcall
+ r.ofcall = &RCreate{
+ tag: ifcall.Tag(),
+ qid: fi.Qid(),
+ iounit: s.MSize - 23,
+ }
respond(r, nil)
}
func rCreate(r *Req, err error) {}
@@ -749,7 +752,7 @@ func respond(r *Req, err error) {
r.srv.Writer.Write(r.ofcall.marshal())
// free tag.
- if r.pool == nil && err != EDupTag {
+ if r.pool == nil && err != ErrDupTag {
panic("ReqPool is nil but err is not EDupTag")
}
if r.pool != nil {