// Package vfs provides a virtual filesystem which can be written to. // vfs.FS is a superset of io/fs.FS. package vfs import ( "io" "io/fs" ) // FS represents sacks/fssacks' minimal view of a filesystem. // Names are interpreted as in io/fs: no leading slash, the entire namespace // may be edited by sacks/fssacks to provide sacks.Sack facilities. // Names are slash-separated. Use "path" instead of "path/filepath". // // Currently, sacks/fssacks only accesses its FS synchronously. There is no // guarantee for this to stay that way, however. type FS interface { // Lstat may be implemented using os.Stat, offering all symlinks and the // resulting possibly wider filesystem reach to sacks/fssacks. Lstat(name string) (fs.FileInfo, error) // sacks/fssacks will always call Chmod with perm==0444. Chmod(name string, perm fs.FileMode) error // sacks/fssacks will always call MkdirAll with perm==0755 MkdirAll(name string, perm fs.FileMode) error // sacks/fssacks will only ever call Remove on directories (meaning paths // it reasonably thinks are directories: an (exotic) filesystem may for // example both resolve "a.tar/b.eml" and "a.tar" to files; in this case, // "a.tar" may be considered a directory since it appears as non-leaf in // a valid path). // NOTE (internal): Specialising this to "Rmdir" does not by itself // guarantee sack monotonicity (meaning the impossibility to lose data) // as Rename could be used to stamp the empty file onto everything. // // Remove errors if name doesn't exist. Remove(name string) error // NOTE: ReadDir(".") is the correct root-level call. // Implementations are free but not required to also understand "/" and "". ReadDir(name string) ([]fs.DirEntry, error) // Rename is expected to be atomic. Rename(oldname, newname string) error // sacks/fssacks will always call OpenFile with // flag==os.O_WRONLY|os.O_CREATE|os.O_EXCL and perm==0444 or // flag==os.O_RDONLY and perm==0. // The returned io.ReadWriteCloser MUST error either on Read or Write. // // BUG(jfrech): 2024-05-20: ReadWriteSyncCloser is an **awful** interface! OpenFile(name string, flag int, perm fs.FileMode) (ReadWriteSyncCloser, error) } type WriteSyncCloser interface { io.Writer Sync() error // must be idempotent io.Closer } type ReadWriteSyncCloser interface { io.Reader WriteSyncCloser }