diff options
Diffstat (limited to 'back/cmd/authfs/session.go')
| -rw-r--r-- | back/cmd/authfs/session.go | 187 |
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 +} |