capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

filesystem.h (53349B)


      1 // Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #pragma once
     23 
     24 #include "memory.h"
     25 #include "io.h"
     26 #include <inttypes.h>
     27 #include "time.h"
     28 #include "function.h"
     29 #include "hash.h"
     30 
     31 namespace kj {
     32 
     33 template <typename T>
     34 class Vector;
     35 
     36 class PathPtr;
     37 
     38 class Path {
     39   // A Path identifies a file in a directory tree.
     40   //
     41   // In KJ, we avoid representing paths as plain strings because this can lead to path injection
     42   // bugs as well as numerous kinds of bugs relating to path parsing edge cases. The Path class's
     43   // interface is designed to "make it hard to screw up".
     44   //
     45   // A "Path" is in fact a list of strings, each string being one component of the path (as would
     46   // normally be separated by '/'s). Path components are not allowed to contain '/' nor '\0', nor
     47   // are they allowed to be the special names "", ".", nor "..".
     48   //
     49   // If you explicitly want to parse a path that contains '/'s, ".", and "..", you must use
     50   // parse() and/or eval(). However, users of this interface are encouraged to avoid parsing
     51   // paths at all, and instead express paths as string arrays.
     52   //
     53   // Note that when using the Path class, ".." is always canonicalized in path space without
     54   // consulting the actual filesystem. This means that "foo/some-symlink/../bar" is exactly
     55   // equivalent to "foo/bar". This differs from the kernel's behavior when resolving paths passed
     56   // to system calls: the kernel would have resolved "some-symlink" to its target physical path,
     57   // and then would have interpreted ".." relative to that. In practice, the kernel's behavior is
     58   // rarely what the user or programmer intended, hence canonicalizing in path space produces a
     59   // better result.
     60   //
     61   // Path objects are "immutable": functions that "modify" the path return a new path. However,
     62   // if the path being operated on is an rvalue, copying can be avoided. Hence it makes sense to
     63   // write code like:
     64   //
     65   //     Path p = ...;
     66   //     p = kj::mv(p).append("bar");  // in-place update, avoids string copying
     67 
     68 public:
     69   Path(decltype(nullptr));  // empty path
     70 
     71   explicit Path(StringPtr name);
     72   explicit Path(String&& name);
     73   // Create a Path containing only one component. `name` is a single filename; it cannot contain
     74   // '/' nor '\0' nor can it be exactly "" nor "." nor "..".
     75   //
     76   // If you want to allow '/'s and such, you must call Path::parse(). We force you to do this to
     77   // prevent path injection bugs where you didn't consider what would happen if the path contained
     78   // a '/'.
     79 
     80   explicit Path(std::initializer_list<StringPtr> parts);
     81   explicit Path(ArrayPtr<const StringPtr> parts);
     82   explicit Path(Array<String> parts);
     83   // Construct a path from an array. Note that this means you can do:
     84   //
     85   //     Path{"foo", "bar", "baz"}   // equivalent to Path::parse("foo/bar/baz")
     86 
     87   KJ_DISALLOW_COPY(Path);
     88   Path(Path&&) = default;
     89   Path& operator=(Path&&) = default;
     90 
     91   Path clone() const;
     92 
     93   static Path parse(StringPtr path);
     94   // Parses a path in traditional format. Components are separated by '/'. Any use of "." or
     95   // ".." will be canonicalized (if they can't be canonicalized, e.g. because the path starts with
     96   // "..", an exception is thrown). Multiple consecutive '/'s will be collapsed. A leading '/'
     97   // is NOT accepted -- if that is a problem, you probably want `eval()`. Trailing '/'s are
     98   // ignored.
     99 
    100   Path append(Path&& suffix) const&;
    101   Path append(Path&& suffix) &&;
    102   Path append(PathPtr suffix) const&;
    103   Path append(PathPtr suffix) &&;
    104   Path append(StringPtr suffix) const&;
    105   Path append(StringPtr suffix) &&;
    106   Path append(String&& suffix) const&;
    107   Path append(String&& suffix) &&;
    108   // Create a new path by appending the given path to this path.
    109   //
    110   // `suffix` cannot contain '/' characters. Instead, you can append an array:
    111   //
    112   //     path.append({"foo", "bar"})
    113   //
    114   // Or, use Path::parse():
    115   //
    116   //     path.append(Path::parse("foo//baz/../bar"))
    117 
    118   Path eval(StringPtr pathText) const&;
    119   Path eval(StringPtr pathText) &&;
    120   // Evaluates a traditional path relative to this one. `pathText` is parsed like `parse()` would,
    121   // except that:
    122   // - It can contain leading ".." components that traverse up the tree.
    123   // - It can have a leading '/' which completely replaces the current path.
    124   //
    125   // THE NAME OF THIS METHOD WAS CHOSEN TO INSPIRE FEAR.
    126   //
    127   // Instead of using `path.eval(str)`, always consider whether you really want
    128   // `path.append(Path::parse(str))`. The former is much riskier than the latter in terms of path
    129   // injection vulnerabilities.
    130 
    131   PathPtr basename() const&;
    132   Path basename() &&;
    133   // Get the last component of the path. (Use `basename()[0]` to get just the string.)
    134 
    135   PathPtr parent() const&;
    136   Path parent() &&;
    137   // Get the parent path.
    138 
    139   String toString(bool absolute = false) const;
    140   // Converts the path to a traditional path string, appropriate to pass to a unix system call.
    141   // Never throws.
    142 
    143   const String& operator[](size_t i) const&;
    144   String operator[](size_t i) &&;
    145   size_t size() const;
    146   const String* begin() const;
    147   const String* end() const;
    148   PathPtr slice(size_t start, size_t end) const&;
    149   Path slice(size_t start, size_t end) &&;
    150   // A Path can be accessed as an array of strings.
    151 
    152   bool operator==(PathPtr other) const;
    153   bool operator!=(PathPtr other) const;
    154   bool operator< (PathPtr other) const;
    155   bool operator> (PathPtr other) const;
    156   bool operator<=(PathPtr other) const;
    157   bool operator>=(PathPtr other) const;
    158   // Compare path components lexically.
    159 
    160   bool operator==(const Path& other) const;
    161   bool operator!=(const Path& other) const;
    162   bool operator< (const Path& other) const;
    163   bool operator> (const Path& other) const;
    164   bool operator<=(const Path& other) const;
    165   bool operator>=(const Path& other) const;
    166 
    167   uint hashCode() const;
    168   // Can use in HashMap.
    169 
    170   bool startsWith(PathPtr prefix) const;
    171   bool endsWith(PathPtr suffix) const;
    172   // Compare prefix / suffix.
    173 
    174   Path evalWin32(StringPtr pathText) const&;
    175   Path evalWin32(StringPtr pathText) &&;
    176   // Evaluates a Win32-style path, as might be written by a user. Differences from `eval()`
    177   // include:
    178   //
    179   // - Backslashes can be used as path separators.
    180   // - Absolute paths begin with a drive letter followed by a colon. The drive letter, including
    181   //   the colon, will become the first component of the path, e.g. "c:\foo" becomes {"c:", "foo"}.
    182   // - A network path like "\\host\share\path" is parsed as {"host", "share", "path"}.
    183 
    184   Path evalNative(StringPtr pathText) const&;
    185   Path evalNative(StringPtr pathText) &&;
    186   // Alias for either eval() or evalWin32() depending on the target platform. Use this when you are
    187   // parsing a path provided by a user and you want the user to be able to use the "natural" format
    188   // for their platform.
    189 
    190   String toWin32String(bool absolute = false) const;
    191   // Converts the path to a Win32 path string, as you might display to a user.
    192   //
    193   // This is meant for display. For making Win32 system calls, consider `toWin32Api()` instead.
    194   //
    195   // If `absolute` is true, the path is expected to be an absolute path, meaning the first
    196   // component is a drive letter, namespace, or network host name. These are converted to their
    197   // regular Win32 format -- i.e. this method does the reverse of `evalWin32()`.
    198   //
    199   // This throws if the path would have unexpected special meaning or is otherwise invalid on
    200   // Windows, such as if it contains backslashes (within a path component), colons, or special
    201   // names like "con".
    202 
    203   String toNativeString(bool absolute = false) const;
    204   // Alias for either toString() or toWin32String() depending on the target platform. Use this when
    205   // you are formatting a path to display to a user and you want to present it in the "natural"
    206   // format for the user's platform.
    207 
    208   Array<wchar_t> forWin32Api(bool absolute) const;
    209   // Like toWin32String, but additionally:
    210   // - Converts the path to UTF-16, with a NUL terminator included.
    211   // - For absolute paths, adds the "\\?\" prefix which opts into permitting paths longer than
    212   //   MAX_PATH, and turns off relative path processing (which KJ paths already handle in userspace
    213   //   anyway).
    214   //
    215   // This method is good to use when making a Win32 API call, e.g.:
    216   //
    217   //     DeleteFileW(path.forWin32Api(true).begin());
    218 
    219   static Path parseWin32Api(ArrayPtr<const wchar_t> text);
    220   // Parses an absolute path as returned by a Win32 API call like GetFinalPathNameByHandle() or
    221   // GetCurrentDirectory(). A "\\?\" prefix is optional but understood if present.
    222   //
    223   // Since such Win32 API calls generally return a length, this function inputs an array slice.
    224   // The slice should not include any NUL terminator.
    225 
    226 private:
    227   Array<String> parts;
    228 
    229   // TODO(perf): Consider unrolling one element from `parts`, so that a one-element path doesn't
    230   //   require allocation of an array.
    231 
    232   enum { ALREADY_CHECKED };
    233   Path(Array<String> parts, decltype(ALREADY_CHECKED));
    234 
    235   friend class PathPtr;
    236 
    237   static String stripNul(String input);
    238   static void validatePart(StringPtr part);
    239   static void evalPart(Vector<String>& parts, ArrayPtr<const char> part);
    240   static Path evalImpl(Vector<String>&& parts, StringPtr path);
    241   static Path evalWin32Impl(Vector<String>&& parts, StringPtr path, bool fromApi = false);
    242   static size_t countParts(StringPtr path);
    243   static size_t countPartsWin32(StringPtr path);
    244   static bool isWin32Drive(ArrayPtr<const char> part);
    245   static bool isNetbiosName(ArrayPtr<const char> part);
    246   static bool isWin32Special(StringPtr part);
    247 };
    248 
    249 class PathPtr {
    250   // Points to a Path or a slice of a Path, but doesn't own it.
    251   //
    252   // PathPtr is to Path as ArrayPtr is to Array and StringPtr is to String.
    253 
    254 public:
    255   PathPtr(decltype(nullptr));
    256   PathPtr(const Path& path);
    257 
    258   Path clone();
    259   Path append(Path&& suffix) const;
    260   Path append(PathPtr suffix) const;
    261   Path append(StringPtr suffix) const;
    262   Path append(String&& suffix) const;
    263   Path eval(StringPtr pathText) const;
    264   PathPtr basename() const;
    265   PathPtr parent() const;
    266   String toString(bool absolute = false) const;
    267   const String& operator[](size_t i) const;
    268   size_t size() const;
    269   const String* begin() const;
    270   const String* end() const;
    271   PathPtr slice(size_t start, size_t end) const;
    272   bool operator==(PathPtr other) const;
    273   bool operator!=(PathPtr other) const;
    274   bool operator< (PathPtr other) const;
    275   bool operator> (PathPtr other) const;
    276   bool operator<=(PathPtr other) const;
    277   bool operator>=(PathPtr other) const;
    278   uint hashCode() const;
    279   bool startsWith(PathPtr prefix) const;
    280   bool endsWith(PathPtr suffix) const;
    281   Path evalWin32(StringPtr pathText) const;
    282   Path evalNative(StringPtr pathText) const;
    283   String toWin32String(bool absolute = false) const;
    284   String toNativeString(bool absolute = false) const;
    285   Array<wchar_t> forWin32Api(bool absolute) const;
    286   // Equivalent to the corresponding methods of `Path`.
    287 
    288 private:
    289   ArrayPtr<const String> parts;
    290 
    291   explicit PathPtr(ArrayPtr<const String> parts);
    292 
    293   String toWin32StringImpl(bool absolute, bool forApi) const;
    294 
    295   friend class Path;
    296 };
    297 
    298 // =======================================================================================
    299 // The filesystem API
    300 //
    301 // This API is strictly synchronous because, unfortunately, there's no such thing as asynchronous
    302 // filesystem access in practice. The filesystem drivers on Linux are written to assume they can
    303 // block. The AIO API is only actually asynchronous for reading/writing the raw file blocks, but if
    304 // the filesystem needs to be involved (to allocate blocks, update metadata, etc.) that will block.
    305 // It's best to imagine that the filesystem is just another tier of memory that happens to be
    306 // slower than RAM (which is slower than L3 cache, which is slower than L2, which is slower than
    307 // L1). You can't do asynchronous RAM access so why asynchronous filesystem? The only way to
    308 // parallelize these is using threads.
    309 //
    310 // All KJ filesystem objects are thread-safe, and so all methods are marked "const" (even write
    311 // methods). Of course, if you concurrently write the same bytes of a file from multiple threads,
    312 // it's unspecified which write will "win".
    313 
    314 class FsNode {
    315   // Base class for filesystem node types.
    316 
    317 public:
    318   Own<const FsNode> clone() const;
    319   // Creates a new object of exactly the same type as this one, pointing at exactly the same
    320   // external object.
    321   //
    322   // Under the hood, this will call dup(), so the FD number will not be the same.
    323 
    324   virtual Maybe<int> getFd() const { return nullptr; }
    325   // Get the underlying Unix file descriptor, if any. Returns nullptr if this object actually isn't
    326   // wrapping a file descriptor.
    327 
    328   virtual Maybe<void*> getWin32Handle() const { return nullptr; }
    329   // Get the underlying Win32 HANDLE, if any. Returns nullptr if this object actually isn't
    330   // wrapping a handle.
    331 
    332   enum class Type {
    333     FILE,
    334     DIRECTORY,
    335     SYMLINK,
    336     BLOCK_DEVICE,
    337     CHARACTER_DEVICE,
    338     NAMED_PIPE,
    339     SOCKET,
    340     OTHER,
    341   };
    342 
    343   struct Metadata {
    344     Type type = Type::FILE;
    345 
    346     uint64_t size = 0;
    347     // Logical size of the file.
    348 
    349     uint64_t spaceUsed = 0;
    350     // Physical size of the file on disk. May be smaller for sparse files, or larger for
    351     // pre-allocated files.
    352 
    353     Date lastModified = UNIX_EPOCH;
    354     // Last modification time of the file.
    355 
    356     uint linkCount = 1;
    357     // Number of hard links pointing to this node.
    358 
    359     uint64_t hashCode = 0;
    360     // Hint which can be used to determine if two FsNode instances point to the same underlying
    361     // file object. If two FsNodes report different hashCodes, then they are not the same object.
    362     // If they report the same hashCode, then they may or may not be the same object.
    363     //
    364     // The Unix filesystem implementation builds the hashCode based on st_dev and st_ino of
    365     // `struct stat`. However, note that some filesystems -- especially FUSE-based -- may not fill
    366     // in st_ino.
    367     //
    368     // The Windows filesystem implementation builds the hashCode based on dwVolumeSerialNumber and
    369     // dwFileIndex{Low,High} of the BY_HANDLE_FILE_INFORMATION structure. However, these are again
    370     // not guaranteed to be unique on all filesystems. In particular the documentation says that
    371     // ReFS uses 128-bit identifiers which can't be represented here, and again virtual filesystems
    372     // may often not report real identifiers.
    373     //
    374     // Of course, the process of hashing values into a single hash code can also cause collisions
    375     // even if the filesystem reports reliable information.
    376     //
    377     // Additionally note that this value is not reliable when returned by `lstat()`. You should
    378     // actually open the object, then call `stat()` on the opened object.
    379 
    380     // Not currently included:
    381     // - Access control info: Differs wildly across platforms, and KJ prefers capabilities anyway.
    382     // - Other timestamps: Differs across platforms.
    383     // - Device number: If you care, you're probably doing platform-specific stuff anyway.
    384 
    385     Metadata() = default;
    386     Metadata(Type type, uint64_t size, uint64_t spaceUsed, Date lastModified, uint linkCount,
    387              uint64_t hashCode)
    388         : type(type), size(size), spaceUsed(spaceUsed), lastModified(lastModified),
    389           linkCount(linkCount), hashCode(hashCode) {}
    390     // TODO(cleanup): This constructor is redundant in C++14, but needed in C++11.
    391   };
    392 
    393   virtual Metadata stat() const = 0;
    394 
    395   virtual void sync() const = 0;
    396   virtual void datasync() const = 0;
    397   // Maps to fsync() and fdatasync() system calls.
    398   //
    399   // Also, when creating or overwriting a file, the first call to sync() atomically links the file
    400   // into the filesystem (*after* syncing the data), so than incomplete data is never visible to
    401   // other processes. (In practice this works by writing into a temporary file and then rename()ing
    402   // it.)
    403 
    404 protected:
    405   virtual Own<const FsNode> cloneFsNode() const = 0;
    406   // Implements clone(). Required to return an object with exactly the same type as this one.
    407   // Hence, every subclass must implement this.
    408 };
    409 
    410 class ReadableFile: public FsNode {
    411 public:
    412   Own<const ReadableFile> clone() const;
    413 
    414   String readAllText() const;
    415   // Read all text in the file and return as a big string.
    416 
    417   Array<byte> readAllBytes() const;
    418   // Read all bytes in the file and return as a big byte array.
    419   //
    420   // This differs from mmap() in that the read is performed all at once. Future changes to the file
    421   // do not affect the returned copy. Consider using mmap() instead, particularly for large files.
    422 
    423   virtual size_t read(uint64_t offset, ArrayPtr<byte> buffer) const = 0;
    424   // Fills `buffer` with data starting at `offset`. Returns the number of bytes actually read --
    425   // the only time this is less than `buffer.size()` is when EOF occurs mid-buffer.
    426 
    427   virtual Array<const byte> mmap(uint64_t offset, uint64_t size) const = 0;
    428   // Maps the file to memory read-only. The returned array always has exactly the requested size.
    429   // Depending on the capabilities of the OS and filesystem, the mapping may or may not reflect
    430   // changes that happen to the file after mmap() returns.
    431   //
    432   // Multiple calls to mmap() on the same file may or may not return the same mapping (it is
    433   // immutable, so there's no possibility of interference).
    434   //
    435   // If the file cannot be mmap()ed, an implementation may choose to allocate a buffer on the heap,
    436   // read into it, and return that. This should only happen if a real mmap() is impossible.
    437   //
    438   // The returned array is always exactly the size requested. However, accessing bytes beyond the
    439   // current end of the file may raise SIGBUS, or may simply return zero.
    440 
    441   virtual Array<byte> mmapPrivate(uint64_t offset, uint64_t size) const = 0;
    442   // Like mmap() but returns a view that the caller can modify. Modifications will not be written
    443   // to the underlying file. Every call to this method returns a unique mapping. Changes made to
    444   // the underlying file by other clients may or may not be reflected in the mapping -- in fact,
    445   // some changes may be reflected while others aren't, even within the same mapping.
    446   //
    447   // In practice this is often implemented using copy-on-write pages. When you first write to a
    448   // page, a copy is made. Hence, changes to the underlying file within that page stop being
    449   // reflected in the mapping.
    450 };
    451 
    452 class AppendableFile: public FsNode, public OutputStream {
    453 public:
    454   Own<const AppendableFile> clone() const;
    455 
    456   // All methods are inherited.
    457 };
    458 
    459 class WritableFileMapping {
    460 public:
    461   virtual ArrayPtr<byte> get() const = 0;
    462   // Gets the mapped bytes. The returned array can be modified, and those changes may be written to
    463   // the underlying file, but there is no guarantee that they are written unless you subsequently
    464   // call changed().
    465 
    466   virtual void changed(ArrayPtr<byte> slice) const = 0;
    467   // Notifies the implementation that the given bytes have changed. For some implementations this
    468   // may be a no-op while for others it may be necessary in order for the changes to be written
    469   // back at all.
    470   //
    471   // `slice` must be a slice of `bytes()`.
    472 
    473   virtual void sync(ArrayPtr<byte> slice) const = 0;
    474   // Implies `changed()`, and then waits until the range has actually been written to disk before
    475   // returning.
    476   //
    477   // `slice` must be a slice of `bytes()`.
    478   //
    479   // On Windows, this calls FlushViewOfFile(). The documentation for this function implies that in
    480   // some circumstances, to fully sync to physical disk, you may need to call FlushFileBuffers() on
    481   // the file HANDLE as well. The documentation is not very clear on when and why this is needed.
    482   // If you believe your program needs this, you can accomplish it by calling `.sync()` on the File
    483   // object after calling `.sync()` on the WritableFileMapping.
    484 };
    485 
    486 class File: public ReadableFile {
    487 public:
    488   Own<const File> clone() const;
    489 
    490   void writeAll(ArrayPtr<const byte> bytes) const;
    491   void writeAll(StringPtr text) const;
    492   // Completely replace the file with the given bytes or text.
    493 
    494   virtual void write(uint64_t offset, ArrayPtr<const byte> data) const = 0;
    495   // Write the given data starting at the given offset in the file.
    496 
    497   virtual void zero(uint64_t offset, uint64_t size) const = 0;
    498   // Write zeros to the file, starting at `offset` and continuing for `size` bytes. If the platform
    499   // supports it, this will "punch a hole" in the file, such that blocks that are entirely zeros
    500   // do not take space on disk.
    501 
    502   virtual void truncate(uint64_t size) const = 0;
    503   // Set the file end pointer to `size`. If `size` is less than the current size, data past the end
    504   // is truncated. If `size` is larger than the current size, zeros are added to the end of the
    505   // file. If the platform supports it, blocks containing all-zeros will not be stored to disk.
    506 
    507   virtual Own<const WritableFileMapping> mmapWritable(uint64_t offset, uint64_t size) const = 0;
    508   // Like ReadableFile::mmap() but returns a mapping for which any changes will be immediately
    509   // visible in other mappings of the file on the same system and will eventually be written back
    510   // to the file.
    511 
    512   virtual size_t copy(uint64_t offset, const ReadableFile& from, uint64_t fromOffset,
    513                       uint64_t size) const;
    514   // Copies bytes from one file to another.
    515   //
    516   // Copies `size` bytes or to EOF, whichever comes first. Returns the number of bytes actually
    517   // copied. Hint: Pass kj::maxValue for `size` to always copy to EOF.
    518   //
    519   // The copy is not atomic. Concurrent writes may lead to garbage results.
    520   //
    521   // The default implementation performs a series of reads and writes. Subclasses can often provide
    522   // superior implementations that offload the work to the OS or even implement copy-on-write.
    523 };
    524 
    525 class ReadableDirectory: public FsNode {
    526   // Read-only subset of `Directory`.
    527 
    528 public:
    529   Own<const ReadableDirectory> clone() const;
    530 
    531   virtual Array<String> listNames() const = 0;
    532   // List the contents of this directory. Does NOT include "." nor "..".
    533 
    534   struct Entry {
    535     FsNode::Type type;
    536     String name;
    537 
    538     inline bool operator< (const Entry& other) const { return name <  other.name; }
    539     inline bool operator> (const Entry& other) const { return name >  other.name; }
    540     inline bool operator<=(const Entry& other) const { return name <= other.name; }
    541     inline bool operator>=(const Entry& other) const { return name >= other.name; }
    542     // Convenience comparison operators to sort entries by name.
    543   };
    544 
    545   virtual Array<Entry> listEntries() const = 0;
    546   // List the contents of the directory including the type of each file. On some platforms and
    547   // filesystems, this is just as fast as listNames(), but on others it may require stat()ing each
    548   // file.
    549 
    550   virtual bool exists(PathPtr path) const = 0;
    551   // Does the specified path exist?
    552   //
    553   // If the path is a symlink, the symlink is followed and the return value indicates if the target
    554   // exists. If you want to know if the symlink exists, use lstat(). (This implies that listNames()
    555   // may return names for which exists() reports false.)
    556 
    557   FsNode::Metadata lstat(PathPtr path) const;
    558   virtual Maybe<FsNode::Metadata> tryLstat(PathPtr path) const = 0;
    559   // Gets metadata about the path. If the path is a symlink, it is not followed -- the metadata
    560   // describes the symlink itself. `tryLstat()` returns null if the path doesn't exist.
    561 
    562   Own<const ReadableFile> openFile(PathPtr path) const;
    563   virtual Maybe<Own<const ReadableFile>> tryOpenFile(PathPtr path) const = 0;
    564   // Open a file for reading.
    565   //
    566   // `tryOpenFile()` returns null if the path doesn't exist. Other errors still throw exceptions.
    567 
    568   Own<const ReadableDirectory> openSubdir(PathPtr path) const;
    569   virtual Maybe<Own<const ReadableDirectory>> tryOpenSubdir(PathPtr path) const = 0;
    570   // Opens a subdirectory.
    571   //
    572   // `tryOpenSubdir()` returns null if the path doesn't exist. Other errors still throw exceptions.
    573 
    574   String readlink(PathPtr path) const;
    575   virtual Maybe<String> tryReadlink(PathPtr path) const = 0;
    576   // If `path` is a symlink, reads and returns the link contents.
    577   //
    578   // Note that tryReadlink() differs subtly from tryOpen*(). For example, tryOpenFile() throws if
    579   // the path is not a file (e.g. if it's a directory); it only returns null if the path doesn't
    580   // exist at all. tryReadlink() returns null if either the path doesn't exist, or if it does exist
    581   // but isn't a symlink. This is because if it were to throw instead, then almost every real-world
    582   // use case of tryReadlink() would be forced to perform an lstat() first for the sole purpose of
    583   // checking if it is a link, wasting a syscall and a path traversal.
    584   //
    585   // See Directory::symlink() for warnings about symlinks.
    586 };
    587 
    588 enum class WriteMode {
    589   // Mode for opening a file (or directory) for write.
    590   //
    591   // (To open a file or directory read-only, do not specify a mode.)
    592   //
    593   // WriteMode is a bitfield. Hence, it overloads the bitwise logic operators. To check if a
    594   // particular bit is set in a bitfield, use kj::has(), like:
    595   //
    596   //     if (kj::has(mode, WriteMode::MUST_EXIST)) {
    597   //       requireExists(path);
    598   //     }
    599   //
    600   // (`if (mode & WriteMode::MUST_EXIST)` doesn't work because WriteMode is an enum class, which
    601   // cannot be converted to bool. Alas, C++ does not allow you to define a conversion operator
    602   // on an enum type, so we can't define a conversion to bool.)
    603 
    604   // -----------------------------------------
    605   // Core flags
    606   //
    607   // At least one of CREATE or MODIFY must be specified. Optionally, the two flags can be combined
    608   // with a bitwise-OR.
    609 
    610   CREATE = 1,
    611   // Create a new empty file.
    612   //
    613   // When not combined with MODIFY, if the file already exists (including as a broken symlink),
    614   // tryOpenFile() returns null (and openFile() throws).
    615   //
    616   // When combined with MODIFY, if the path already exists, it will be opened as if CREATE hadn't
    617   // been specified at all. If the path refers to a broken symlink, the file at the target of the
    618   // link will be created (if its parent directory exists).
    619 
    620   MODIFY = 2,
    621   // Modify an existing file.
    622   //
    623   // When not combined with CREATE, if the file doesn't exist (including if it is a broken symlink),
    624   // tryOpenFile() returns null (and openFile() throws).
    625   //
    626   // When combined with CREATE, if the path doesn't exist, it will be created as if MODIFY hadn't
    627   // been specified at all. If the path refers to a broken symlink, the file at the target of the
    628   // link will be created (if its parent directory exists).
    629 
    630   // -----------------------------------------
    631   // Additional flags
    632   //
    633   // Any number of these may be OR'd with the core flags.
    634 
    635   CREATE_PARENT = 4,
    636   // Indicates that if the target node's parent directory doesn't exist, it should be created
    637   // automatically, along with its parent, and so on. This creation is NOT atomic.
    638   //
    639   // This bit only makes sense with CREATE or REPLACE.
    640 
    641   EXECUTABLE = 8,
    642   // Mark this file executable, if this is a meaningful designation on the host platform.
    643 
    644   PRIVATE = 16,
    645   // Indicates that this file is sensitive and should have permissions masked so that it is only
    646   // accessible by the current user.
    647   //
    648   // When this is not used, the platform's default access control settings are used. On Unix,
    649   // that usually means the umask is applied. On Windows, it means permissions are inherited from
    650   // the parent.
    651 };
    652 
    653 inline constexpr WriteMode operator|(WriteMode a, WriteMode b) {
    654   return static_cast<WriteMode>(static_cast<uint>(a) | static_cast<uint>(b));
    655 }
    656 inline constexpr WriteMode operator&(WriteMode a, WriteMode b) {
    657   return static_cast<WriteMode>(static_cast<uint>(a) & static_cast<uint>(b));
    658 }
    659 inline constexpr WriteMode operator+(WriteMode a, WriteMode b) {
    660   return static_cast<WriteMode>(static_cast<uint>(a) | static_cast<uint>(b));
    661 }
    662 inline constexpr WriteMode operator-(WriteMode a, WriteMode b) {
    663   return static_cast<WriteMode>(static_cast<uint>(a) & ~static_cast<uint>(b));
    664 }
    665 template <typename T, typename = EnableIf<__is_enum(T)>>
    666 bool has(T haystack, T needle) {
    667   return (static_cast<__underlying_type(T)>(haystack) &
    668           static_cast<__underlying_type(T)>(needle)) ==
    669           static_cast<__underlying_type(T)>(needle);
    670 }
    671 
    672 enum class TransferMode {
    673   // Specifies desired behavior for Directory::transfer().
    674 
    675   MOVE,
    676   // The node is moved to the new location, i.e. the old location is deleted. If possible, this
    677   // move is performed without copying, otherwise it is performed as a copy followed by a delete.
    678 
    679   LINK,
    680   // The new location becomes a synonym for the old location (a "hard link"). Filesystems have
    681   // varying support for this -- typically, it is not supported on directories.
    682 
    683   COPY
    684   // The new location becomes a copy of the old.
    685   //
    686   // Some filesystems may implement this in terms of copy-on-write.
    687   //
    688   // If the filesystem supports sparse files, COPY takes sparseness into account -- it will punch
    689   // holes in the target file where holes exist in the source file.
    690 };
    691 
    692 class Directory: public ReadableDirectory {
    693   // Refers to a specific directory on disk.
    694   //
    695   // A `Directory` object *only* provides access to children of the directory, not parents. That
    696   // is, you cannot open the file "..", nor jump to the root directory with "/".
    697   //
    698   // On OSs that support it, a `Directory` is backed by an open handle to the directory node. This
    699   // means:
    700   // - If the directory is renamed on-disk, the `Directory` object still points at it.
    701   // - Opening files in the directory only requires the OS to traverse the path from the directory
    702   //   to the file; it doesn't have to re-traverse all the way from the filesystem root.
    703   //
    704   // On Windows, a `Directory` object holds a lock on the underlying directory such that it cannot
    705   // be renamed nor deleted while the object exists. This is necessary because Windows does not
    706   // fully support traversing paths relative to file handles (it does for some operations but not
    707   // all), so the KJ filesystem implementation is forced to remember the full path and needs to
    708   // ensure that the path is not invalidated. If, in the future, Windows fully supports
    709   // handle-relative paths, KJ may stop locking directories in this way, so do not rely on this
    710   // behavior.
    711 
    712 public:
    713   Own<const Directory> clone() const;
    714 
    715   template <typename T>
    716   class Replacer {
    717     // Implements an atomic replacement of a file or directory, allowing changes to be made to
    718     // storage in a way that avoids losing data in a power outage and prevents other processes
    719     // from observing content in an inconsistent state.
    720     //
    721     // `T` may be `File` or `Directory`. For readability, the text below describes replacing a
    722     // file, but the logic is the same for directories.
    723     //
    724     // When you call `Directory::replaceFile()`, a temporary file is created, but the specified
    725     // path is not yet touched. You may call `get()` to obtain the temporary file object, through
    726     // which you may initialize its content, knowing that no other process can see it yet. The file
    727     // is atomically moved to its final path when you call `commit()`. If you destroy the Replacer
    728     // without calling commit(), the temporary file is deleted.
    729     //
    730     // Note that most operating systems sadly do not support creating a truly unnamed temporary file
    731     // and then linking it in later. Moreover, the file cannot necessarily be created in the system
    732     // temporary directory because it might not be on the same filesystem as the target. Therefore,
    733     // the replacement file may initially be created in the same directory as its eventual target.
    734     // The implementation of Directory will choose a name that is unique and "hidden" according to
    735     // the conventions of the filesystem. Additionally, the implementation of Directory will avoid
    736     // returning these temporary files from its list*() methods, in order to avoid observable
    737     // inconsistencies across platforms.
    738   public:
    739     explicit Replacer(WriteMode mode);
    740 
    741     virtual const T& get() = 0;
    742     // Gets the File or Directory representing the replacement data. Fill in this object before
    743     // calling commit().
    744 
    745     void commit();
    746     virtual bool tryCommit() = 0;
    747     // Commit the replacement.
    748     //
    749     // `tryCommit()` may return false based on the CREATE/MODIFY bits passed as the WriteMode when
    750     // the replacement was initiated. (If CREATE but not MODIFY was used, tryCommit() returns
    751     // false to indicate that the target file already existed. If MODIFY but not CREATE was used,
    752     // tryCommit() returns false to indicate that the file didn't exist.)
    753     //
    754     // `commit()` is atomic, meaning that there is no point in time at which other processes
    755     // observing the file will see it in an intermediate state -- they will either see the old
    756     // content or the complete new content. This includes in the case of a power outage or machine
    757     // failure: on recovery, the file will either be in the old state or the new state, but not in
    758     // some intermediate state.
    759     //
    760     // It's important to note that a power failure *after commit() returns* can still revert the
    761     // file to its previous state. That is, `commit()` does NOT guarantee that, upon return, the
    762     // new content is durable. In order to guarantee this, you must call `sync()` on the immediate
    763     // parent directory of the replaced file.
    764     //
    765     // Note that, sadly, not all filesystems / platforms are capable of supporting all of the
    766     // guarantees documented above. In such cases, commit() will make a best-effort attempt to do
    767     // what it claims. Some examples of possible problems include:
    768     // - Any guarantees about durability through a power outage probably require a journaling
    769     //   filesystem.
    770     // - Many platforms do not support atomically replacing a non-empty directory. Linux does as
    771     //   of kernel 3.15 (via the renameat2() syscall using RENAME_EXCHANGE). Where not supported,
    772     //   the old directory will be moved away just before the replacement is moved into place.
    773     // - Many platforms do not support atomically requiring the existence or non-existence of a
    774     //   file before replacing it. In these cases, commit() may have to perform the check as a
    775     //   separate step, with a small window for a race condition.
    776     // - Many platforms do not support "unlinking" a non-empty directory, meaning that a replaced
    777     //   directory will need to be deconstructed by deleting all contents. If another process has
    778     //   the directory open when it is replaced, that process will observe the contents
    779     //   disappearing after the replacement (actually, a swap) has taken place. This differs from
    780     //   files, where a process that has opened a file before it is replaced will continue see the
    781     //   file's old content unchanged after the replacement.
    782     // - On Windows, there are multiple ways to replace one file with another in a single system
    783     //   call, but none are documented as being atomic. KJ always uses `MoveFileEx()` with
    784     //   MOVEFILE_REPLACE_EXISTING. While the alternative `ReplaceFile()` is attractive for many
    785     //   reasons, it has the critical problem that it cannot be used when the source file has open
    786     //   file handles, which is generally the case when using Replacer.
    787 
    788   protected:
    789     const WriteMode mode;
    790   };
    791 
    792   using ReadableDirectory::openFile;
    793   using ReadableDirectory::openSubdir;
    794   using ReadableDirectory::tryOpenFile;
    795   using ReadableDirectory::tryOpenSubdir;
    796 
    797   Own<const File> openFile(PathPtr path, WriteMode mode) const;
    798   virtual Maybe<Own<const File>> tryOpenFile(PathPtr path, WriteMode mode) const = 0;
    799   // Open a file for writing.
    800   //
    801   // `tryOpenFile()` returns null if the path is required to exist but doesn't (MODIFY or REPLACE)
    802   // or if the path is required not to exist but does (CREATE or RACE). These are the only cases
    803   // where it returns null -- all other types of errors (like "access denied") throw exceptions.
    804 
    805   virtual Own<Replacer<File>> replaceFile(PathPtr path, WriteMode mode) const = 0;
    806   // Construct a file which, when ready, will be atomically moved to `path`, replacing whatever
    807   // is there already. See `Replacer<T>` for detalis.
    808   //
    809   // The `CREATE` and `MODIFY` bits of `mode` are not enforced until commit time, hence
    810   // `replaceFile()` has no "try" variant.
    811 
    812   virtual Own<const File> createTemporary() const = 0;
    813   // Create a temporary file backed by this directory's filesystem, but which isn't linked into
    814   // the directory tree. The file is deleted from disk when all references to it have been dropped.
    815 
    816   Own<AppendableFile> appendFile(PathPtr path, WriteMode mode) const;
    817   virtual Maybe<Own<AppendableFile>> tryAppendFile(PathPtr path, WriteMode mode) const = 0;
    818   // Opens the file for appending only. Useful for log files.
    819   //
    820   // If the underlying filesystem supports it, writes to the file will always be appended even if
    821   // other writers are writing to the same file at the same time -- however, some implementations
    822   // may instead assume that no other process is changing the file size between writes.
    823 
    824   Own<const Directory> openSubdir(PathPtr path, WriteMode mode) const;
    825   virtual Maybe<Own<const Directory>> tryOpenSubdir(PathPtr path, WriteMode mode) const = 0;
    826   // Opens a subdirectory for writing.
    827 
    828   virtual Own<Replacer<Directory>> replaceSubdir(PathPtr path, WriteMode mode) const = 0;
    829   // Construct a directory which, when ready, will be atomically moved to `path`, replacing
    830   // whatever is there already. See `Replacer<T>` for detalis.
    831   //
    832   // The `CREATE` and `MODIFY` bits of `mode` are not enforced until commit time, hence
    833   // `replaceSubdir()` has no "try" variant.
    834 
    835   void symlink(PathPtr linkpath, StringPtr content, WriteMode mode) const;
    836   virtual bool trySymlink(PathPtr linkpath, StringPtr content, WriteMode mode) const = 0;
    837   // Create a symlink. `content` is the raw text which will be written into the symlink node.
    838   // How this text is interpreted is entirely dependent on the filesystem. Note in particular that:
    839   // - Windows will require a path that uses backslashes as the separator.
    840   // - InMemoryDirectory does not support symlinks containing "..".
    841   //
    842   // Unfortunately under many implementations symlink() can be used to break out of the directory
    843   // by writing an absolute path or utilizing "..". Do not call this method with a value for
    844   // `target` that you don't trust.
    845   //
    846   // `mode` must be CREATE or REPLACE, not MODIFY. CREATE_PARENT is honored but EXECUTABLE and
    847   // PRIVATE have no effect. `trySymlink()` returns false in CREATE mode when the target already
    848   // exists.
    849 
    850   void transfer(PathPtr toPath, WriteMode toMode,
    851                 PathPtr fromPath, TransferMode mode) const;
    852   void transfer(PathPtr toPath, WriteMode toMode,
    853                 const Directory& fromDirectory, PathPtr fromPath,
    854                 TransferMode mode) const;
    855   virtual bool tryTransfer(PathPtr toPath, WriteMode toMode,
    856                            const Directory& fromDirectory, PathPtr fromPath,
    857                            TransferMode mode) const;
    858   virtual Maybe<bool> tryTransferTo(const Directory& toDirectory, PathPtr toPath, WriteMode toMode,
    859                                     PathPtr fromPath, TransferMode mode) const;
    860   // Move, link, or copy a file/directory tree from one location to another.
    861   //
    862   // Filesystems vary in what kinds of transfers are allowed, especially for TransferMode::LINK,
    863   // and whether TransferMode::MOVE is implemented as an actual move vs. copy+delete.
    864   //
    865   // tryTransfer() returns false if the source location didn't exist, or when `toMode` is CREATE
    866   // and the target already exists. The default implementation implements only TransferMode::COPY.
    867   //
    868   // tryTransferTo() exists to implement double-dispatch. It should be called as a fallback by
    869   // implementations of tryTransfer() in cases where the target directory would otherwise fail or
    870   // perform a pessimal transfer. The default implementation returns nullptr, which the caller
    871   // should interpret as: "I don't have any special optimizations; do the obvious thing."
    872   //
    873   // `toMode` controls how the target path is created. CREATE_PARENT is honored but EXECUTABLE and
    874   // PRIVATE have no effect.
    875 
    876   void remove(PathPtr path) const;
    877   virtual bool tryRemove(PathPtr path) const = 0;
    878   // Deletes/unlinks the given path. If the path names a directory, it is recursively deleted.
    879   //
    880   // tryRemove() returns false in the specific case that the path doesn't exist. remove() would
    881   // throw in this case. In all other error cases (like "access denied"), tryRemove() still throws;
    882   // it is only "does not exist" that produces a false return.
    883 
    884   // TODO(someday):
    885   // - Support sockets? There's no openat()-like interface for sockets, so it's hard to support
    886   //   them currently. Also you'd probably want to use them with the async library.
    887   // - Support named pipes? Unclear if there's a use case that isn't better-served by sockets.
    888   //   Then again, they can be openat()ed.
    889   // - Support watching for changes (inotify). Probably also requires the async library. Also
    890   //   lacks openat()-like semantics.
    891   // - xattrs -- linux-specific
    892   // - chown/chmod/etc. -- unix-specific, ACLs, eww
    893   // - set timestamps -- only needed by archiving programs/
    894   // - advisory locks
    895   // - sendfile?
    896   // - fadvise and such
    897 
    898 private:
    899   static void commitFailed(WriteMode mode);
    900 };
    901 
    902 class Filesystem {
    903 public:
    904   virtual const Directory& getRoot() const = 0;
    905   // Get the filesystem's root directory, as of the time the Filesystem object was created.
    906 
    907   virtual const Directory& getCurrent() const = 0;
    908   // Get the filesystem's current directory, as of the time the Filesystem object was created.
    909 
    910   virtual PathPtr getCurrentPath() const = 0;
    911   // Get the path from the root to the current directory, as of the time the Filesystem object was
    912   // created. Note that because a `Directory` does not provide access to its parent, if you want to
    913   // follow `..` from the current directory, you must use `getCurrentPath().eval("..")` or
    914   // `getCurrentPath().parent()`.
    915   //
    916   // This function attempts to determine the path as it appeared in the user's shell before this
    917   // program was started. That means, if the user had `cd`ed into a symlink, the path through that
    918   // symlink is returned, *not* the canonical path.
    919   //
    920   // Because of this, there is an important difference between how the operating system interprets
    921   // "../foo" and what you get when you write `getCurrentPath().eval("../foo")`: The former
    922   // will interpret ".." relative to the directory's canonical path, whereas the latter will
    923   // interpret it relative to the path shown in the user's shell. In practice, the latter is
    924   // almost always what the user wants! But the former behavior is what almost all commands do
    925   // in practice, and it leads to confusion. KJ commands should implement the behavior the user
    926   // expects.
    927 };
    928 
    929 // =======================================================================================
    930 
    931 Own<File> newInMemoryFile(const Clock& clock);
    932 Own<Directory> newInMemoryDirectory(const Clock& clock);
    933 // Construct file and directory objects which reside in-memory.
    934 //
    935 // InMemoryFile has the following special properties:
    936 // - The backing store is not sparse and never gets smaller even if you truncate the file.
    937 // - While a non-private memory mapping exists, the backing store cannot get larger. Any operation
    938 //   which would expand it will throw.
    939 //
    940 // InMemoryDirectory has the following special properties:
    941 // - Symlinks are processed using Path::parse(). This implies tha a symlink cannot point to a
    942 //   parent directory -- InMemoryDirectory does not know its parent.
    943 // - link() can link directory nodes in addition to files.
    944 // - link() and rename() accept any kind of Directory as `fromDirectory` -- it doesn't need to be
    945 //   another InMemoryDirectory. However, for rename(), the from path must be a directory.
    946 
    947 Own<AppendableFile> newFileAppender(Own<const File> inner);
    948 // Creates an AppendableFile by wrapping a File. Note that this implementation assumes it is the
    949 // only writer. A correct implementation should always append to the file even if other writes
    950 // are happening simultaneously, as is achieved with the O_APPEND flag to open(2), but that
    951 // behavior is not possible to emulate on top of `File`.
    952 
    953 #if _WIN32
    954 typedef AutoCloseHandle OsFileHandle;
    955 #else
    956 typedef AutoCloseFd OsFileHandle;
    957 #endif
    958 
    959 Own<ReadableFile> newDiskReadableFile(OsFileHandle fd);
    960 Own<AppendableFile> newDiskAppendableFile(OsFileHandle fd);
    961 Own<File> newDiskFile(OsFileHandle fd);
    962 Own<ReadableDirectory> newDiskReadableDirectory(OsFileHandle fd);
    963 Own<Directory> newDiskDirectory(OsFileHandle fd);
    964 // Wrap a file descriptor (or Windows HANDLE) as various filesystem types.
    965 
    966 Own<Filesystem> newDiskFilesystem();
    967 // Get at implementation of `Filesystem` representing the real filesystem.
    968 //
    969 // DO NOT CALL THIS except at the top level of your program, e.g. in main(). Anywhere else, you
    970 // should instead have your caller pass in a Filesystem object, or a specific Directory object,
    971 // or whatever it is that your code needs. This ensures that your code supports dependency
    972 // injection, which makes it more reusable and testable.
    973 //
    974 // newDiskFilesystem() reads the current working directory at the time it is called. The returned
    975 // object is not affected by subsequent calls to chdir().
    976 
    977 // =======================================================================================
    978 // inline implementation details
    979 
    980 inline Path::Path(decltype(nullptr)): parts(nullptr) {}
    981 inline Path::Path(std::initializer_list<StringPtr> parts)
    982     : Path(arrayPtr(parts.begin(), parts.end())) {}
    983 inline Path::Path(Array<String> parts, decltype(ALREADY_CHECKED))
    984     : parts(kj::mv(parts)) {}
    985 inline Path Path::clone() const { return PathPtr(*this).clone(); }
    986 inline Path Path::append(Path&& suffix) const& { return PathPtr(*this).append(kj::mv(suffix)); }
    987 inline Path Path::append(PathPtr suffix) const& { return PathPtr(*this).append(suffix); }
    988 inline Path Path::append(StringPtr suffix) const& { return append(Path(suffix)); }
    989 inline Path Path::append(StringPtr suffix) && { return kj::mv(*this).append(Path(suffix)); }
    990 inline Path Path::append(String&& suffix) const& { return append(Path(kj::mv(suffix))); }
    991 inline Path Path::append(String&& suffix) && { return kj::mv(*this).append(Path(kj::mv(suffix))); }
    992 inline Path Path::eval(StringPtr pathText) const& { return PathPtr(*this).eval(pathText); }
    993 inline PathPtr Path::basename() const& { return PathPtr(*this).basename(); }
    994 inline PathPtr Path::parent() const& { return PathPtr(*this).parent(); }
    995 inline const String& Path::operator[](size_t i) const& { return parts[i]; }
    996 inline String Path::operator[](size_t i) && { return kj::mv(parts[i]); }
    997 inline size_t Path::size() const { return parts.size(); }
    998 inline const String* Path::begin() const { return parts.begin(); }
    999 inline const String* Path::end() const { return parts.end(); }
   1000 inline PathPtr Path::slice(size_t start, size_t end) const& {
   1001   return PathPtr(*this).slice(start, end);
   1002 }
   1003 inline bool Path::operator==(PathPtr other) const { return PathPtr(*this) == other; }
   1004 inline bool Path::operator!=(PathPtr other) const { return PathPtr(*this) != other; }
   1005 inline bool Path::operator< (PathPtr other) const { return PathPtr(*this) <  other; }
   1006 inline bool Path::operator> (PathPtr other) const { return PathPtr(*this) >  other; }
   1007 inline bool Path::operator<=(PathPtr other) const { return PathPtr(*this) <= other; }
   1008 inline bool Path::operator>=(PathPtr other) const { return PathPtr(*this) >= other; }
   1009 inline bool Path::operator==(const Path& other) const { return PathPtr(*this) == PathPtr(other); }
   1010 inline bool Path::operator!=(const Path& other) const { return PathPtr(*this) != PathPtr(other); }
   1011 inline bool Path::operator< (const Path& other) const { return PathPtr(*this) <  PathPtr(other); }
   1012 inline bool Path::operator> (const Path& other) const { return PathPtr(*this) >  PathPtr(other); }
   1013 inline bool Path::operator<=(const Path& other) const { return PathPtr(*this) <= PathPtr(other); }
   1014 inline bool Path::operator>=(const Path& other) const { return PathPtr(*this) >= PathPtr(other); }
   1015 inline uint Path::hashCode() const { return kj::hashCode(parts); }
   1016 inline bool Path::startsWith(PathPtr prefix) const { return PathPtr(*this).startsWith(prefix); }
   1017 inline bool Path::endsWith  (PathPtr suffix) const { return PathPtr(*this).endsWith  (suffix); }
   1018 inline String Path::toString(bool absolute) const { return PathPtr(*this).toString(absolute); }
   1019 inline Path Path::evalWin32(StringPtr pathText) const& {
   1020   return PathPtr(*this).evalWin32(pathText);
   1021 }
   1022 inline String Path::toWin32String(bool absolute) const {
   1023   return PathPtr(*this).toWin32String(absolute);
   1024 }
   1025 inline Array<wchar_t> Path::forWin32Api(bool absolute) const {
   1026   return PathPtr(*this).forWin32Api(absolute);
   1027 }
   1028 
   1029 inline PathPtr::PathPtr(decltype(nullptr)): parts(nullptr) {}
   1030 inline PathPtr::PathPtr(const Path& path): parts(path.parts) {}
   1031 inline PathPtr::PathPtr(ArrayPtr<const String> parts): parts(parts) {}
   1032 inline Path PathPtr::append(StringPtr suffix) const { return append(Path(suffix)); }
   1033 inline Path PathPtr::append(String&& suffix) const { return append(Path(kj::mv(suffix))); }
   1034 inline const String& PathPtr::operator[](size_t i) const { return parts[i]; }
   1035 inline size_t PathPtr::size() const { return parts.size(); }
   1036 inline const String* PathPtr::begin() const { return parts.begin(); }
   1037 inline const String* PathPtr::end() const { return parts.end(); }
   1038 inline PathPtr PathPtr::slice(size_t start, size_t end) const {
   1039   return PathPtr(parts.slice(start, end));
   1040 }
   1041 inline bool PathPtr::operator!=(PathPtr other) const { return !(*this == other); }
   1042 inline bool PathPtr::operator> (PathPtr other) const { return other < *this; }
   1043 inline bool PathPtr::operator<=(PathPtr other) const { return !(other < *this); }
   1044 inline bool PathPtr::operator>=(PathPtr other) const { return !(*this < other); }
   1045 inline uint PathPtr::hashCode() const { return kj::hashCode(parts); }
   1046 inline String PathPtr::toWin32String(bool absolute) const {
   1047   return toWin32StringImpl(absolute, false);
   1048 }
   1049 
   1050 #if _WIN32
   1051 inline Path Path::evalNative(StringPtr pathText) const& {
   1052   return evalWin32(pathText);
   1053 }
   1054 inline Path Path::evalNative(StringPtr pathText) && {
   1055   return kj::mv(*this).evalWin32(pathText);
   1056 }
   1057 inline String Path::toNativeString(bool absolute) const {
   1058   return toWin32String(absolute);
   1059 }
   1060 inline Path PathPtr::evalNative(StringPtr pathText) const {
   1061   return evalWin32(pathText);
   1062 }
   1063 inline String PathPtr::toNativeString(bool absolute) const {
   1064   return toWin32String(absolute);
   1065 }
   1066 #else
   1067 inline Path Path::evalNative(StringPtr pathText) const& {
   1068   return eval(pathText);
   1069 }
   1070 inline Path Path::evalNative(StringPtr pathText) && {
   1071   return kj::mv(*this).eval(pathText);
   1072 }
   1073 inline String Path::toNativeString(bool absolute) const {
   1074   return toString(absolute);
   1075 }
   1076 inline Path PathPtr::evalNative(StringPtr pathText) const {
   1077   return eval(pathText);
   1078 }
   1079 inline String PathPtr::toNativeString(bool absolute) const {
   1080   return toString(absolute);
   1081 }
   1082 #endif  // _WIN32, else
   1083 
   1084 inline Own<const FsNode> FsNode::clone() const { return cloneFsNode(); }
   1085 inline Own<const ReadableFile> ReadableFile::clone() const {
   1086   return cloneFsNode().downcast<const ReadableFile>();
   1087 }
   1088 inline Own<const AppendableFile> AppendableFile::clone() const {
   1089   return cloneFsNode().downcast<const AppendableFile>();
   1090 }
   1091 inline Own<const File> File::clone() const { return cloneFsNode().downcast<const File>(); }
   1092 inline Own<const ReadableDirectory> ReadableDirectory::clone() const {
   1093   return cloneFsNode().downcast<const ReadableDirectory>();
   1094 }
   1095 inline Own<const Directory> Directory::clone() const {
   1096   return cloneFsNode().downcast<const Directory>();
   1097 }
   1098 
   1099 inline void Directory::transfer(
   1100     PathPtr toPath, WriteMode toMode, PathPtr fromPath, TransferMode mode) const {
   1101   return transfer(toPath, toMode, *this, fromPath, mode);
   1102 }
   1103 
   1104 template <typename T>
   1105 inline Directory::Replacer<T>::Replacer(WriteMode mode): mode(mode) {}
   1106 
   1107 template <typename T>
   1108 void Directory::Replacer<T>::commit() {
   1109   if (!tryCommit()) commitFailed(mode);
   1110 }
   1111 
   1112 } // namespace kj