podman

Форк
0
298 строк · 6.4 Кб
1
//go:build go1.16
2
// +build go1.16
3

4
package afero
5

6
import (
7
	"io"
8
	"io/fs"
9
	"os"
10
	"path"
11
	"sort"
12
	"time"
13

14
	"github.com/spf13/afero/internal/common"
15
)
16

17
// IOFS adopts afero.Fs to stdlib io/fs.FS
18
type IOFS struct {
19
	Fs
20
}
21

22
func NewIOFS(fs Fs) IOFS {
23
	return IOFS{Fs: fs}
24
}
25

26
var (
27
	_ fs.FS         = IOFS{}
28
	_ fs.GlobFS     = IOFS{}
29
	_ fs.ReadDirFS  = IOFS{}
30
	_ fs.ReadFileFS = IOFS{}
31
	_ fs.StatFS     = IOFS{}
32
	_ fs.SubFS      = IOFS{}
33
)
34

35
func (iofs IOFS) Open(name string) (fs.File, error) {
36
	const op = "open"
37

38
	// by convention for fs.FS implementations we should perform this check
39
	if !fs.ValidPath(name) {
40
		return nil, iofs.wrapError(op, name, fs.ErrInvalid)
41
	}
42

43
	file, err := iofs.Fs.Open(name)
44
	if err != nil {
45
		return nil, iofs.wrapError(op, name, err)
46
	}
47

48
	// file should implement fs.ReadDirFile
49
	if _, ok := file.(fs.ReadDirFile); !ok {
50
		file = readDirFile{file}
51
	}
52

53
	return file, nil
54
}
55

56
func (iofs IOFS) Glob(pattern string) ([]string, error) {
57
	const op = "glob"
58

59
	// afero.Glob does not perform this check but it's required for implementations
60
	if _, err := path.Match(pattern, ""); err != nil {
61
		return nil, iofs.wrapError(op, pattern, err)
62
	}
63

64
	items, err := Glob(iofs.Fs, pattern)
65
	if err != nil {
66
		return nil, iofs.wrapError(op, pattern, err)
67
	}
68

69
	return items, nil
70
}
71

72
func (iofs IOFS) ReadDir(name string) ([]fs.DirEntry, error) {
73
	f, err := iofs.Fs.Open(name)
74
	if err != nil {
75
		return nil, iofs.wrapError("readdir", name, err)
76
	}
77

78
	defer f.Close()
79

80
	if rdf, ok := f.(fs.ReadDirFile); ok {
81
		items, err := rdf.ReadDir(-1)
82
		if err != nil {
83
			return nil, iofs.wrapError("readdir", name, err)
84
		}
85
		sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() })
86
		return items, nil
87
	}
88

89
	items, err := f.Readdir(-1)
90
	if err != nil {
91
		return nil, iofs.wrapError("readdir", name, err)
92
	}
93
	sort.Sort(byName(items))
94

95
	ret := make([]fs.DirEntry, len(items))
96
	for i := range items {
97
		ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}
98
	}
99

100
	return ret, nil
101
}
102

103
func (iofs IOFS) ReadFile(name string) ([]byte, error) {
104
	const op = "readfile"
105

106
	if !fs.ValidPath(name) {
107
		return nil, iofs.wrapError(op, name, fs.ErrInvalid)
108
	}
109

110
	bytes, err := ReadFile(iofs.Fs, name)
111
	if err != nil {
112
		return nil, iofs.wrapError(op, name, err)
113
	}
114

115
	return bytes, nil
116
}
117

118
func (iofs IOFS) Sub(dir string) (fs.FS, error) { return IOFS{NewBasePathFs(iofs.Fs, dir)}, nil }
119

120
func (IOFS) wrapError(op, path string, err error) error {
121
	if _, ok := err.(*fs.PathError); ok {
122
		return err // don't need to wrap again
123
	}
124

125
	return &fs.PathError{
126
		Op:   op,
127
		Path: path,
128
		Err:  err,
129
	}
130
}
131

132
// readDirFile provides adapter from afero.File to fs.ReadDirFile needed for correct Open
133
type readDirFile struct {
134
	File
135
}
136

137
var _ fs.ReadDirFile = readDirFile{}
138

139
func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
140
	items, err := r.File.Readdir(n)
141
	if err != nil {
142
		return nil, err
143
	}
144

145
	ret := make([]fs.DirEntry, len(items))
146
	for i := range items {
147
		ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}
148
	}
149

150
	return ret, nil
151
}
152

153
// FromIOFS adopts io/fs.FS to use it as afero.Fs
154
// Note that io/fs.FS is read-only so all mutating methods will return fs.PathError with fs.ErrPermission
155
// To store modifications you may use afero.CopyOnWriteFs
156
type FromIOFS struct {
157
	fs.FS
158
}
159

160
var _ Fs = FromIOFS{}
161

162
func (f FromIOFS) Create(name string) (File, error) { return nil, notImplemented("create", name) }
163

164
func (f FromIOFS) Mkdir(name string, perm os.FileMode) error { return notImplemented("mkdir", name) }
165

166
func (f FromIOFS) MkdirAll(path string, perm os.FileMode) error {
167
	return notImplemented("mkdirall", path)
168
}
169

170
func (f FromIOFS) Open(name string) (File, error) {
171
	file, err := f.FS.Open(name)
172
	if err != nil {
173
		return nil, err
174
	}
175

176
	return fromIOFSFile{File: file, name: name}, nil
177
}
178

179
func (f FromIOFS) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
180
	return f.Open(name)
181
}
182

183
func (f FromIOFS) Remove(name string) error {
184
	return notImplemented("remove", name)
185
}
186

187
func (f FromIOFS) RemoveAll(path string) error {
188
	return notImplemented("removeall", path)
189
}
190

191
func (f FromIOFS) Rename(oldname, newname string) error {
192
	return notImplemented("rename", oldname)
193
}
194

195
func (f FromIOFS) Stat(name string) (os.FileInfo, error) { return fs.Stat(f.FS, name) }
196

197
func (f FromIOFS) Name() string { return "fromiofs" }
198

199
func (f FromIOFS) Chmod(name string, mode os.FileMode) error {
200
	return notImplemented("chmod", name)
201
}
202

203
func (f FromIOFS) Chown(name string, uid, gid int) error {
204
	return notImplemented("chown", name)
205
}
206

207
func (f FromIOFS) Chtimes(name string, atime time.Time, mtime time.Time) error {
208
	return notImplemented("chtimes", name)
209
}
210

211
type fromIOFSFile struct {
212
	fs.File
213
	name string
214
}
215

216
func (f fromIOFSFile) ReadAt(p []byte, off int64) (n int, err error) {
217
	readerAt, ok := f.File.(io.ReaderAt)
218
	if !ok {
219
		return -1, notImplemented("readat", f.name)
220
	}
221

222
	return readerAt.ReadAt(p, off)
223
}
224

225
func (f fromIOFSFile) Seek(offset int64, whence int) (int64, error) {
226
	seeker, ok := f.File.(io.Seeker)
227
	if !ok {
228
		return -1, notImplemented("seek", f.name)
229
	}
230

231
	return seeker.Seek(offset, whence)
232
}
233

234
func (f fromIOFSFile) Write(p []byte) (n int, err error) {
235
	return -1, notImplemented("write", f.name)
236
}
237

238
func (f fromIOFSFile) WriteAt(p []byte, off int64) (n int, err error) {
239
	return -1, notImplemented("writeat", f.name)
240
}
241

242
func (f fromIOFSFile) Name() string { return f.name }
243

244
func (f fromIOFSFile) Readdir(count int) ([]os.FileInfo, error) {
245
	rdfile, ok := f.File.(fs.ReadDirFile)
246
	if !ok {
247
		return nil, notImplemented("readdir", f.name)
248
	}
249

250
	entries, err := rdfile.ReadDir(count)
251
	if err != nil {
252
		return nil, err
253
	}
254

255
	ret := make([]os.FileInfo, len(entries))
256
	for i := range entries {
257
		ret[i], err = entries[i].Info()
258

259
		if err != nil {
260
			return nil, err
261
		}
262
	}
263

264
	return ret, nil
265
}
266

267
func (f fromIOFSFile) Readdirnames(n int) ([]string, error) {
268
	rdfile, ok := f.File.(fs.ReadDirFile)
269
	if !ok {
270
		return nil, notImplemented("readdir", f.name)
271
	}
272

273
	entries, err := rdfile.ReadDir(n)
274
	if err != nil {
275
		return nil, err
276
	}
277

278
	ret := make([]string, len(entries))
279
	for i := range entries {
280
		ret[i] = entries[i].Name()
281
	}
282

283
	return ret, nil
284
}
285

286
func (f fromIOFSFile) Sync() error { return nil }
287

288
func (f fromIOFSFile) Truncate(size int64) error {
289
	return notImplemented("truncate", f.name)
290
}
291

292
func (f fromIOFSFile) WriteString(s string) (ret int, err error) {
293
	return -1, notImplemented("writestring", f.name)
294
}
295

296
func notImplemented(op, path string) error {
297
	return &fs.PathError{Op: op, Path: path, Err: fs.ErrPermission}
298
}
299

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.