commit e72454ff7e26e1c102d7532561154cd9c453787e
parent 825c0b5de9a56096a364e94ee499ed241fc21bd0
Author: Matsuda Kenji <info@mtkn.jp>
Date: Fri, 13 Oct 2023 16:50:50 +0900
add mount for client
Diffstat:
| M | client.go | | | 5 | +++-- |
| A | client2.go | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | fid.go | | | 74 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | file.go | | | 28 | +++++++++++++++++++++------- |
| M | fs.go | | | 1 | + |
5 files changed, 151 insertions(+), 9 deletions(-)
diff --git a/client.go b/client.go
@@ -11,11 +11,12 @@ type Client struct {
msize uint32
mSizeLock *sync.Mutex
uname string
- fPool *FidPool
+ fPool *clientFidPool
rPool *clientReqPool
txc chan<- *clientReq
errc chan error
cancel context.CancelFunc
+ root *ClientFile
}
type LibErr string
@@ -31,7 +32,7 @@ func NewClient(mSize uint32, uname string, r io.Reader, w io.Writer) *Client {
msize: mSize,
mSizeLock: new(sync.Mutex),
uname: uname,
- fPool: allocFidPool(),
+ fPool: allocClientFidPool(),
rPool: newClientReqPool(),
errc: make(chan error),
cancel: cancel,
diff --git a/client2.go b/client2.go
@@ -0,0 +1,51 @@
+package lib9p
+
+import (
+ "io"
+ "context"
+ "fmt"
+)
+
+func (c *Client) Root() File {
+ return c.root
+}
+
+func Mount(r io.Reader, w io.Writer, uname, aname string) (fs FS, err error) {
+ var (
+ mSize uint32 = 8196
+ version = "9P2000"
+ ctx = context.TODO()
+ )
+ c := NewClient(mSize, uname, r, w)
+ defer func() { if err != nil { c.Stop() } }()
+ rmSize, rver, err := c.Version(ctx, mSize, version)
+ if err != nil {
+ return nil, fmt.Errorf("version: %v", err)
+ }
+ if rver != "version" {
+ return nil, fmt.Errorf("incompatible version %s", rver)
+ }
+ if rmSize < mSize {
+ c.setMSize(rmSize)
+ }
+ // TODO: auth
+
+ fid, err := c.fPool.add(0)
+ if err != nil {
+ return nil, fmt.Errorf("add fid: %v", err)
+ }
+ qid, err := c.Attach(ctx, fid.fid, NOFID, uname, aname)
+ if err != nil {
+ return nil, fmt.Errorf("attach: %v", err)
+ }
+ c.root = &ClientFile{
+ name: "/",
+ path: ".",
+ fid: fid,
+ qid: qid,
+ client: c,
+ }
+ c.root.parent = c.root
+ fid.file = c.root
+ return c, nil
+}
+\ No newline at end of file
diff --git a/fid.go b/fid.go
@@ -101,3 +101,76 @@ func (pool *FidPool) String() string {
s += "}"
return s
}
+
+type clientFid struct {
+ fid uint32
+ omode OpenMode // -1 for not open
+ offset uint64
+ file *ClientFile
+}
+
+func newClientFid(fid uint32) *clientFid {
+ return &clientFid{
+ fid: fid,
+ omode: -1,
+ offset: 0,
+ }
+}
+
+type clientFidPool struct {
+ m map[uint32]*clientFid
+ lock *sync.Mutex
+}
+
+func allocClientFidPool() *clientFidPool {
+ return &clientFidPool{
+ m: make(map[uint32]*clientFid),
+ lock: new(sync.Mutex),
+ }
+}
+
+func (pool *clientFidPool) lookup(fid uint32) (*clientFid, bool) {
+ pool.lock.Lock()
+ defer pool.lock.Unlock()
+
+ f, ok := pool.m[fid]
+ return f, ok
+}
+
+func (pool *clientFidPool) add(fid uint32) (*clientFid, error) {
+ pool.lock.Lock()
+ defer pool.lock.Unlock()
+
+ if _, ok := pool.m[fid]; ok {
+ return nil, fmt.Errorf("fid already in use.")
+ }
+ f := newClientFid(fid)
+ pool.m[fid] = f
+ return f, nil
+}
+
+func (pool *clientFidPool) delete(fid uint32) {
+ pool.lock.Lock()
+ defer pool.lock.Unlock()
+
+ delete(pool.m, fid)
+}
+
+func (pool *clientFidPool) String() string {
+ pool.lock.Lock() // TODO: need?
+ defer pool.lock.Unlock()
+ s := "{"
+ for fnum, fstruct := range pool.m {
+ if fstruct.file == nil {
+ s += fmt.Sprintf(" [%d]<nil>", fnum)
+ continue
+ }
+ st, err := fstruct.file.Stat()
+ if err != nil {
+ panic(err)
+ }
+ s += fmt.Sprintf(" [%d]%v", fnum, st.Name())
+ }
+ s += "}"
+ return s
+}
+\ No newline at end of file
diff --git a/file.go b/file.go
@@ -1,6 +1,7 @@
package lib9p
import (
+ "context"
"fmt"
"io"
)
@@ -68,12 +69,14 @@ func walkfile(f File, name string) (File, error) {
}
type ClientFile struct {
- stat Stat
name string
path string
parent *ClientFile
children []*ClientFile
- fid *Fid
+ fid *clientFid
+ qid Qid
+ iounit uint32
+ client *Client
}
func (cf *ClientFile) Parent() (File, error) {
@@ -89,21 +92,32 @@ func (cf *ClientFile) Child() ([]File, error) {
}
func (cf *ClientFile) Stat() (*FileInfo, error) {
- return &FileInfo{cf.stat}, nil
+ st, err := cf.client.Stat(context.TODO(), cf.fid.fid)
+ if err != nil {
+ return nil, err
+ }
+ return &FileInfo{*st}, nil
}
func (cf *ClientFile) Qid() Qid {
- return cf.stat.Qid
+ return cf.qid
}
func (cf *ClientFile) Open(mode OpenMode) error {
- cf.fid.OMode = mode
+ qid, iounit, err := cf.client.Open(context.TODO(), cf.fid.fid, mode)
+ if err != nil {
+ return err
+ }
+ cf.qid = qid
+ cf.iounit = iounit
+ cf.fid.omode = mode
return nil
}
func (cf *ClientFile) Close() error {
- cf.fid.OMode = -1
- return nil
+ err := cf.client.Clunk(context.TODO(), cf.fid.fid)
+ cf.fid = nil
+ return err
}
func (cf *ClientFile) Read(b []byte) (int, error) {
diff --git a/fs.go b/fs.go
@@ -10,6 +10,7 @@ type FS interface {
type ClientFS struct {
root *ClientFile
+ client *Client
}
func (cfs ClientFS) Root() File {