commit 0020dcd0a0e379bad363ac2aee9a8535fdde00f5
parent 09bdb46c6034b5376d33de023267317df0671dfc
Author: Matsuda Kenji <info@mtkn.jp>
Date: Mon, 17 Jul 2023 11:35:00 +0900
split file
Diffstat:
| M | fcall.go | | | 78 | +++++------------------------------------------------------------------------- |
| A | fid.go | | | 68 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | file.go | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | server.go | | | 48 | ++---------------------------------------------- |
4 files changed, 148 insertions(+), 119 deletions(-)
diff --git a/fcall.go b/fcall.go
@@ -39,20 +39,6 @@ const (
Tmax = 128
)
-// QidType represents the type of Qid. the 'QT' prefix may be redundant.
-type QidType uint8
-
-const (
- QTDIR QidType = 0x80 /* type bit for directories */
- QTAPPEND = 0x40 /* type bit for append only files */
- QTEXCL = 0x20 /* type bit for exclusive use files */
- QTMOUNT = 0x10 /* type bit for mounted channel */
- QTAUTH = 0x08 /* type bit for authentication file */
- QTTMP = 0x04 /* type bit for non-backed-up file */
- QTSYMLINK = 0x02 /* type bit for symbolic link */
- QTFILE = 0x00 /* type bits for plain file */
-)
-
// Gbit16 reads b as 2-byte long little endian unsigned integer and
// returns the result
func gbit16(b []byte) uint16 { return binary.LittleEndian.Uint16(b[0:2]) }
@@ -74,54 +60,6 @@ func pbit32(b []byte, n uint32) { binary.LittleEndian.PutUint32(b, n) }
// Pbit64 puts into b an 8-byte long little endian unsigned integer n.
func pbit64(b []byte, n uint64) { binary.LittleEndian.PutUint64(b, n) }
-const (
- Topenfd = 98
- Ropenfd = 99
-)
-
-type Req struct {
- srv *Srv
- ifcall Msg
- ofcall Msg
-}
-
-type Fid []byte
-
-func (f Fid) String() string {
- return fmt.Sprintf("%d", gbit32(f))
-}
-
-type Qid []byte
-
-func (q Qid) Type() QidType { return QidType(q[0]) }
-func (q Qid) SetType(t QidType) { q[0] = uint8(t) }
-func (q Qid) Vers() uint32 { return gbit32(q[1:5]) }
-func (q Qid) SetVers(v uint32) { pbit32(q[1:5], v) }
-func (q Qid) Path() uint64 { return gbit64(q[5:13]) }
-func (q Qid) SetPath(p uint64) { pbit64(q[5:13], p) }
-func (q Qid) String() string {
- return fmt.Sprintf("(%016d %d %s)", q.Path(), q.Vers(), q.typeStr())
-}
-
-// TypeStr returns the q.Type() as string for debugging information.
-func (q Qid) typeStr() string {
- var s string
- t := q.Type()
- if t&QTDIR != 0 {
- s += "d"
- }
- if t&QTAPPEND != 0 {
- s += "a"
- }
- if t&QTEXCL != 0 {
- s += "l"
- }
- if t&QTAUTH != 0 {
- s += "A"
- }
- return s
-}
-
// Msg represents any kind of message of 9P.
// It defines methods for common fields.
type Msg interface {
@@ -192,7 +130,7 @@ type TAuth []byte
func (msg TAuth) Size() uint32 { return gbit32(msg[0:4]) }
func (msg TAuth) Type() MsgType { return MsgType(msg[4]) }
func (msg TAuth) Tag() uint16 { return gbit16(msg[5:7]) }
-func (msg TAuth) AFid() uint32 { return gbit32(msg[7:11]) }
+func (msg TAuth) AFid() Fid { return Fid(msg[7:11]) }
func (msg TAuth) UName() string {
size := gbit16(msg[11:13])
return string(msg[13 : 13+size])
@@ -204,7 +142,7 @@ func (msg TAuth) AName() string {
}
func (msg TAuth) conv2M() []byte { return []byte(msg)[:msg.Size()] }
func (msg TAuth) String() string {
- return fmt.Sprintf("Tauth tag %d afid %d uname %s aname %s",
+ return fmt.Sprintf("Tauth tag %d afid %v uname %s aname %s",
msg.Tag(), msg.AFid(), msg.UName(), msg.AName())
}
@@ -226,7 +164,7 @@ func (msg TAttach) Size() uint32 { return gbit32(msg[0:4]) }
func (msg TAttach) Type() MsgType { return MsgType(msg[4]) }
func (msg TAttach) Tag() uint16 { return gbit16(msg[5:7]) }
func (msg TAttach) Fid() Fid { return Fid(msg[7:11]) }
-func (msg TAttach) AFid() uint32 { return gbit32(msg[11:15]) }
+func (msg TAttach) AFid() Fid { return Fid(msg[11:15]) }
func (msg TAttach) UName() string {
usize := gbit16(msg[15:17])
return string(msg[17 : 17+usize])
@@ -238,14 +176,8 @@ func (msg TAttach) AName() string {
}
func (msg TAttach) conv2M() []byte { return []byte(msg)[:msg.Size()] }
func (msg TAttach) String() string {
- var afid int64
- if msg.AFid() == ^uint32(0) {
- afid = -1
- } else {
- afid = int64(msg.AFid())
- }
- return fmt.Sprintf("Tattach tag %d fid %v afid %d uname %s aname %s",
- msg.Tag(), msg.Fid(), afid, msg.UName(), msg.AName())
+ return fmt.Sprintf("Tattach tag %d fid %v afid %v uname %s aname %s",
+ msg.Tag(), msg.Fid(), msg.AFid(), msg.UName(), msg.AName())
}
type RAttach []byte
diff --git a/fid.go b/fid.go
@@ -0,0 +1,68 @@
+package lib9p
+
+import (
+ "fmt"
+)
+
+// QidType represents the type of Qid. the 'QT' prefix may be redundant.
+type QidType uint8
+
+const (
+ QTDIR QidType = 0x80 /* type bit for directories */
+ QTAPPEND = 0x40 /* type bit for append only files */
+ QTEXCL = 0x20 /* type bit for exclusive use files */
+ QTMOUNT = 0x10 /* type bit for mounted channel */
+ QTAUTH = 0x08 /* type bit for authentication file */
+ QTTMP = 0x04 /* type bit for non-backed-up file */
+ QTSYMLINK = 0x02 /* type bit for symbolic link */
+ QTFILE = 0x00 /* type bits for plain file */
+)
+
+type Req struct {
+ srv *Srv
+ ifcall Msg
+ ofcall Msg
+}
+
+type Fid []byte
+
+const NOFID = ^uint32(0)
+
+func (f Fid) String() string {
+ fn := int64(gbit32(f))
+ if uint32(fn) == NOFID {
+ fn = -1
+ }
+ return fmt.Sprintf("%d", fn)
+}
+
+type Qid []byte
+
+func (q Qid) Type() QidType { return QidType(q[0]) }
+func (q Qid) SetType(t QidType) { q[0] = uint8(t) }
+func (q Qid) Vers() uint32 { return gbit32(q[1:5]) }
+func (q Qid) SetVers(v uint32) { pbit32(q[1:5], v) }
+func (q Qid) Path() uint64 { return gbit64(q[5:13]) }
+func (q Qid) SetPath(p uint64) { pbit64(q[5:13], p) }
+func (q Qid) String() string {
+ return fmt.Sprintf("(%016d %d %s)", q.Path(), q.Vers(), q.typeStr())
+}
+
+// TypeStr returns the q.Type() as string for debugging information.
+func (q Qid) typeStr() string {
+ var s string
+ t := q.Type()
+ if t&QTDIR != 0 {
+ s += "d"
+ }
+ if t&QTAPPEND != 0 {
+ s += "a"
+ }
+ if t&QTEXCL != 0 {
+ s += "l"
+ }
+ if t&QTAUTH != 0 {
+ s += "A"
+ }
+ return s
+}
diff --git a/file.go b/file.go
@@ -0,0 +1,73 @@
+package lib9p
+
+import (
+ "io/fs"
+ "time"
+)
+
+const (
+ DMDIR = 0x80000000
+ DMAPPEND = 0x40000000
+ DMEXCL = 0x20000000
+ DMTMP = 0x04000000
+)
+
+type Stat []byte
+
+func (s Stat) Size() uint16 { return gbit16(s[0:2]) }
+func (s Stat) Type() uint16 { return gbit16(s[2:4]) }
+func (s Stat) Dev() uint32 { return gbit32(s[4:8]) }
+func (s Stat) Qid() Qid { return Qid(s[8:21]) }
+func (s Stat) Mode() uint32 { return gbit32(s[21:25]) }
+func (s Stat) ATime() uint32 { return gbit32(s[25:29]) }
+func (s Stat) MTime() uint32 { return gbit32(s[29:33]) }
+func (s Stat) Length() uint64 { return gbit64(s[33:41]) }
+func (s Stat) Name() string {
+ nlen := gbit16(s[41:43])
+ return string(s[43 : 43+nlen])
+}
+func (s Stat) Uid() string {
+ nlen := gbit16(s[41:43])
+ ulen := gbit16(s[43+nlen : 43+nlen+2])
+ return string(s[43+nlen+2 : 43+nlen+2+ulen])
+}
+func (s Stat) Gid() string {
+ nlen := gbit16(s[41:43])
+ ulen := gbit16(s[43+nlen : 43+nlen+2])
+ glen := gbit16(s[43+nlen+2+ulen : 43+nlen+2+ulen+2])
+ return string(s[43+nlen+2+ulen+2 : 43+nlen+2+ulen+2+glen])
+}
+func (s Stat) MUid() string {
+ nlen := gbit16(s[41:43])
+ ulen := gbit16(s[43+nlen : 43+nlen+2])
+ glen := gbit16(s[43+nlen+2+ulen : 43+nlen+2+ulen+2])
+ mlen := gbit16(s[43+nlen+2+ulen+2+glen : 43+nlen+2+ulen+2+glen+2])
+ return string(s[43+nlen+2+ulen+2+glen+2 : 43+nlen+2+ulen+2+glen+2+mlen])
+}
+
+type FileInfo Stat
+
+func (fi FileInfo) Name() string { return Stat(fi).Name() }
+func (fi FileInfo) Size() int64 { return int64(Stat(fi).Length()) }
+func (fi FileInfo) Mode() fs.FileMode {
+ var mode fs.FileMode
+ smode := Stat(fi).Mode()
+ if smode&DMDIR != 0 {
+ mode |= fs.ModeDir
+ }
+ if smode&DMAPPEND != 0 {
+ mode |= fs.ModeAppend
+ }
+ if smode&DMEXCL != 0 {
+ mode |= fs.ModeExclusive
+ }
+ if smode&DMTMP != 0 {
+ mode |= fs.ModeTemporary
+ }
+ // Permission bits are fixed according to godoc of fs.FileMode
+ mode |= fs.FileMode(smode&0777)
+ return mode
+}
+func (fi FileInfo) ModTime() time.Time { return time.Unix(int64(Stat(fi).MTime()), 0) }
+func (fi FileInfo) IsDir() bool { return Stat(fi).Mode()&DMDIR != 0 }
+func (fi FileInfo) Sys() any { return Stat(fi) }
diff --git a/server.go b/server.go
@@ -7,7 +7,6 @@ import (
"log"
"os"
"strings"
- "time"
)
var chatty9P = false
@@ -23,50 +22,6 @@ type Srv struct {
io.Writer
}
-const (
- DMDIR = 0x80000000
- DMAPPEND = 0x40000000
- DMEXCL = 0x20000000
- DMTMP = 0x04000000
-)
-
-type FileInfo struct {
- // type uint16
- dev uint32
- qid Qid
- mode uint32
- aTime int32
- mTime int32 // also in fs.FileInfo
- length int64 // also in fs.FileInfo
- name string // also in fs.FileInfo
- uid string
- gid string
- mUid string
-}
-
-func (fi *FileInfo) Name() string { return fi.name }
-func (fi *FileInfo) Size() int64 { return fi.length }
-func (fi *FileInfo) Mode() fs.FileMode {
- var mode fs.FileMode
- if fi.mode&DMDIR != 0 {
- mode |= fs.ModeDir
- }
- if fi.mode&DMAPPEND != 0 {
- mode |= fs.ModeAppend
- }
- if fi.mode&DMEXCL != 0 {
- mode |= fs.ModeExclusive
- }
- if fi.mode&DMTMP != 0 {
- mode |= fs.ModeTemporary
- }
- mode |= fs.FileMode(fi.mode & 0777)
- return mode
-}
-func (fi *FileInfo) ModTime() time.Time { return time.Unix(int64(fi.mTime), 0) }
-func (fi *FileInfo) IsDir() bool { return fi.qid.Type()&QTDIR != 0 }
-func (fi *FileInfo) Sys() any { return fi }
-
func getReq(s *Srv) (*Req, error) {
var r Req
@@ -146,7 +101,8 @@ func sAttach(s *Srv, r *Req) {
respond(r, nil)
}
-func rAttach(r *Req, err error) {}
+func rAttach(r *Req, err error) {
+}
func rError(r *Req, err error) {
size := uint32(4 + 1 + 2 + 2 + len(err.Error()))