blob: b9eae569f9ecd58129e0e42f2309ac64351e5ecf [file] [log] [blame]
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package fs defines basic interfaces to a file system.
// A file system can be provided by the host operating system
// but also by other packages.
package fs
import (
"os"
"unicode/utf8"
)
// An FS provides access to a hierarchical file system.
//
// The FS interface is the minimum implementation required of the file system.
// A file system may implement additional interfaces,
// such as ReadFileFS, to provide additional or optimized functionality.
type FS interface {
// Open opens the named file.
//
// When Open returns an error, it should be of type *PathError
// with the Op field set to "open", the Path field set to name,
// and the Err field describing the problem.
//
// Open should reject attempts to open names that do not satisfy
// ValidPath(name), returning a *PathError with Err set to
// ErrInvalid or ErrNotExist.
Open(name string) (File, error)
}
// ValidPath reports whether the given path name
// is valid for use in a call to Open.
//
// Path names passed to open are UTF-8-encoded,
// unrooted, slash-separated sequences of path elements, like “x/y/z”.
// Path names must not contain an element that is “.” or “..” or the empty string,
// except for the special case that the root directory is named “.”.
// Paths must not start or end with a slash: “/x” and “x/” are invalid.
//
// Note that paths are slash-separated on all systems, even Windows.
// Paths containing other characters such as backslash and colon
// are accepted as valid, but those characters must never be
// interpreted by an FS implementation as path element separators.
func ValidPath(name string) bool {
if !utf8.ValidString(name) {
return false
}
if name == "." {
// special case
return true
}
// Iterate over elements in name, checking each.
for {
i := 0
for i < len(name) && name[i] != '/' {
i++
}
elem := name[:i]
if elem == "" || elem == "." || elem == ".." {
return false
}
if i == len(name) {
return true // reached clean ending
}
name = name[i+1:]
}
}
// A ReadDirFile is a directory file whose entries can be read with the ReadDir method.
// Every directory file should implement this interface.
// (It is permissible for any file to implement this interface,
// but if so ReadDir should return an error for non-directories.)
type ReadDirFile interface {
File
// ReadDir reads the contents of the directory and returns
// a slice of up to n DirEntry values in directory order.
// Subsequent calls on the same file will yield further DirEntry values.
//
// If n > 0, ReadDir returns at most n DirEntry structures.
// In this case, if ReadDir returns an empty slice, it will return
// a non-nil error explaining why.
// At the end of a directory, the error is io.EOF.
//
// If n <= 0, ReadDir returns all the DirEntry values from the directory
// in a single slice. In this case, if ReadDir succeeds (reads all the way
// to the end of the directory), it returns the slice and a nil error.
// If it encounters an error before the end of the directory,
// ReadDir returns the DirEntry list read until that point and a non-nil error.
ReadDir(n int) ([]DirEntry, error)
}
// Generic file system errors.
// Errors returned by file systems can be tested against these errors
// using errors.Is.
var (
ErrInvalid = os.ErrInvalid // "invalid argument"
ErrPermission = os.ErrPermission // "permission denied"
ErrExist = os.ErrExist // "file already exists"
ErrNotExist = os.ErrNotExist // "file does not exist"
ErrClosed = os.ErrClosed // "file already closed"
)
func errInvalid() error { return os.ErrInvalid }
func errPermission() error { return os.ErrPermission }
func errExist() error { return os.ErrExist }
func errNotExist() error { return os.ErrNotExist }
func errClosed() error { return os.ErrClosed }
// A FileInfo describes a file and is returned by Stat.
type FileInfo = os.FileInfo
// A FileMode represents a file's mode and permission bits.
// The bits have the same definition on all systems, so that
// information about files can be moved from one system
// to another portably. Not all bits apply to all systems.
// The only required bit is ModeDir for directories.
type FileMode = os.FileMode
const (
ModeDir = os.ModeDir
ModeAppend = os.ModeAppend
ModeExclusive = os.ModeExclusive
ModeTemporary = os.ModeTemporary
ModeSymlink = os.ModeSymlink
ModeDevice = os.ModeDevice
ModeNamedPipe = os.ModeNamedPipe
ModeSocket = os.ModeSocket
ModeSetuid = os.ModeSetuid
ModeSetgid = os.ModeSetgid
ModeCharDevice = os.ModeCharDevice
ModeSticky = os.ModeSticky
ModeIrregular = os.ModeIrregular
ModeType = os.ModeType
ModePerm = os.ModePerm
)
// PathError records an error and the operation and file path that caused it.
type PathError = os.PathError