lib9p

Go 9P library.
Log | Files | Refs

commit 8fb09c72847ef13ab02fafb2c266684f36ae0bc2
parent 0992cc760c2083abc929711d1a53891f96d0c41f
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Thu, 21 Sep 2023 09:59:29 +0900

implementing file system for testing

Diffstat:
Aclient_test.go | 139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfcall.go | 293+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Afs_test.go | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 406 insertions(+), 118 deletions(-)

diff --git a/client_test.go b/client_test.go @@ -0,0 +1,139 @@ +package lib9p + +import ( + "fmt" + "io" + "testing" +) + +func newReq(s *Server, msg Msg) (*Req, error) { + r, err := s.rPool.add(msg.Tag()) + if err != nil { + return nil, fmt.Errorf("ReqPool.add(%d): %w", msg.Tag(), err) + } + r.srv = s + r.tag = msg.Tag() + r.ifcall = msg + return r, nil +} + +func handleReq(s *Server, r *Req) { + switch r.ifcall.(type) { + default: + respond(r, fmt.Errorf("unknown message type: %d", r.ifcall.Type())) + case *TVersion: + sVersion(s, r) + case *TAuth: + sAuth(s, r) + case *TAttach: + sAttach(s, r) + case *TWalk: + sWalk(s, r) + case *TOpen: + sOpen(s, r) + case *TCreate: + sCreate(s, r) + case *TRead: + sRead(s, r) + case *TWrite: + sWrite(s, r) + case *TClunk: + sClunk(s, r) + case *TRemove: + sRemove(s, r) + case *TStat: + sStat(s, r) + case *TWStat: + sWStat(s, r) + } +} + +func TestWalk(t *testing.T) { + fsys := &testFS{ + root: &testFile{ + name: "root", + omode: -1, + isDir: true, + children: []*testFile{ + &testFile{ + name: "unko", + omode: -1, + isDir: false, + content: []byte("unko\n"), + }, + }, + }, + } + fsys.root.fsys = fsys + fsys.root.parent = fsys.root + fsys.root.children[0].fsys = fsys + fsys.root.children[0].parent = fsys.root + + f, err := fsys.Open(".") + if err != nil { + t.Errorf("open: %v", err) + } else { + t.Logf("file: %s", f.(*testFile).name) + } + f, err = fsys.Open("unko") + if err != nil { + t.Errorf("open: %v", err) + } else { + t.Logf("file: %s", f.(*testFile).name) + } + f, err = fsys.Open("chinko") + if err != nil { + t.Logf("open: %v", err) + } else { + t.Errorf("file: %s", f.(*testFile).name) + } + +} + +func TestSVersion(t *testing.T) { + sr, _ := io.Pipe() + cr, sw := io.Pipe() + msg := []Msg{ + &TVersion{ + tag: ^uint16(0), + mSize: 1024, + version: "9P2000", + }, + &TAttach{ + tag: 0, + fid: 0, + afid: NOFID, + uname: "glenda", + aname: "", + }, + } + fsys := &testFS{ + root: &testFile{ + omode: -1, + name: "root", + children: nil, + content: nil, + }, + } + fsys.root.fsys = fsys + fsys.root.parent = fsys.root + + s := NewServer(fsys, 1024, sr, sw) + + for _, m := range msg { + r, err := newReq(s, m) + if err != nil { + t.Fatalf("newReq: %v", err) + return + } + t.Logf("<-- %v\n", r.ifcall) + + go handleReq(s, r) + buf := make([]byte, 1024) + _, err = cr.Read(buf) + if err != nil { + t.Fatalf("read: %v", err) + } + t.Logf("--> %v\n", bufMsg(buf)) + } +} diff --git a/fcall.go b/fcall.go @@ -68,11 +68,69 @@ func (msg bufMsg) Type() MsgType { return MsgType(msg[4]) } func (msg bufMsg) Tag() uint16 { return gbit16(msg[5:7]) } func (msg bufMsg) SetTag(t uint16) { pbit16(msg[5:7], t) } func (msg bufMsg) marshal() []byte { return []byte(msg)[:msg.Size()] } -func (msg bufMsg) String() string { return fmt.Sprint([]byte(msg[:msg.Size()])) } +func (msg bufMsg) String() string { + switch msg.Type() { + case Tversion: + return newTVersion(msg).String() + case Rversion: + return newRVersion(msg).String() + case Tauth: + return newTAuth(msg).String() + case Rauth: + return newRAuth(msg).String() + case Tattach: + return newTAttach(msg).String() + case Rattach: + return newRAttach(msg).String() + case Rerror: + return newRError(msg).String() + case Tflush: + return newTFlush(msg).String() + case Rflush: + return newRFlush(msg).String() + case Twalk: + return newTWalk(msg).String() + case Rwalk: + return newRWalk(msg).String() + case Topen: + return newTOpen(msg).String() + case Ropen: + return newROpen(msg).String() + case Tcreate: + return newTCreate(msg).String() + case Rcreate: + return newRCreate(msg).String() + case Tread: + return newTRead(msg).String() + case Rread: + return newRRead(msg).String() + case Twrite: + return newTWrite(msg).String() + case Rwrite: + return newRWrite(msg).String() + case Tclunk: + return newTClunk(msg).String() + case Rclunk: + return newRClunk(msg).String() + case Tremove: + return newTRemove(msg).String() + case Rremove: + return newRRemove(msg).String() + case Tstat: + return newTStat(msg).String() + case Rstat: + return newRStat(msg).String() + case Twstat: + return newTWStat(msg).String() + case Rwstat: + return newRWStat(msg).String() + default: + return fmt.Sprint([]byte(msg[:msg.Size()])) + } +} // TVersion represents Tversion message of 9P. type TVersion struct { - size uint32 tag uint16 mSize uint32 version string @@ -80,14 +138,13 @@ type TVersion struct { func newTVersion(buf []byte) *TVersion { msg := new(TVersion) - msg.size = gbit32(buf[0:4]) msg.tag = gbit16(buf[5:7]) msg.mSize = gbit32(buf[7:11]) vs := gbit16(buf[11:13]) msg.version = string(buf[13 : 13+vs]) return msg } -func (msg *TVersion) Size() uint32 { return msg.size } +func (msg *TVersion) Size() uint32 { return uint32(4 + 1 + 2 + 4 + 2 + len(msg.version)) } func (msg *TVersion) Type() MsgType { return Tversion } func (msg *TVersion) Tag() uint16 { return msg.tag } func (msg *TVersion) SetTag(t uint16) { msg.tag = t } @@ -161,7 +218,6 @@ func (msg *RVersion) String() string { } type TAuth struct { - size uint32 tag uint16 afid uint32 uname string @@ -171,7 +227,6 @@ type TAuth struct { func newTAuth(buf []byte) *TAuth { cur := 0 msg := new(TAuth) - msg.size = gbit32(buf[cur : cur+4]) cur += 4 cur += 1 // message type msg.tag = gbit16(buf[cur : cur+2]) @@ -186,18 +241,20 @@ func newTAuth(buf []byte) *TAuth { cur += 2 msg.aname = string(buf[cur : cur+l]) cur += l - if cur != int(msg.size) { + if cur != int(gbit32(buf[0:4])) { panic("length of buf and cursor position not match") } return msg } -func (msg *TAuth) Size() uint32 { return msg.size } -func (msg *TAuth) Type() MsgType { return Tauth } -func (msg *TAuth) Tag() uint16 { return msg.tag } +func (msg *TAuth) Size() uint32 { + return uint32(4 + 1 + 2 + 4 + 2 + len(msg.uname) + 2 + len(msg.aname)) +} +func (msg *TAuth) Type() MsgType { return Tauth } +func (msg *TAuth) Tag() uint16 { return msg.tag } func (msg *TAuth) SetTag(t uint16) { msg.tag = t } -func (msg *TAuth) AFid() uint32 { return msg.afid } -func (msg *TAuth) UName() string { return msg.uname } -func (msg *TAuth) AName() string { return msg.aname } +func (msg *TAuth) AFid() uint32 { return msg.afid } +func (msg *TAuth) UName() string { return msg.uname } +func (msg *TAuth) AName() string { return msg.aname } func (msg *TAuth) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -248,11 +305,11 @@ func newRAuth(buf []byte) *RAuth { msg.aqid = unmarshalQid(buf[7:]) return msg } -func (msg *RAuth) Size() uint32 { return 4 + 1 + 2 + 13 } -func (msg *RAuth) Type() MsgType { return Rauth } -func (msg *RAuth) Tag() uint16 { return msg.tag } +func (msg *RAuth) Size() uint32 { return 4 + 1 + 2 + 13 } +func (msg *RAuth) Type() MsgType { return Rauth } +func (msg *RAuth) Tag() uint16 { return msg.tag } func (msg *RAuth) SetTag(t uint16) { msg.tag = t } -func (msg *RAuth) AQid() Qid { return msg.aqid } +func (msg *RAuth) AQid() Qid { return msg.aqid } func (msg *RAuth) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -278,7 +335,6 @@ func (msg *RAuth) String() string { } type TAttach struct { - size uint32 tag uint16 fid uint32 afid uint32 @@ -289,7 +345,6 @@ type TAttach struct { func newTAttach(buf []byte) *TAttach { cur := 0 msg := new(TAttach) - msg.size = gbit32(buf[cur : cur+4]) cur += 4 cur += 1 // message type msg.tag = gbit16(buf[cur : cur+2]) @@ -306,19 +361,21 @@ func newTAttach(buf []byte) *TAttach { cur += 2 msg.aname = string(buf[cur : cur+l]) cur += l - if cur != int(msg.size) { + if cur != int(gbit32(buf[0:4])) { panic("length of buf and cursor position not match") } return msg } -func (msg *TAttach) Size() uint32 { return msg.size } -func (msg *TAttach) Type() MsgType { return Tattach } -func (msg *TAttach) Tag() uint16 { return msg.tag } +func (msg *TAttach) Size() uint32 { + return uint32(4 + 1 + 2 + 4 + 4 + 2 + len(msg.uname) + 2 + len(msg.aname)) +} +func (msg *TAttach) Type() MsgType { return Tattach } +func (msg *TAttach) Tag() uint16 { return msg.tag } func (msg *TAttach) SetTag(t uint16) { msg.tag = t } -func (msg *TAttach) Fid() uint32 { return msg.fid } -func (msg *TAttach) AFid() uint32 { return msg.afid } -func (msg *TAttach) UName() string { return msg.uname } -func (msg *TAttach) AName() string { return msg.aname } +func (msg *TAttach) Fid() uint32 { return msg.fid } +func (msg *TAttach) AFid() uint32 { return msg.afid } +func (msg *TAttach) UName() string { return msg.uname } +func (msg *TAttach) AName() string { return msg.aname } func (msg *TAttach) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -375,11 +432,11 @@ func newRAttach(buf []byte) *RAttach { msg.qid = unmarshalQid(buf[7:]) return msg } -func (msg *RAttach) Size() uint32 { return 4 + 1 + 2 + 13 } -func (msg *RAttach) Type() MsgType { return Rattach } -func (msg *RAttach) Tag() uint16 { return msg.tag } +func (msg *RAttach) Size() uint32 { return 4 + 1 + 2 + 13 } +func (msg *RAttach) Type() MsgType { return Rattach } +func (msg *RAttach) Tag() uint16 { return msg.tag } func (msg *RAttach) SetTag(t uint16) { msg.tag = t } -func (msg *RAttach) Qid() Qid { return msg.qid } +func (msg *RAttach) Qid() Qid { return msg.qid } func (msg *RAttach) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -416,11 +473,11 @@ func newRError(buf []byte) *RError { msg.ename = fmt.Errorf("%s", string(buf[9:9+es])) return msg } -func (msg *RError) Size() uint32 { return uint32(4 + 1 + 2 + 2 + len(msg.EName())) } -func (msg *RError) Type() MsgType { return Rerror } -func (msg *RError) Tag() uint16 { return msg.tag } +func (msg *RError) Size() uint32 { return uint32(4 + 1 + 2 + 2 + len(msg.EName())) } +func (msg *RError) Type() MsgType { return Rerror } +func (msg *RError) Tag() uint16 { return msg.tag } func (msg *RError) SetTag(t uint16) { msg.tag = t } -func (msg *RError) EName() string { return msg.ename.Error() } +func (msg *RError) EName() string { return msg.ename.Error() } func (msg *RError) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -459,11 +516,11 @@ func newTFlush(buf []byte) *TFlush { return msg } -func (msg *TFlush) Size() uint32 { return 9 } -func (msg *TFlush) Type() MsgType { return Tflush } -func (msg *TFlush) Tag() uint16 { return msg.tag } +func (msg *TFlush) Size() uint32 { return 9 } +func (msg *TFlush) Type() MsgType { return Tflush } +func (msg *TFlush) Tag() uint16 { return msg.tag } func (msg *TFlush) SetTag(t uint16) { msg.tag = t } -func (msg *TFlush) OldTag() uint16 { return msg.oldtag } +func (msg *TFlush) OldTag() uint16 { return msg.oldtag } func (msg *TFlush) marshal() []byte { buf := make([]byte, msg.Size()) pbit32(buf[0:4], msg.Size()) @@ -486,9 +543,9 @@ func newRFlush(buf []byte) *RFlush { return msg } -func (msg *RFlush) Size() uint32 { return 7 } -func (msg *RFlush) Type() MsgType { return Rflush } -func (msg *RFlush) Tag() uint16 { return msg.tag } +func (msg *RFlush) Size() uint32 { return 7 } +func (msg *RFlush) Type() MsgType { return Rflush } +func (msg *RFlush) Tag() uint16 { return msg.tag } func (msg *RFlush) SetTag(t uint16) { msg.tag = t } func (msg *RFlush) marshal() []byte { buf := make([]byte, msg.Size()) @@ -603,10 +660,10 @@ func newRWalk(buf []byte) *RWalk { func (msg *RWalk) Size() uint32 { return uint32(4 + 1 + 2 + 2 + len(msg.Qid())*13) } -func (msg *RWalk) Type() MsgType { return Rwalk } -func (msg *RWalk) Tag() uint16 { return msg.tag } +func (msg *RWalk) Type() MsgType { return Rwalk } +func (msg *RWalk) Tag() uint16 { return msg.tag } func (msg *RWalk) SetTag(t uint16) { msg.tag = t } -func (msg *RWalk) Qid() []Qid { return msg.qid } +func (msg *RWalk) Qid() []Qid { return msg.qid } func (msg *RWalk) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -661,12 +718,12 @@ func newTOpen(buf []byte) *TOpen { } return msg } -func (msg *TOpen) Size() uint32 { return msg.size } -func (msg *TOpen) Type() MsgType { return Topen } -func (msg *TOpen) Tag() uint16 { return msg.tag } +func (msg *TOpen) Size() uint32 { return msg.size } +func (msg *TOpen) Type() MsgType { return Topen } +func (msg *TOpen) Tag() uint16 { return msg.tag } func (msg *TOpen) SetTag(t uint16) { msg.tag = t } -func (msg *TOpen) Fid() uint32 { return msg.fid } -func (msg *TOpen) Mode() OpenMode { return msg.mode } +func (msg *TOpen) Fid() uint32 { return msg.fid } +func (msg *TOpen) Mode() OpenMode { return msg.mode } func (msg *TOpen) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -707,11 +764,11 @@ func newROpen(buf []byte) *ROpen { func (msg *ROpen) Size() uint32 { return uint32(4 + 1 + 2 + 13 + 4) } -func (msg *ROpen) Type() MsgType { return Ropen } -func (msg *ROpen) Tag() uint16 { return msg.tag } +func (msg *ROpen) Type() MsgType { return Ropen } +func (msg *ROpen) Tag() uint16 { return msg.tag } func (msg *ROpen) SetTag(t uint16) { msg.tag = t } -func (msg *ROpen) Qid() Qid { return msg.qid } -func (msg *ROpen) IoUnit() uint32 { return msg.iounit } +func (msg *ROpen) Qid() Qid { return msg.qid } +func (msg *ROpen) IoUnit() uint32 { return msg.iounit } func (msg *ROpen) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -770,13 +827,13 @@ func newTCreate(buf []byte) *TCreate { func (msg *TCreate) Size() uint32 { return uint32(4 + 1 + 2 + 4 + 2 + len(msg.name) + 4 + 1) } -func (msg *TCreate) Type() MsgType { return Tcreate } -func (msg *TCreate) Tag() uint16 { return msg.tag } +func (msg *TCreate) Type() MsgType { return Tcreate } +func (msg *TCreate) Tag() uint16 { return msg.tag } func (msg *TCreate) SetTag(t uint16) { msg.tag = t } -func (msg *TCreate) Fid() uint32 { return msg.fid } -func (msg *TCreate) Name() string { return msg.name } -func (msg *TCreate) Perm() FileMode { return msg.perm } -func (msg *TCreate) Mode() OpenMode { return msg.mode } +func (msg *TCreate) Fid() uint32 { return msg.fid } +func (msg *TCreate) Name() string { return msg.name } +func (msg *TCreate) Perm() FileMode { return msg.perm } +func (msg *TCreate) Mode() OpenMode { return msg.mode } func (msg *TCreate) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -827,11 +884,11 @@ func newRCreate(buf []byte) *RCreate { func (msg *RCreate) Size() uint32 { return uint32(4 + 1 + 2 + 13 + 4) } -func (msg *RCreate) Type() MsgType { return Rcreate } -func (msg *RCreate) Tag() uint16 { return msg.tag } +func (msg *RCreate) Type() MsgType { return Rcreate } +func (msg *RCreate) Tag() uint16 { return msg.tag } func (msg *RCreate) SetTag(t uint16) { msg.tag = t } -func (msg *RCreate) Qid() Qid { return msg.qid } -func (msg *RCreate) IoUnit() uint32 { return msg.iounit } +func (msg *RCreate) Qid() Qid { return msg.qid } +func (msg *RCreate) IoUnit() uint32 { return msg.iounit } func (msg *RCreate) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -885,13 +942,13 @@ func newTRead(buf []byte) *TRead { } return msg } -func (msg *TRead) Size() uint32 { return msg.size } -func (msg *TRead) Type() MsgType { return Tread } -func (msg *TRead) Tag() uint16 { return msg.tag } +func (msg *TRead) Size() uint32 { return msg.size } +func (msg *TRead) Type() MsgType { return Tread } +func (msg *TRead) Tag() uint16 { return msg.tag } func (msg *TRead) SetTag(t uint16) { msg.tag = t } -func (msg *TRead) Fid() uint32 { return msg.fid } -func (msg *TRead) Offset() uint64 { return msg.offset } -func (msg *TRead) Count() uint32 { return msg.count } +func (msg *TRead) Fid() uint32 { return msg.fid } +func (msg *TRead) Offset() uint64 { return msg.offset } +func (msg *TRead) Count() uint32 { return msg.count } func (msg *TRead) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -936,11 +993,11 @@ func newRRead(buf []byte) *RRead { func (msg *RRead) Size() uint32 { return uint32(4 + 1 + 2 + 4 + msg.Count()) } -func (msg *RRead) Type() MsgType { return Rread } -func (msg *RRead) Tag() uint16 { return msg.tag } +func (msg *RRead) Type() MsgType { return Rread } +func (msg *RRead) Tag() uint16 { return msg.tag } func (msg *RRead) SetTag(t uint16) { msg.tag = t } -func (msg *RRead) Count() uint32 { return msg.count } -func (msg *RRead) Data() []byte { return msg.data } +func (msg *RRead) Count() uint32 { return msg.count } +func (msg *RRead) Data() []byte { return msg.data } func (msg *RRead) marshal() []byte { if uint32(len(msg.Data())) != msg.Count() { panic(fmt.Errorf("data size %d and count %d don't match", @@ -1014,16 +1071,16 @@ func newTWrite(buf []byte) *TWrite { } return msg } -func (msg *TWrite) Size() uint32 { +func (msg *TWrite) Size() uint32 { return uint32(4 + 1 + 2 + 4 + 8 + 4 + len(msg.Data())) } -func (msg *TWrite) Type() MsgType { return Twrite } -func (msg *TWrite) Tag() uint16 { return msg.tag } +func (msg *TWrite) Type() MsgType { return Twrite } +func (msg *TWrite) Tag() uint16 { return msg.tag } func (msg *TWrite) SetTag(t uint16) { msg.tag = t } -func (msg *TWrite) Fid() uint32 { return msg.fid } -func (msg *TWrite) Offset() uint64 { return msg.offset } -func (msg *TWrite) Count() uint32 { return msg.count } -func (msg *TWrite) Data() []byte { return msg.data } +func (msg *TWrite) Fid() uint32 { return msg.fid } +func (msg *TWrite) Offset() uint64 { return msg.offset } +func (msg *TWrite) Count() uint32 { return msg.count } +func (msg *TWrite) Data() []byte { return msg.data } func (msg *TWrite) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -1067,10 +1124,10 @@ func newRWrite(buf []byte) *RWrite { func (msg *RWrite) Size() uint32 { return uint32(4 + 1 + 2 + 4) } -func (msg *RWrite) Type() MsgType { return Rwrite } -func (msg *RWrite) Tag() uint16 { return msg.tag } +func (msg *RWrite) Type() MsgType { return Rwrite } +func (msg *RWrite) Tag() uint16 { return msg.tag } func (msg *RWrite) SetTag(t uint16) { msg.tag = t } -func (msg *RWrite) Count() uint32 { return msg.count } +func (msg *RWrite) Count() uint32 { return msg.count } func (msg *RWrite) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) @@ -1106,11 +1163,11 @@ func newTClunk(buf []byte) *TClunk { return msg } -func (msg *TClunk) Size() uint32 { return msg.size } -func (msg *TClunk) Type() MsgType { return Tclunk } -func (msg *TClunk) Tag() uint16 { return msg.tag } +func (msg *TClunk) Size() uint32 { return msg.size } +func (msg *TClunk) Type() MsgType { return Tclunk } +func (msg *TClunk) Tag() uint16 { return msg.tag } func (msg *TClunk) SetTag(t uint16) { msg.tag = t } -func (msg *TClunk) Fid() uint32 { return msg.fid } +func (msg *TClunk) Fid() uint32 { return msg.fid } func (msg *TClunk) marshal() []byte { m := make([]byte, msg.Size()) pbit32(m[0:4], msg.Size()) @@ -1133,9 +1190,9 @@ func newRClunk(buf []byte) *RClunk { msg.tag = gbit16(buf[5:7]) return msg } -func (msg *RClunk) Size() uint32 { return 7 } -func (msg *RClunk) Type() MsgType { return Rclunk } -func (msg *RClunk) Tag() uint16 { return msg.tag } +func (msg *RClunk) Size() uint32 { return 7 } +func (msg *RClunk) Type() MsgType { return Rclunk } +func (msg *RClunk) Tag() uint16 { return msg.tag } func (msg *RClunk) SetTag(t uint16) { msg.tag = t } func (msg *RClunk) marshal() []byte { m := make([]byte, msg.Size()) @@ -1148,10 +1205,11 @@ func (msg *RClunk) String() string { return fmt.Sprintf("Rclunk tag %d", msg.Tag()) } -type TRemove struct{ +type TRemove struct { tag uint16 fid uint32 } + func newTRemove(buf []byte) *TRemove { msg := new(TRemove) msg.tag = gbit16(buf[5:7]) @@ -1159,11 +1217,11 @@ func newTRemove(buf []byte) *TRemove { return msg } -func (msg *TRemove) Size() uint32 { return 4 + 1 + 2 + 4 } -func (msg *TRemove) Type() MsgType { return Tremove } -func (msg *TRemove) Tag() uint16 { return msg.tag } +func (msg *TRemove) Size() uint32 { return 4 + 1 + 2 + 4 } +func (msg *TRemove) Type() MsgType { return Tremove } +func (msg *TRemove) Tag() uint16 { return msg.tag } func (msg *TRemove) SetTag(t uint16) { msg.tag = t } -func (msg *TRemove) Fid() uint32 { return msg.fid } +func (msg *TRemove) Fid() uint32 { return msg.fid } func (msg *TRemove) marshal() []byte { m := make([]byte, msg.Size()) pbit32(m[0:4], msg.Size()) @@ -1176,7 +1234,7 @@ func (msg *TRemove) String() string { return fmt.Sprintf("Tremove tag %d fid %d", msg.Tag(), msg.Fid()) } -type RRemove struct{ +type RRemove struct { tag uint16 } @@ -1185,9 +1243,9 @@ func newRRemove(buf []byte) *RRemove { msg.tag = gbit16(buf[5:7]) return msg } -func (msg *RRemove) Size() uint32 { return 4 + 1 + 2 } -func (msg *RRemove) Type() MsgType { return Rremove } -func (msg *RRemove) Tag() uint16 { return msg.tag } +func (msg *RRemove) Size() uint32 { return 4 + 1 + 2 } +func (msg *RRemove) Type() MsgType { return Rremove } +func (msg *RRemove) Tag() uint16 { return msg.tag } func (msg *RRemove) SetTag(t uint16) { msg.tag = t } func (msg *RRemove) marshal() []byte { m := make([]byte, msg.Size()) @@ -1213,11 +1271,11 @@ func newTStat(buf []byte) *TStat { msg.fid = gbit32(buf[7:11]) return msg } -func (msg *TStat) Size() uint32 { return msg.size } -func (msg *TStat) Type() MsgType { return Tstat } -func (msg *TStat) Tag() uint16 { return msg.tag } +func (msg *TStat) Size() uint32 { return msg.size } +func (msg *TStat) Type() MsgType { return Tstat } +func (msg *TStat) Tag() uint16 { return msg.tag } func (msg *TStat) SetTag(t uint16) { msg.tag = t } -func (msg *TStat) Fid() uint32 { return msg.fid } +func (msg *TStat) Fid() uint32 { return msg.fid } func (msg *TStat) marshal() []byte { m := make([]byte, msg.Size()) pbit32(m[0:4], msg.Size()) @@ -1245,8 +1303,8 @@ func newRStat(buf []byte) *RStat { func (msg *RStat) Size() uint32 { return uint32(4 + 1 + 2 + 2 + 2 + msg.stat.size()) } -func (msg *RStat) Type() MsgType { return Rstat } -func (msg *RStat) Tag() uint16 { return msg.tag } +func (msg *RStat) Type() MsgType { return Rstat } +func (msg *RStat) Tag() uint16 { return msg.tag } func (msg *RStat) SetTag(t uint16) { msg.tag = t } func (msg *RStat) marshal() []byte { buf := make([]byte, msg.Size()) @@ -1266,9 +1324,9 @@ func (msg *RStat) String() string { return fmt.Sprintf("Rstat tag %d stat %s", msg.Tag(), msg.stat) } -type TWStat struct{ - tag uint16 - fid uint32 +type TWStat struct { + tag uint16 + fid uint32 stat *Stat } @@ -1282,11 +1340,11 @@ func newTWStat(buf []byte) *TWStat { func (msg *TWStat) Size() uint32 { return uint32(4 + 1 + 2 + 4 + 2 + 2 + msg.stat.size()) } -func (msg *TWStat) Type() MsgType { return Twstat } -func (msg *TWStat) Tag() uint16 { return msg.tag } +func (msg *TWStat) Type() MsgType { return Twstat } +func (msg *TWStat) Tag() uint16 { return msg.tag } func (msg *TWStat) SetTag(t uint16) { msg.tag = t } -func (msg *TWStat) Fid() uint32 { return msg.fid } -func (msg *TWStat) Stat() *Stat { return msg.stat } +func (msg *TWStat) Fid() uint32 { return msg.fid } +func (msg *TWStat) Stat() *Stat { return msg.stat } func (msg *TWStat) marshal() []byte { buf := make([]byte, msg.Size()) pbit32(buf[0:4], msg.Size()) @@ -1306,8 +1364,7 @@ func (msg *TWStat) String() string { return fmt.Sprintf("Twstat tag %d fid %d stat %s", msg.Tag(), msg.Fid(), msg.stat) } - -type RWStat struct{ +type RWStat struct { tag uint16 } @@ -1316,9 +1373,9 @@ func newRWStat(buf []byte) *RWStat { msg.tag = gbit16(buf[5:7]) return msg } -func (msg *RWStat) Size() uint32 { return 4 + 1 + 2 } -func (msg *RWStat) Type() MsgType { return Rwstat } -func (msg *RWStat) Tag() uint16 { return msg.tag } +func (msg *RWStat) Size() uint32 { return 4 + 1 + 2 } +func (msg *RWStat) Type() MsgType { return Rwstat } +func (msg *RWStat) Tag() uint16 { return msg.tag } func (msg *RWStat) SetTag(t uint16) { msg.tag = t } func (msg *RWStat) marshal() []byte { m := make([]byte, msg.Size()) diff --git a/fs_test.go b/fs_test.go @@ -0,0 +1,92 @@ +package lib9p + +import ( + "bytes" + "fmt" + "strings" +) + +type testFile struct { + name string + omode OpenMode + isDir bool + fsys *testFS + parent *testFile + children []*testFile + content []byte + reader *bytes.Reader + stat Stat +} + +func (f *testFile) Parent() (File, error) { return f.parent, nil } +func (f *testFile) Child() ([]File, error) { + child := make([]File, len(f.children)) + for i, c := range f.children { + child[i] = c + } + return child, nil +} +func (f *testFile) Stat() (*FileInfo, error) { return &FileInfo{Stat: f.stat}, nil } +func (f *testFile) Open(omode OpenMode) error { + if f.omode != -1 { + return fmt.Errorf("already open") + } + if omode == -1 { + return fmt.Errorf("invalid mode: %d", omode) + } + f.omode = omode + f.reader = bytes.NewReader(f.content) + return nil +} + +func (f *testFile) Close() error { + f.omode = -1 + f.reader = nil + return nil +} + +func (f *testFile) Read(b []byte) (int, error) { + if f.omode != OREAD && f.omode != ORDWR { + return 0, fmt.Errorf("permission denied") + } + return f.reader.Read(b) +} + +type testFS struct { + root *testFile +} + +func (fs *testFS) Open(path string) (File, error) { + path = clean9path(path) + wnames := split9path(path) + return fs.walk(wnames) +} + +func (fs *testFS) walk(wnames []string) (*testFile, error) { + cwd := fs.root +L: + for i, name := range wnames { + for _, child := range cwd.children { + if child.name == name { + cwd = child + continue L + } + } + return nil, fmt.Errorf("%s not found", strings.Join(wnames[:i+1], "/")) + } + return cwd, nil +} + +func clean9path(path string) string { + if path[len(path)-1] == '/' { + path = path[:len(path)-1] + } + return path +} + +func split9path(path string) []string { + if path == "." || path == "/" { + return []string{} + } + return strings.Split(path, "/") +}