summaryrefslogtreecommitdiffstats
path: root/back/cmd/authfs/session.go
diff options
context:
space:
mode:
Diffstat (limited to 'back/cmd/authfs/session.go')
-rw-r--r--back/cmd/authfs/session.go187
1 files changed, 187 insertions, 0 deletions
diff --git a/back/cmd/authfs/session.go b/back/cmd/authfs/session.go
new file mode 100644
index 0000000..2d4eb98
--- /dev/null
+++ b/back/cmd/authfs/session.go
@@ -0,0 +1,187 @@
+package main
+
+import (
+ "context"
+ "sync"
+
+ "github.com/docker-archive/go-p9p"
+)
+
+// Session implements the p9p.Session interface.
+type Session struct {
+ mu sync.Mutex
+ fids map[p9p.Fid]Fid
+ *Root
+}
+
+type Fid struct {
+ File
+ uname string
+}
+
+type File interface {
+ Qid() p9p.Qid
+ Stat() (p9p.Dir, error)
+ Open(mode p9p.Flag) error
+ Remove() error
+ Read(ctx context.Context, p []byte, offset int64) (n int, err error)
+ Write(ctx context.Context, p []byte, offset int64) (n int, err error)
+}
+
+type Dir interface {
+ File
+ Create(ctx context.Context, name string, perm uint32, mode p9p.Flag) (File, error)
+ Walk(ctx context.Context, name string) (File, error)
+}
+
+func NewSession(root *Root) p9p.Session {
+ return &Session{
+ fids: make(map[p9p.Fid]Fid),
+ Root: root,
+ }
+}
+
+func (s *Session) Auth(ctx context.Context, afid p9p.Fid, uname, aname string) (p9p.Qid, error) {
+ return p9p.Qid{}, p9p.MessageRerror{"authfs: no authentication required"}
+}
+
+func (s *Session) Attach(ctx context.Context, fid, afid p9p.Fid, uname, aname string) (p9p.Qid, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ if _, exists := s.fids[fid]; exists {
+ return p9p.Qid{}, p9p.ErrDupfid
+ }
+ f := Fid{s.root, uname}
+ s.fids[fid] = f
+ return f.Qid(), nil
+}
+
+func (s *Session) Clunk(ctx context.Context, fid p9p.Fid) error {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ if _, ok := s.fids[fid]; ok {
+ delete(s.fids, fid)
+ return nil
+ } else {
+ return p9p.ErrUnknownfid
+ }
+}
+
+func (s *Session) Remove(ctx context.Context, fid p9p.Fid) error {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ f, ok := s.fids[fid]
+ if !ok {
+ return p9p.ErrUnknownfid
+ }
+ delete(s.fids, fid) // clunk
+ return f.Remove()
+}
+
+func (s *Session) Walk(ctx context.Context, fid, newfid p9p.Fid, names ...string) ([]p9p.Qid, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ f, ok := s.fids[fid]
+ if !ok {
+ return nil, p9p.ErrUnknownfid
+ }
+
+ if _, exists := s.fids[newfid]; exists {
+ return nil, p9p.ErrDupfid
+ }
+
+ var (
+ qids []p9p.Qid
+ err error
+ dot = f
+ )
+ defer func() { s.fids[newfid] = dot }()
+ for _, name := range names {
+ dir, ok := dot.File.(Dir)
+ if !ok {
+ return qids, p9p.ErrWalknodir
+ }
+ dot.File, err = dir.Walk(ctx, name)
+ if err != nil {
+ return qids, err
+ }
+ qids = append(qids, dot.File.Qid())
+ }
+ return qids, nil
+}
+
+func (s *Session) Read(ctx context.Context, fid p9p.Fid, p []byte, offset int64) (n int, err error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ if f, ok := s.fids[fid]; ok {
+ return f.File.Read(ctx, p, offset)
+ } else {
+ return 0, p9p.ErrUnknownfid
+ }
+}
+
+func (s *Session) Write(ctx context.Context, fid p9p.Fid, p []byte, offset int64) (n int, err error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ if f, ok := s.fids[fid]; ok {
+ return f.File.Write(ctx, p, offset)
+ } else {
+ return 0, p9p.ErrUnknownfid
+ }
+}
+
+func (s *Session) Open(ctx context.Context, fid p9p.Fid, mode p9p.Flag) (p9p.Qid, uint32, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ f, ok := s.fids[fid]
+ if !ok {
+ return p9p.Qid{}, 0, p9p.ErrUnknownfid
+ }
+ if err := f.Open(mode); err != nil {
+ return p9p.Qid{}, 0, err
+ }
+ return f.File.Qid(), 0, nil
+}
+
+func (s *Session) Create(ctx context.Context, parent p9p.Fid, name string, perm uint32, mode p9p.Flag) (p9p.Qid, uint32, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ f, ok := s.fids[parent]
+ if !ok {
+ return p9p.Qid{}, 0, p9p.ErrUnknownfid
+ }
+ dir, ok := f.File.(Dir)
+ if !ok {
+ return p9p.Qid{}, 0, p9p.ErrCreatenondir
+ }
+
+ child, err := dir.Create(ctx, name, perm, mode)
+ return child.Qid(), 0, err
+}
+
+func (s *Session) Stat(ctx context.Context, fid p9p.Fid) (p9p.Dir, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ if f, ok := s.fids[fid]; ok {
+ return f.File.Stat()
+ } else {
+ return p9p.Dir{}, p9p.ErrUnknownfid
+ }
+}
+
+func (s *Session) WStat(ctx context.Context, fid p9p.Fid, dir p9p.Dir) error {
+ return p9p.ErrPerm
+}
+
+func (s *Session) Version() (msize int, version string) {
+ return p9p.DefaultMSize, p9p.DefaultVersion
+}