// Package store defines storage interfaces and a filesystem-backed // implementation used by the 9P server. package store import ( "context" "os" "time" ) // StoreEntry is an open handle to a single named blob. type StoreEntry interface { Stat() (os.FileInfo, error) Read() ([]byte, error) Write(data []byte) error BlockingRead(ctx context.Context, base string) (content []byte, nextBase string, err error) // OneShot returns true if the entry yields data once per open (offset>0 → EOF). OneShot() bool // IsBlocking returns true if Read blocks until data is available (use BlockingRead). IsBlocking() bool // Async returns true if writes should be dispatched asynchronously. Async() bool } // Store is a named collection of entries. type Store interface { Stat(name string) (os.FileInfo, error) List() ([]os.DirEntry, error) Open(name string) (StoreEntry, error) Create(name string) error Delete(name string) error Rename(oldName, newName string) error } // Runnable is a running agent that can be observed and controlled. type Runnable interface { RunnableID() string Cancel() Interrupt() AppendLog([]byte) LogInfo() (length int, vers uint32) } // EntryConfig implements StoreEntry via function pointers. type EntryConfig struct { StatFn func() (os.FileInfo, error) ReadFn func() ([]byte, error) WriteFn func([]byte) error BlockingReadFn func(context.Context, string) ([]byte, string, error) OneShot_ bool IsBlocking_ bool Async_ bool } func (e *EntryConfig) Stat() (os.FileInfo, error) { return e.StatFn() } func (e *EntryConfig) Read() ([]byte, error) { return e.ReadFn() } func (e *EntryConfig) Write(data []byte) error { return e.WriteFn(data) } func (e *EntryConfig) BlockingRead(ctx context.Context, base string) ([]byte, string, error) { return e.BlockingReadFn(ctx, base) } func (e *EntryConfig) OneShot() bool { return e.OneShot_ } func (e *EntryConfig) IsBlocking() bool { return e.IsBlocking_ } func (e *EntryConfig) Async() bool { return e.Async_ } // SyntheticFileInfo implements os.FileInfo for entries with no backing file. type SyntheticFileInfo struct { Name_ string Mode_ os.FileMode Size_ int64 IsDir_ bool } func (f *SyntheticFileInfo) Name() string { return f.Name_ } func (f *SyntheticFileInfo) Size() int64 { return f.Size_ } func (f *SyntheticFileInfo) Mode() os.FileMode { return f.Mode_ } func (f *SyntheticFileInfo) ModTime() time.Time { return time.Time{} } func (f *SyntheticFileInfo) IsDir() bool { return f.IsDir_ } func (f *SyntheticFileInfo) Sys() any { return nil } // SyntheticEntry implements os.DirEntry for entries with no backing file. type SyntheticEntry struct { Name_ string Mode_ os.FileMode IsDir_ bool } func (e *SyntheticEntry) Name() string { return e.Name_ } func (e *SyntheticEntry) IsDir() bool { return e.IsDir_ } func (e *SyntheticEntry) Type() os.FileMode { if e.IsDir_ { return os.ModeDir } return 0 } func (e *SyntheticEntry) Info() (os.FileInfo, error) { return &SyntheticFileInfo{Name_: e.Name_, Mode_: e.Mode_, IsDir_: e.IsDir_}, nil } // FileEntry returns a synthetic file DirEntry. func FileEntry(name string, mode os.FileMode) os.DirEntry { return &SyntheticEntry{Name_: name, Mode_: mode} } // DirEntry returns a synthetic directory DirEntry. func DirEntry(name string, mode os.FileMode) os.DirEntry { return &SyntheticEntry{Name_: name, Mode_: mode, IsDir_: true} }