commit c6af3f65b27200506b27c21cbabb21c6a437a729
parent 6c0c7d2380a2bce23c6577c9dfc665764ed71858
Author: Matsuda Kenji <info@mtkn.jp>
Date: Tue, 12 Sep 2023 08:33:47 +0900
implement create
Diffstat:
| M | file.go | | | 10 | +++++++++- |
| M | server.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)