github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/io/fs/fs.go (about) 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 5 // Package fs defines basic interfaces to a file system. 6 // A file system can be provided by the host operating system 7 // but also by other packages. 8 package fs 9 10 import ( 11 "internal/oserror" 12 "time" 13 ) 14 15 // An FS provides access to a hierarchical file system. 16 // 17 // The FS interface is the minimum implementation required of the file system. 18 // A file system may implement additional interfaces, 19 // such as ReadFileFS, to provide additional or optimized functionality. 20 type FS interface { 21 // Open opens the named file. 22 // 23 // When Open returns an error, it should be of type *PathError 24 // with the Op field set to "open", the Path field set to name, 25 // and the Err field describing the problem. 26 // 27 // Open should reject attempts to open names that do not satisfy 28 // ValidPath(name), returning a *PathError with Err set to 29 // ErrInvalid or ErrNotExist. 30 Open(name string) (File, error) 31 } 32 33 // ValidPath reports whether the given path name 34 // is valid for use in a call to Open. 35 // Path names passed to open are unrooted, slash-separated 36 // sequences of path elements, like “x/y/z”. 37 // Path names must not contain a “.” or “..” or empty element, 38 // except for the special case that the root directory is named “.”. 39 // 40 // Paths are slash-separated on all systems, even Windows. 41 // Backslashes must not appear in path names. 42 func ValidPath(name string) bool { 43 if name == "." { 44 // special case 45 return true 46 } 47 48 // Iterate over elements in name, checking each. 49 for { 50 i := 0 51 for i < len(name) && name[i] != '/' { 52 if name[i] == '\\' { 53 return false 54 } 55 i++ 56 } 57 elem := name[:i] 58 if elem == "" || elem == "." || elem == ".." { 59 return false 60 } 61 if i == len(name) { 62 return true // reached clean ending 63 } 64 name = name[i+1:] 65 } 66 } 67 68 // A File provides access to a single file. 69 // The File interface is the minimum implementation required of the file. 70 // A file may implement additional interfaces, such as 71 // ReadDirFile, ReaderAt, or Seeker, to provide additional or optimized functionality. 72 type File interface { 73 Stat() (FileInfo, error) 74 Read([]byte) (int, error) 75 Close() error 76 } 77 78 // A DirEntry is an entry read from a directory 79 // (using the ReadDir function or a ReadDirFile's ReadDir method). 80 type DirEntry interface { 81 // Name returns the name of the file (or subdirectory) described by the entry. 82 // This name is only the final element of the path (the base name), not the entire path. 83 // For example, Name would return "hello.go" not "/home/gopher/hello.go". 84 Name() string 85 86 // IsDir reports whether the entry describes a directory. 87 IsDir() bool 88 89 // Type returns the type bits for the entry. 90 // The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method. 91 Type() FileMode 92 93 // Info returns the FileInfo for the file or subdirectory described by the entry. 94 // The returned FileInfo may be from the time of the original directory read 95 // or from the time of the call to Info. If the file has been removed or renamed 96 // since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist). 97 // If the entry denotes a symbolic link, Info reports the information about the link itself, 98 // not the link's target. 99 Info() (FileInfo, error) 100 } 101 102 // A ReadDirFile is a directory file whose entries can be read with the ReadDir method. 103 // Every directory file should implement this interface. 104 // (It is permissible for any file to implement this interface, 105 // but if so ReadDir should return an error for non-directories.) 106 type ReadDirFile interface { 107 File 108 109 // ReadDir reads the contents of the directory and returns 110 // a slice of up to n DirEntry values in directory order. 111 // Subsequent calls on the same file will yield further DirEntry values. 112 // 113 // If n > 0, ReadDir returns at most n DirEntry structures. 114 // In this case, if ReadDir returns an empty slice, it will return 115 // a non-nil error explaining why. 116 // At the end of a directory, the error is io.EOF. 117 // 118 // If n <= 0, ReadDir returns all the DirEntry values from the directory 119 // in a single slice. In this case, if ReadDir succeeds (reads all the way 120 // to the end of the directory), it returns the slice and a nil error. 121 // If it encounters an error before the end of the directory, 122 // ReadDir returns the DirEntry list read until that point and a non-nil error. 123 ReadDir(n int) ([]DirEntry, error) 124 } 125 126 // Generic file system errors. 127 // Errors returned by file systems can be tested against these errors 128 // using errors.Is. 129 var ( 130 ErrInvalid = errInvalid() // "invalid argument" 131 ErrPermission = errPermission() // "permission denied" 132 ErrExist = errExist() // "file already exists" 133 ErrNotExist = errNotExist() // "file does not exist" 134 ErrClosed = errClosed() // "file already closed" 135 ) 136 137 func errInvalid() error { return oserror.ErrInvalid } 138 func errPermission() error { return oserror.ErrPermission } 139 func errExist() error { return oserror.ErrExist } 140 func errNotExist() error { return oserror.ErrNotExist } 141 func errClosed() error { return oserror.ErrClosed } 142 143 // A FileInfo describes a file and is returned by Stat. 144 type FileInfo interface { 145 Name() string // base name of the file 146 Size() int64 // length in bytes for regular files; system-dependent for others 147 Mode() FileMode // file mode bits 148 ModTime() time.Time // modification time 149 IsDir() bool // abbreviation for Mode().IsDir() 150 Sys() interface{} // underlying data source (can return nil) 151 } 152 153 // A FileMode represents a file's mode and permission bits. 154 // The bits have the same definition on all systems, so that 155 // information about files can be moved from one system 156 // to another portably. Not all bits apply to all systems. 157 // The only required bit is ModeDir for directories. 158 type FileMode uint32 159 160 // The defined file mode bits are the most significant bits of the FileMode. 161 // The nine least-significant bits are the standard Unix rwxrwxrwx permissions. 162 // The values of these bits should be considered part of the public API and 163 // may be used in wire protocols or disk representations: they must not be 164 // changed, although new bits might be added. 165 const ( 166 // The single letters are the abbreviations 167 // used by the String method's formatting. 168 ModeDir FileMode = 1 << (32 - 1 - iota) // d: is a directory 169 ModeAppend // a: append-only 170 ModeExclusive // l: exclusive use 171 ModeTemporary // T: temporary file; Plan 9 only 172 ModeSymlink // L: symbolic link 173 ModeDevice // D: device file 174 ModeNamedPipe // p: named pipe (FIFO) 175 ModeSocket // S: Unix domain socket 176 ModeSetuid // u: setuid 177 ModeSetgid // g: setgid 178 ModeCharDevice // c: Unix character device, when ModeDevice is set 179 ModeSticky // t: sticky 180 ModeIrregular // ?: non-regular file; nothing else is known about this file 181 182 // Mask for the type bits. For regular files, none will be set. 183 ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular 184 185 ModePerm FileMode = 0777 // Unix permission bits 186 ) 187 188 func (m FileMode) String() string { 189 const str = "dalTLDpSugct?" 190 var buf [32]byte // Mode is uint32. 191 w := 0 192 for i, c := range str { 193 if m&(1<<uint(32-1-i)) != 0 { 194 buf[w] = byte(c) 195 w++ 196 } 197 } 198 if w == 0 { 199 buf[w] = '-' 200 w++ 201 } 202 const rwx = "rwxrwxrwx" 203 for i, c := range rwx { 204 if m&(1<<uint(9-1-i)) != 0 { 205 buf[w] = byte(c) 206 } else { 207 buf[w] = '-' 208 } 209 w++ 210 } 211 return string(buf[:w]) 212 } 213 214 // IsDir reports whether m describes a directory. 215 // That is, it tests for the ModeDir bit being set in m. 216 func (m FileMode) IsDir() bool { 217 return m&ModeDir != 0 218 } 219 220 // IsRegular reports whether m describes a regular file. 221 // That is, it tests that no mode type bits are set. 222 func (m FileMode) IsRegular() bool { 223 return m&ModeType == 0 224 } 225 226 // Perm returns the Unix permission bits in m (m & ModePerm). 227 func (m FileMode) Perm() FileMode { 228 return m & ModePerm 229 } 230 231 // Type returns type bits in m (m & ModeType). 232 func (m FileMode) Type() FileMode { 233 return m & ModeType 234 } 235 236 // PathError records an error and the operation and file path that caused it. 237 type PathError struct { 238 Op string 239 Path string 240 Err error 241 } 242 243 func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() } 244 245 func (e *PathError) Unwrap() error { return e.Err } 246 247 // Timeout reports whether this error represents a timeout. 248 func (e *PathError) Timeout() bool { 249 t, ok := e.Err.(interface{ Timeout() bool }) 250 return ok && t.Timeout() 251 }