1// Copyright 2020 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package fs 6 7import ( 8 "errors" 9 "internal/bytealg" 10 "slices" 11) 12 13// ReadDirFS is the interface implemented by a file system 14// that provides an optimized implementation of [ReadDir]. 15type ReadDirFS interface { 16 FS 17 18 // ReadDir reads the named directory 19 // and returns a list of directory entries sorted by filename. 20 ReadDir(name string) ([]DirEntry, error) 21} 22 23// ReadDir reads the named directory 24// and returns a list of directory entries sorted by filename. 25// 26// If fs implements [ReadDirFS], ReadDir calls fs.ReadDir. 27// Otherwise ReadDir calls fs.Open and uses ReadDir and Close 28// on the returned file. 29func ReadDir(fsys FS, name string) ([]DirEntry, error) { 30 if fsys, ok := fsys.(ReadDirFS); ok { 31 return fsys.ReadDir(name) 32 } 33 34 file, err := fsys.Open(name) 35 if err != nil { 36 return nil, err 37 } 38 defer file.Close() 39 40 dir, ok := file.(ReadDirFile) 41 if !ok { 42 return nil, &PathError{Op: "readdir", Path: name, Err: errors.New("not implemented")} 43 } 44 45 list, err := dir.ReadDir(-1) 46 slices.SortFunc(list, func(a, b DirEntry) int { 47 return bytealg.CompareString(a.Name(), b.Name()) 48 }) 49 return list, err 50} 51 52// dirInfo is a DirEntry based on a FileInfo. 53type dirInfo struct { 54 fileInfo FileInfo 55} 56 57func (di dirInfo) IsDir() bool { 58 return di.fileInfo.IsDir() 59} 60 61func (di dirInfo) Type() FileMode { 62 return di.fileInfo.Mode().Type() 63} 64 65func (di dirInfo) Info() (FileInfo, error) { 66 return di.fileInfo, nil 67} 68 69func (di dirInfo) Name() string { 70 return di.fileInfo.Name() 71} 72 73func (di dirInfo) String() string { 74 return FormatDirEntry(di) 75} 76 77// FileInfoToDirEntry returns a [DirEntry] that returns information from info. 78// If info is nil, FileInfoToDirEntry returns nil. 79func FileInfoToDirEntry(info FileInfo) DirEntry { 80 if info == nil { 81 return nil 82 } 83 return dirInfo{fileInfo: info} 84} 85