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