package virtfs import ( "context" "os" "time" ) // Standard permission constants for EDSL-built trees. const ( PermChildDir os.FileMode = 0555 PermIdx os.FileMode = 0444 PermMkdir os.FileMode = 0755 PermMkdirPrivate os.FileMode = 0700 ) // File is an open handle to a single named blob. type File interface { Stat() (os.FileInfo, error) Read() ([]byte, error) Write(data []byte) error Close() error // called when fid is clunked/closed BlockingRead(ctx context.Context, base string) (content []byte, nextBase string, err error) // Read-side contracts (mutually exclusive — at most one true): // BlockingReadMode — blocks up to 500ms for next value, returns it or empty, EOF on 2nd read // StreamMode — blocks indefinitely, streams data incrementally, FD lives until EOF // RdwrMode — write blocks until result produced, read returns result once BlockingReadMode() bool StreamMode() bool RdwrMode() bool } // fileConfig implements File via function pointers. type fileConfig struct { StatFn func() (os.FileInfo, error) ReadFn func() ([]byte, error) WriteFn func([]byte) error CloseFn func() error BlockingReadFn func(context.Context, string) ([]byte, string, error) BlockingRead_ bool // one-shot waiter: block 500ms, return once, EOF on 2nd read StreamMode_ bool // indefinite stream: block forever, keep FD open Rdwr_ bool // rdwr: write blocks on write, read returns result once } func (e *fileConfig) Stat() (os.FileInfo, error) { return e.StatFn() } func (e *fileConfig) Read() ([]byte, error) { return e.ReadFn() } func (e *fileConfig) Write(data []byte) error { return e.WriteFn(data) } func (e *fileConfig) Close() error { if e.CloseFn != nil { return e.CloseFn() } return nil } func (e *fileConfig) BlockingRead(ctx context.Context, base string) ([]byte, string, error) { return e.BlockingReadFn(ctx, base) } func (e *fileConfig) BlockingReadMode() bool { return e.BlockingRead_ } func (e *fileConfig) StreamMode() bool { return e.StreamMode_ } func (e *fileConfig) RdwrMode() bool { return e.Rdwr_ } // SyntheticFileInfo implements os.FileInfo for entries with no backing file. type SyntheticFileInfo struct { Name_ string Mode_ os.FileMode Size_ int64 IsDir_ bool UID_ string GID_ string Vers_ uint32 } 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} }