eden/fs/docs/Paths.md
There are three Path object types, each with a stored and non-stored (Piece)
variation. PathComponent and RelativePath were introduced to have the type
system prevent accidental bugs with using the wrong types in the wrong places.
Their purpose was originally to deal with names in our inode namespace.
AbsolutePath was introduced later with the intent to track names in the system
VFS namespace rather than in our mount point namespace.
Values of each of the following types are immutable. They are internally stored
as either a std::string or a folly::StringPiece, depending on if the Path
is stored or non-stored (Piece).
PathComponent/PathComponentPieceRelativePath/RelativePathPiecePathComponent(Piece)s strung togetherAbsolutePath(Piece)AbsolutePath/AbsolutePathPiecePathComponents and RelativePathsAbsolutePathsfolly::StringPiecestd::string values and Stored values.RelativePath to a RelativePathPiece, but cannot
compare a RelativePath to an AbsolutePath.ComposedPathIterator - Used for iteration of a RelativePath/AbsolutePath
using various iteration methods (paths(), allPaths(), suffixes(),
findParents()). An iterator over prefixes of a composed path. Iterating
yields a series of composed path elements. For example, iterating the path
"foo/bar/baz" will yield this series of Piece elements:
AbsolutePath ("\?" on Windows)dirname() and basename() methods to focus on the
portions of interest.PathComponentIterator- Used for iteration of a ComposedPath using the
iteration method components(). An iterator over components of a composed
path. Iterating yields a series of independent path elements. For example,
iterating the relative path "foo/bar/baz" will yield this series of
PathComponentPiece elements:
All the stored paths are merely a wrapper around an std::string, and the piece
version are also just a wrapper on top of a folly::StringPiece (which has
similar semantic as std::string_view), that is, a piece merely holds a view of
to the underlying std::string buffer. When a stored path is being moved, the
held std::string is also moved, which in most cases prevents copying and
re-allocating a string, this makes the move operation fairly cheap and since the
pieces were a view on that first string memory allocation, these are still
viewing valid and allocated memory.
However, std::string have an optimization where small strings aren't heap
allocated, but are stored in the std::string object itself, this is called SSO
for small string optimization. In this case, a folly::StringPiece is no longer
a view on the heap allocated memory, but on that SSO memory. What this means is
that moving a SSO std::string will make the folly::StringPiece invalid as it
would no longer point to valid memory!
What this means is that taking a path piece of a stored path and then moving
that stored path to extend its lifetime (say by moving it to an ensure blob),
will lead to a use after free when using the path piece in the case where the
stored path is small enough that the SSO kicks-in.
stringPiece() - Returns the path as a folly::StringPiececopy() - Returns a stored (deep) copy of this pathpiece() - Returns a non-stored (shallow) copy of this pathvalue() - Returns a reference to the underlying stored valuebasename() - Given a path like "a/b/c", returns "c"dirname() - Given a path like "a/b/c", returns "a/b"getcwd() - Gets the current working directory as an AbsolutePathcanonicalPath() - Removes duplicate "/" characters, resolves "/./" and
"/../" components. "//foo" is converted to "/foo". Does not resolve symlinks.
If the path is relative, the current working directory is prepended to it.
This succeeds even if the input path does not existjoinAndNormalize() - canonicalize a path string relative to a relative path
baserelpath() - Converts an arbitrary unsanitized input string to a normalized
AbsolutePath. This resolves symlinks, as well as "." and "." components in
the input path. If the input path is a relative path, it is converted to an
absolute path. This throws if the input path does not exist or if a parent
directory is inaccessibleexpandUser() - Returns a new path with ~ replaced by the path to the
current user's home directory. This function does not support expanding the
home dir of arbitrary users, and will throw an exception if the string starts
with ~ but not ~/. The resulting path will be passed through
canonicalPath() and returnednormalizeBestEffort() - Attempts to normalize a path by first attempting
relpath() and falling back to canonicalPath() on failure.splitFirst() - Splits a path into the first component and the remainder of
the path. If the path has only one component, the remainder will be empty. If
the path is empty, an exception is thrownensureDirectoryExists() - Ensures that the specified path exists as a
directory. This creates the specified directory if necessary, creating any
parent directories as required as well. Returns true if the directory was
created, and false if it already existed. Throws an exception on error,
including if the path or one of its parent directories is a file rather than a
directoryremoveRecursively() - Recursively removes a directory tree. Returns false if
the directory did not exist in the first place, and true if the directory was
successfully removed. Throws an exception on error.getconf NAME_MAX $PATH to check the path component limits for a
given filesystemgetconf PATH_MAX $PATH to check the total path length limits for a
given filesystem