lib9p

Go 9P library.
Log | Files | Refs

commit c6af3f65b27200506b27c21cbabb21c6a437a729
parent 6c0c7d2380a2bce23c6577c9dfc665764ed71858
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 12 Sep 2023 08:33:47 +0900

implement create

Diffstat:
Mfile.go | 10+++++++++-
Mserver.go | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/file.go b/file.go @@ -11,10 +11,18 @@ type File interface { Read(b []byte) (int, error) } +type CreaterFile interface { + File + // Create creats a file named name in this directory. + // It sets the owner of newly created file to the specified uid, + // and file mode to the specified perm. + Create(name string, uid string, mode OpenMode, perm FileMode) (File, error) +} + type WriterStatFile interface { File - // WStat set file Stat to stat. + // WStat sets file Stat to stat. // After successful call, the file's Stat() method should return // the same Stat as stat. // If there is an error, file's status must remain the same as before. diff --git a/server.go b/server.go @@ -155,6 +155,17 @@ func sAttach(s *Server, r *Req) { func rAttach(r *Req, err error) {} +func rError(r *Req, err error) { + ofcall := &RError{ + tag: r.ifcall.Tag(), + ename: err, + } + r.ofcall = ofcall +} + +func sFlush(s *Server, r *Req) {} +func rFlush(r *Req, err error) {} + func sWalk(s *Server, r *Req) { ifcall := r.ifcall.(*TWalk) oldFid, ok := s.fPool.lookup(ifcall.Fid()) @@ -274,6 +285,64 @@ func sOpen(s *Server, r *Req) { } func rOpen(r *Req, err error) {} +func sCreate(s *Server, r *Req) { + ifcall := r.ifcall.(*TCreate) + + fid, ok := s.fPool.lookup(ifcall.Fid()) + if !ok { + respond(r, fmt.Errorf("unknown fid")) + return + } + dir := fid.File + dirstat, err := dir.Stat() + if err != nil { + respond(r, fmt.Errorf("stat: %v", err)) + return + } + if !dirstat.IsDir() { + respond(r, fmt.Errorf("create on non-dir")) + return + } + if !hasPerm(dir, fid.Uid, AWRITE) { + respond(r, fmt.Errorf("permission denied")) + return + } + + cfdir, ok := fid.File.(CreaterFile) + if !ok { + respond(r, fmt.Errorf("operation not supported")) + return + } + + perm := ifcall.Perm() + dirperm := FSModeTo9Mode(dirstat.Mode()) + if perm & DMDIR == 0 { + perm &= ^FileMode(0666) | (dirperm & FileMode(0666)) + } else { + perm &= ^FileMode(0777) | (dirperm & FileMode(0777)) + } + + file, err := cfdir.Create(ifcall.Name(), fid.Uid, ifcall.Mode(), perm) + if err != nil { + respond(r, fmt.Errorf("create: %v", err)) + return + } + + fi, err := file.Stat() + if err != nil { + respond(r, fmt.Errorf("stat: %v", err)) + return + } + ofcall := new(RCreate) + ofcall.tag = ifcall.Tag() + ofcall.qid = fi.Qid() + ofcall.iounit = s.MSize - 23 + + r.ofcall = ofcall + respond(r, nil) +} +func rCreate(r *Req, err error) {} + func sRead(s *Server, r *Req) { ifcall := r.ifcall.(*TRead) @@ -404,13 +473,8 @@ func sClunk(s *Server, r *Req) { func rClunk(r *Req, err error) {} -func rError(r *Req, err error) { - ofcall := &RError{ - tag: r.ifcall.Tag(), - ename: err, - } - r.ofcall = ofcall -} +func sRemove(s *Server, r *Req) {} +func rRemove(r *Req, err error) {} func sStat(s *Server, r *Req) { ifcall := r.ifcall.(*TStat)