113 lines
2.9 KiB
Go
113 lines
2.9 KiB
Go
package p9
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"ollie/pkg/paths"
|
|
)
|
|
|
|
// sessionStoreFiles maps fixed file entries in s/ to their permissions.
|
|
// Add an entry here to expose a new file; the server uses this map for
|
|
// routing, mode, and stat length.
|
|
var sessionStoreFiles = map[string]os.FileMode{
|
|
"new": 0666,
|
|
"idx": 0444,
|
|
"ls": 0555,
|
|
"kill": 0555,
|
|
"sh": 0555,
|
|
}
|
|
|
|
// sessionStoreOrder defines the listing order for fixed s/ entries.
|
|
var sessionStoreOrder = []string{"new", "idx", "ls", "kill", "sh"}
|
|
|
|
// SessionStore implements Store for the /s/ directory.
|
|
// Entries are session IDs (directories) plus the synthetic files "new" and "idx".
|
|
// Put("new", data) creates a session; Delete(id) kills one; Rename renames one.
|
|
type SessionStore struct {
|
|
srv *Server
|
|
}
|
|
|
|
func (s *SessionStore) List() ([]os.DirEntry, error) {
|
|
entries := make([]os.DirEntry, 0, len(sessionStoreOrder))
|
|
for _, name := range sessionStoreOrder {
|
|
entries = append(entries, syntheticEntry(name, sessionStoreFiles[name]))
|
|
}
|
|
s.srv.mu.RLock()
|
|
for id := range s.srv.sessions {
|
|
entries = append(entries, syntheticDirEntry(id, 0555))
|
|
}
|
|
s.srv.mu.RUnlock()
|
|
return entries, nil
|
|
}
|
|
|
|
func (s *SessionStore) Stat(name string) (os.FileInfo, error) {
|
|
if mode, ok := sessionStoreFiles[name]; ok {
|
|
return &syntheticFileInfo{Name_: name, Mode_: mode}, nil
|
|
}
|
|
s.srv.mu.RLock()
|
|
_, ok := s.srv.sessions[name]
|
|
s.srv.mu.RUnlock()
|
|
if ok {
|
|
return &syntheticFileInfo{Name_: name, Mode_: 0555, IsDir_: true}, nil
|
|
}
|
|
return nil, fmt.Errorf("%s: not found", name)
|
|
}
|
|
|
|
func (s *SessionStore) Get(name string) ([]byte, error) {
|
|
switch name {
|
|
case "new":
|
|
return []byte("name=\ncwd=\nbackend=\nmodel=\nagent=\n"), nil
|
|
case "idx":
|
|
return s.index(), nil
|
|
default:
|
|
if _, ok := sessionStoreFiles[name]; ok {
|
|
return os.ReadFile(paths.CfgDir() + "/scripts/s/" + name)
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("%s: not a readable file", name)
|
|
}
|
|
|
|
func (s *SessionStore) Put(name string, data []byte) error {
|
|
if name != "new" {
|
|
return fmt.Errorf("%s: not writable", name)
|
|
}
|
|
return s.srv.handleNewSession(strings.TrimSpace(string(data)))
|
|
}
|
|
|
|
func (s *SessionStore) Delete(name string) error {
|
|
s.srv.mu.RLock()
|
|
_, ok := s.srv.sessions[name]
|
|
s.srv.mu.RUnlock()
|
|
if !ok {
|
|
return fmt.Errorf("session not found: %s", name)
|
|
}
|
|
s.srv.killSession(name)
|
|
return nil
|
|
}
|
|
|
|
func (s *SessionStore) Create(name string) error {
|
|
return fmt.Errorf("create not supported for sessions")
|
|
}
|
|
|
|
func (s *SessionStore) Rename(oldName, newName string) error {
|
|
return s.srv.renameSession(oldName, newName)
|
|
}
|
|
|
|
func (s *SessionStore) index() []byte {
|
|
var sb strings.Builder
|
|
s.srv.mu.RLock()
|
|
for id, sess := range s.srv.sessions {
|
|
sess.mu.RLock()
|
|
state := sess.core.State()
|
|
cwd := sess.core.CWD()
|
|
be := sess.core.BackendName()
|
|
model := sess.core.ModelName()
|
|
sess.mu.RUnlock()
|
|
fmt.Fprintf(&sb, "%s\t%s\t%s\t%s\t%s\n", id, state, cwd, be, model)
|
|
}
|
|
s.srv.mu.RUnlock()
|
|
return []byte(sb.String())
|
|
}
|