package vfs import ( "errors" "io/fs" "sync" ) // MultiReader passes {Lstat, ReadDir, OpenFile(flag=O_RDONLY)} down the stack // and all others are invalid // // MultiReader is modeled after [io.MultiReader]. func MultiReader(fsyss ...FS) FS { var mu sync.Mutex return Filesystem{ LstatFunc: func(name string) (fs.FileInfo, error) { if len(fsyss) == 0 { return nil, fs.ErrNotExist } mu.Lock() defer mu.Unlock() for _, fsys := range fsyss { info, err := fsys.Lstat(name) if !errors.Is(err, fs.ErrNotExist) { return info, err } } return nil, fs.ErrNotExist }, ReadDirFunc: func(name string) ([]fs.DirEntry, error) { if len(fsyss) == 0 { return nil, fs.ErrNotExist } mu.Lock() defer mu.Unlock() for _, fsys := range fsyss { entries, err := fsys.ReadDir(name) if !errors.Is(err, fs.ErrNotExist) { return entries, err } } return nil, fs.ErrNotExist }, OpenFileFunc: func(name string, flag int, perm fs.FileMode) (ReadWriteSyncCloser, error) { if len(fsyss) == 0 { return nil, fs.ErrNotExist } else if flag != O_RDONLY { return nil, fs.ErrInvalid } mu.Lock() defer mu.Unlock() for _, fsys := range fsyss { f, err := fsys.OpenFile(name, flag, perm) if !errors.Is(err, fs.ErrNotExist) { return f, err } } return nil, fs.ErrNotExist }, } } // WithDevStdin overlays dev/stdin. // // BUG(jfrech): 2024-05-21: Not implemented. func WithDevStdin(fsys FS) FS { return fsys /* // TODO(jfrech): 2024-05-21: Implement or expunge. return Filesystem{ LstatFunc: func(name string) (fs.FileInfo, error) { if name == "dev/stdin" { panic("nyi") } return fsys.Lstat(name) } ChmodFunc: func(name string, perm fs.FileMode) error MkdirAllFunc: func(name string, perm fs.FileMode) error RemoveFunc: func(name string) error ReadDirFunc: func(name string) ([]fs.DirEntry, error) RenameFunc: func(oldname, newname string) error OpenFileFunc: func(name string, flag int, perm fs.FileMode) (ReadWriteSyncCloser, error) LstatFunc: func(name string) (fs.FileInfo, error) { return nil, fs.ErrNotExist }, OpenFileFunc: func(name string, flag int, perm fs.FileMode) (ReadWriteSyncCloser, error) { }, */ }