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  }