Path: blob/main/vendor/github.com/spf13/afero/iofs.go
2875 views
//go:build go1.161// +build go1.1623package afero45import (6"io"7"io/fs"8"os"9"path"10"sort"11"time"1213"github.com/spf13/afero/internal/common"14)1516// IOFS adopts afero.Fs to stdlib io/fs.FS17type IOFS struct {18Fs19}2021func NewIOFS(fs Fs) IOFS {22return IOFS{Fs: fs}23}2425var (26_ fs.FS = IOFS{}27_ fs.GlobFS = IOFS{}28_ fs.ReadDirFS = IOFS{}29_ fs.ReadFileFS = IOFS{}30_ fs.StatFS = IOFS{}31_ fs.SubFS = IOFS{}32)3334func (iofs IOFS) Open(name string) (fs.File, error) {35const op = "open"3637// by convention for fs.FS implementations we should perform this check38if !fs.ValidPath(name) {39return nil, iofs.wrapError(op, name, fs.ErrInvalid)40}4142file, err := iofs.Fs.Open(name)43if err != nil {44return nil, iofs.wrapError(op, name, err)45}4647// file should implement fs.ReadDirFile48if _, ok := file.(fs.ReadDirFile); !ok {49file = readDirFile{file}50}5152return file, nil53}5455func (iofs IOFS) Glob(pattern string) ([]string, error) {56const op = "glob"5758// afero.Glob does not perform this check but it's required for implementations59if _, err := path.Match(pattern, ""); err != nil {60return nil, iofs.wrapError(op, pattern, err)61}6263items, err := Glob(iofs.Fs, pattern)64if err != nil {65return nil, iofs.wrapError(op, pattern, err)66}6768return items, nil69}7071func (iofs IOFS) ReadDir(name string) ([]fs.DirEntry, error) {72f, err := iofs.Fs.Open(name)73if err != nil {74return nil, iofs.wrapError("readdir", name, err)75}7677defer f.Close()7879if rdf, ok := f.(fs.ReadDirFile); ok {80items, err := rdf.ReadDir(-1)81if err != nil {82return nil, iofs.wrapError("readdir", name, err)83}84sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() })85return items, nil86}8788items, err := f.Readdir(-1)89if err != nil {90return nil, iofs.wrapError("readdir", name, err)91}92sort.Sort(byName(items))9394ret := make([]fs.DirEntry, len(items))95for i := range items {96ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}97}9899return ret, nil100}101102func (iofs IOFS) ReadFile(name string) ([]byte, error) {103const op = "readfile"104105if !fs.ValidPath(name) {106return nil, iofs.wrapError(op, name, fs.ErrInvalid)107}108109bytes, err := ReadFile(iofs.Fs, name)110if err != nil {111return nil, iofs.wrapError(op, name, err)112}113114return bytes, nil115}116117func (iofs IOFS) Sub(dir string) (fs.FS, error) { return IOFS{NewBasePathFs(iofs.Fs, dir)}, nil }118119func (IOFS) wrapError(op, path string, err error) error {120if _, ok := err.(*fs.PathError); ok {121return err // don't need to wrap again122}123124return &fs.PathError{125Op: op,126Path: path,127Err: err,128}129}130131// readDirFile provides adapter from afero.File to fs.ReadDirFile needed for correct Open132type readDirFile struct {133File134}135136var _ fs.ReadDirFile = readDirFile{}137138func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {139items, err := r.Readdir(n)140if err != nil {141return nil, err142}143144ret := make([]fs.DirEntry, len(items))145for i := range items {146ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}147}148149return ret, nil150}151152// FromIOFS adopts io/fs.FS to use it as afero.Fs153// Note that io/fs.FS is read-only so all mutating methods will return fs.PathError with fs.ErrPermission154// To store modifications you may use afero.CopyOnWriteFs155type FromIOFS struct {156fs.FS157}158159var _ Fs = FromIOFS{}160161func (f FromIOFS) Create(name string) (File, error) { return nil, notImplemented("create", name) }162163func (f FromIOFS) Mkdir(164name string,165perm os.FileMode,166) error {167return notImplemented("mkdir", name)168}169170func (f FromIOFS) MkdirAll(path string, perm os.FileMode) error {171return notImplemented("mkdirall", path)172}173174func (f FromIOFS) Open(name string) (File, error) {175file, err := f.FS.Open(name)176if err != nil {177return nil, err178}179180return fromIOFSFile{File: file, name: name}, nil181}182183func (f FromIOFS) OpenFile(name string, flag int, perm os.FileMode) (File, error) {184return f.Open(name)185}186187func (f FromIOFS) Remove(name string) error {188return notImplemented("remove", name)189}190191func (f FromIOFS) RemoveAll(path string) error {192return notImplemented("removeall", path)193}194195func (f FromIOFS) Rename(oldname, newname string) error {196return notImplemented("rename", oldname)197}198199func (f FromIOFS) Stat(name string) (os.FileInfo, error) { return fs.Stat(f.FS, name) }200201func (f FromIOFS) Name() string { return "fromiofs" }202203func (f FromIOFS) Chmod(name string, mode os.FileMode) error {204return notImplemented("chmod", name)205}206207func (f FromIOFS) Chown(name string, uid, gid int) error {208return notImplemented("chown", name)209}210211func (f FromIOFS) Chtimes(name string, atime time.Time, mtime time.Time) error {212return notImplemented("chtimes", name)213}214215type fromIOFSFile struct {216fs.File217name string218}219220func (f fromIOFSFile) ReadAt(p []byte, off int64) (n int, err error) {221readerAt, ok := f.File.(io.ReaderAt)222if !ok {223return -1, notImplemented("readat", f.name)224}225226return readerAt.ReadAt(p, off)227}228229func (f fromIOFSFile) Seek(offset int64, whence int) (int64, error) {230seeker, ok := f.File.(io.Seeker)231if !ok {232return -1, notImplemented("seek", f.name)233}234235return seeker.Seek(offset, whence)236}237238func (f fromIOFSFile) Write(p []byte) (n int, err error) {239return -1, notImplemented("write", f.name)240}241242func (f fromIOFSFile) WriteAt(p []byte, off int64) (n int, err error) {243return -1, notImplemented("writeat", f.name)244}245246func (f fromIOFSFile) Name() string { return f.name }247248func (f fromIOFSFile) Readdir(count int) ([]os.FileInfo, error) {249rdfile, ok := f.File.(fs.ReadDirFile)250if !ok {251return nil, notImplemented("readdir", f.name)252}253254entries, err := rdfile.ReadDir(count)255if err != nil {256return nil, err257}258259ret := make([]os.FileInfo, len(entries))260for i := range entries {261ret[i], err = entries[i].Info()262if err != nil {263return nil, err264}265}266267return ret, nil268}269270func (f fromIOFSFile) Readdirnames(n int) ([]string, error) {271rdfile, ok := f.File.(fs.ReadDirFile)272if !ok {273return nil, notImplemented("readdir", f.name)274}275276entries, err := rdfile.ReadDir(n)277if err != nil {278return nil, err279}280281ret := make([]string, len(entries))282for i := range entries {283ret[i] = entries[i].Name()284}285286return ret, nil287}288289func (f fromIOFSFile) Sync() error { return nil }290291func (f fromIOFSFile) Truncate(size int64) error {292return notImplemented("truncate", f.name)293}294295func (f fromIOFSFile) WriteString(s string) (ret int, err error) {296return -1, notImplemented("writestring", f.name)297}298299func notImplemented(op, path string) error {300return &fs.PathError{Op: op, Path: path, Err: fs.ErrPermission}301}302303304