Documentation ¶
Index ¶
- Variables
- func NewBreakoutError(OpArea AbsolutePath, OpPath RelPath, LinkPath RelPath, LinkTarget string) error
- func NormalizeIOError(ioe error) error
- func Walk(afs FS, preVisit WalkFunc, postVisit WalkFunc) error
- type AbsolutePath
- type ErrorCategory
- type FS
- type File
- type FilewalkNode
- type Metadata
- type Perms
- type RelPath
- type Type
- type WalkFunc
Constants ¶
This section is empty.
Variables ¶
var DefaultTime = time.Unix(api.DefaultTime, 0).UTC()
Use this for the accessTime attribute when one is needed but no more obvious value is at hand, or for modifiedTime when doing things like 'create a default dir' when no other value is at hand.
Functions ¶
func NewBreakoutError ¶
func NewBreakoutError(OpArea AbsolutePath, OpPath RelPath, LinkPath RelPath, LinkTarget string) error
func NormalizeIOError ¶
Categorize any errors into errcat-style errors with a category of `fs.ErrorCategory` type. Well-recognized errors will be normalized to a specific type, and all other errors will have a category of `ErrMisc`.
func Walk ¶
Walks a filesystem.
This is much like the standard library's `path/filepath.Walk`, except it's based on `treewalk`, which means it supports both pre- and post-order traversals; and, if uses fs.RelPath (of course) to normalize path names.
If walking directories, implicitly the first path will always be `./`; if the basePath is a file however, the first (and only) path with be `.`. This retains the same invarients from the perspective of the visit funcs (namely, that `filepath.Join(basePath, node.Path)` must be a correct path), but may also require additional understanding from the calling code to handle single files correctly.
In order to get a name for the file in special case that basePath is a single file, use `node.Info.Name()`.
Symlinks are not followed.
The traversal order of siblings is *not* guaranteed, and is *not* necessarily stable.
Caveat: calling `node.NextChild()` during your walk results in undefined behavior.
Types ¶
type AbsolutePath ¶
type AbsolutePath struct {
// contains filtered or unexported fields
}
Relative paths and absolute paths are not interchangeable. Using these path structures aids in keeping these ideas separate and hopefully prevent certain kinds of errors caused by accidentally using the incorrect path type. It is recommended to use absolute paths when possible.
func MustAbsolutePath ¶
func MustAbsolutePath(p string) AbsolutePath
Converts a string to an absolute path struct. Will panic if the given path is not absolute.
func ParseAbsolutePath ¶
func ParseAbsolutePath(p string) (AbsolutePath, error)
Converts a string to an absolute path struct, returning an error if the given path string is not absolute.
func (AbsolutePath) CoerceRelative ¶
func (p AbsolutePath) CoerceRelative() RelPath
func (AbsolutePath) Dir ¶
func (p AbsolutePath) Dir() AbsolutePath
Returns the absolute path of the directory containing this path
func (AbsolutePath) Join ¶
func (p AbsolutePath) Join(p2 RelPath) AbsolutePath
Creates a new absolute path by following the relative path from this path.
func (AbsolutePath) String ¶
func (p AbsolutePath) String() string
An absolute path string with a zero value of "/" for the root directory
type ErrorCategory ¶
type ErrorCategory string
const ( /* The catch-all for errors we haven't particularly mapped. */ ErrMisc ErrorCategory = "fs-misc" ErrUnexpectedEOF ErrorCategory = "fs-unexpected-eof" ErrNotExists ErrorCategory = "fs-not-exists" ErrAlreadyExists ErrorCategory = "fs-already-exists" ErrNotDir ErrorCategory = "fs-not-dir" // contextually, may be a form of either ErrNotExists or ErrAlready exists: shows up when e.g. lstat doesnotexist/deeper/path or mkdir aregularfile/deeper/path. ErrRecursion ErrorCategory = "fs-recursion" // returned when cycles detected in symlinks. ErrShortWrite ErrorCategory = "fs-shortwrite" ErrPermission ErrorCategory = "fs-permission" /* Error returned when operating in a confined filesystem slice and an operation performed would result in effects outside the area, e.g. calling `PlaceFile` with "./reasonable/path" but "./reasonable" happens to be a symlink to "../../.." -- the symlink is valid, but to traverse it would violate confinement. Not all functions which do symlink checks will verify if the symlink target is within the operational area; they may return ErrBreakout upon encountering any symlink, even if following it would still be within bounds. Check the function's documentation for more info on how it behaves. Note that any function returning ErrBreakout is, by nature, doing so in a best-effort sense: if there are concurrent modifcations to the operational area of the filesystem by any other processes, it is *impossible* to avoid a TOCTOU violation. */ ErrBreakout ErrorCategory = "fs-breakout" )
type FS ¶
type FS interface { // The basepath this filesystem was constructed with. // This may be useful for debugging messages, but should not otherwise // be used; there's no reason, since all methods are consistently // using it internally. // May be '/' (the zero AbsolutePath) if not applicable. BasePath() AbsolutePath OpenFile(path RelPath, flag int, perms Perms) (File, error) Mkdir(path RelPath, perms Perms) error Mklink(path RelPath, target string) error Mkfifo(path RelPath, perms Perms) error MkdevBlock(path RelPath, major int64, minor int64, perms Perms) error MkdevChar(path RelPath, major int64, minor int64, perms Perms) error Lchown(path RelPath, uid uint32, gid uint32) error Chmod(path RelPath, perms Perms) error SetTimesLNano(path RelPath, mtime time.Time, atime time.Time) error SetTimesNano(path RelPath, mtime time.Time, atime time.Time) error Stat(path RelPath) (*Metadata, error) LStat(path RelPath) (*Metadata, error) ReadDirNames(path RelPath) ([]string, error) Readlink(path RelPath) (target string, isSymlink bool, err error) /* Resolve a symlink (within the confines of the basepath!), returning the path to the final result. The resolution acts as if the FS basepath is the real root of the filesystem: rooted symlinks or excessive '..' segments still yield paths within the FS basepath. For example, `ResolveLink("../../..", "./lnk")` yields "./". This may opt to be bug-for-bug compatible with linux path resolution: specifically, for paths like "/untraversable/../target", where the first dir is 0000, we will return a permissions error... despite being able to clearly see that the following ".." will make the question irrelevant. */ ResolveLink(symlink string, startingAt RelPath) (RelPath, error) }
Interface for all primitive functions we expect to be able to perform on a filesystem.
All paths accepted are RelPath types; typically the FS instance is constructed with an AbsolutePath, and all further operations are joined with that base path.
type FilewalkNode ¶
func (*FilewalkNode) NextChild ¶
func (t *FilewalkNode) NextChild() treewalk.Node
type Metadata ¶
type Metadata struct { Name RelPath // filename Type Type // type enum Perms Perms // permission bits Uid uint32 // user id of owner Gid uint32 // group id of owner Size int64 // length in bytes Linkname string // if symlink: target name of link Devmajor int64 // major number of character or block device Devminor int64 // minor number of character or block device Mtime time.Time // modified time Xattrs map[string]string }
type Perms ¶
type Perms uint16
The usual posix permission bits (0777) plus the linux interpretation of the setuid, setgid, and sticky bits.
See http://man7.org/linux/man-pages/man2/open.2.html for more information; specifically, store the setuid, setgid, and sticky bits with the same bits as documented for S_ISUID, S_ISGID, and S_ISVTX. http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysstat.h.html documents that any choice for those three bits is valid as long as they do not conflict with the 0777 range, but, why?
More precisely:
#define S_ISUID 0004000 #define S_ISGID 0002000 #define S_ISVTX 0001000
So, '01777' is as it is in your linux system chmod: a sticky bit is set.
Compared to os.FileMode, this conveys the same amount of information as `mode & (ModePerm|ModeSetuid|ModeSetgid|ModeSticky)`, but again note that we follow the bit layout for those additional modes that is standard in the linux headers.
type RelPath ¶
type RelPath struct {
// contains filtered or unexported fields
}
Relative paths and absolute paths are not interchangeable. Using these path structures aids in keeping these ideas separate and hopefully prevent certain kinds of errors caused by accidentally using the incorrect path type. It is recommended to use absolute paths when possible.
func MustRelPath ¶
Converts a string to an relative path struct. Will panic if the given path is absolute.
func (RelPath) GoesUp ¶
Predicate for if this path goes "up" -- in other words, if it starts with "..".
func (RelPath) Split ¶
Returns a slice of relative paths for each segment in the path.
E.g. for "./a/b/c" it will return [".", "./a", "./a/b", "./a/b/c"].
func (RelPath) SplitParent ¶
Returns a slice of relative paths for each segment in the path, minus the path itself.
E.g. for "./a/b/c" it will return [".", "./a", "./a/b"]. Importantly, for "." it will return [] -- an empty list (note that this is different than the behavior of `path.Dir().Split()`, which would still yield ["."].)
For some path where you wish to create all parent paths, it may be useful to `range path.SplitParent()`.
type WalkFunc ¶
type WalkFunc func(filenode *FilewalkNode) error