lib9p

Go 9P library.
Log | Files | Refs

commit 162030d36b2f4a9de344d0bb83ddc04e5ebf548c
parent a65b8e19365e83970ee05585c3673a05931710b0
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri, 15 Sep 2023 08:51:07 +0900

add mkdir

Diffstat:
Mdiskfs/file.go | 21++++++++++++---------
Mserver.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 {