package main import ( "bytes" p9 "github.com/Harvey-OS/ninep/protocol" "git.samanthony.xyz/buth/back/qver" ) type RootDir struct { *qver.Version *UsersDir *SessionsDir } func NewRootDir(path string) (*RootDir, error) { ver := qver.New() users, err := NewUsersDir(path, ver) if err != nil { ver.Close() return nil, err } sessions := NewSessionsDir(ver) return &RootDir{ver, users, sessions}, nil } func (r *RootDir) Close() { r.Version.Close() r.UsersDir.Close() r.SessionsDir.Close() } func (r *RootDir) Qid() (p9.QID, error) { ver, err := r.Version.Get() if err != nil { return p9.QID{}, err } return p9.QID{ Type: p9.QTDIR, Version: ver, Path: rootQidPath, }, nil } func (r *RootDir) Stat() (p9.Dir, error) { qid, err := r.Qid() if err != nil { return p9.Dir{}, err } return p9.Dir{ QID: qid, Mode: p9.DMDIR | p9.DMREAD, // TODO: atime, mtime Name: "/", }, nil } func (r *RootDir) Remove() error { return ErrPerm } func (r *RootDir) Open(mode p9.Mode) error { if mode != p9.OREAD { return ErrPerm } return nil } func (r *RootDir) Read(off p9.Offset, n p9.Count) ([]byte, error) { userInfo, err := r.UsersDir.Stat() if err != nil { return nil, err } sessInfo, err := r.SessionsDir.Stat() if err != nil { return nil, err } buf := new(bytes.Buffer) p9.Marshaldir(buf, userInfo) p9.Marshaldir(buf, sessInfo) b := buf.Bytes() lenb := uint64(len(b)) lo := clamp(uint64(off), 0, lenb) hi := clamp(lo+uint64(n), 0, lenb) return b[lo:hi], nil } func (r *RootDir) Write(off p9.Offset, b []byte) (p9.Count, error) { return 0, ErrPerm } func (r *RootDir) Create(name string, perm p9.Perm, mode p9.Mode) (File, error) { return nil, ErrPerm } func (r *RootDir) Walk(name string) (File, error) { switch name { case "users": return r.UsersDir, nil case "sessions": return r.SessionsDir, nil default: return nil, ErrFileNotExist } } func clamp(x, min, max uint64) uint64 { if x < min { x = min } if x > max { x = max } return x }