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