LLVM 22.0.0git
VirtualFileSystem.h
Go to the documentation of this file.
1//===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// Defines the virtual file system interface vfs::FileSystem.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_VIRTUALFILESYSTEM_H
15#define LLVM_SUPPORT_VIRTUALFILESYSTEM_H
16
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/Chrono.h"
23#include "llvm/Support/Errc.h"
24#include "llvm/Support/Error.h"
28#include "llvm/Support/Path.h"
30#include <cassert>
31#include <cstdint>
32#include <ctime>
33#include <memory>
34#include <optional>
35#include <string>
36#include <system_error>
37#include <utility>
38#include <vector>
39
40namespace llvm {
41
42class MemoryBuffer;
43class MemoryBufferRef;
44class Twine;
45
46namespace vfs {
47
48/// The result of a \p status operation.
49class Status {
50 std::string Name;
53 uint32_t User;
54 uint32_t Group;
55 uint64_t Size;
58
59public:
60 /// Whether this entity has an external path different from the virtual path,
61 /// and the external path is exposed by leaking it through the abstraction.
62 /// For example, a RedirectingFileSystem will set this for paths where
63 /// UseExternalName is true.
64 ///
65 /// FIXME: Currently the external path is exposed by replacing the virtual
66 /// path in this Status object. Instead, we should leave the path in the
67 /// Status intact (matching the requested virtual path) - see
68 /// FileManager::getFileRef for how we plan to fix this.
70
71 Status() = default;
74 llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
77
78 /// Get a copy of a Status with a different size.
79 LLVM_ABI static Status copyWithNewSize(const Status &In, uint64_t NewSize);
80 /// Get a copy of a Status with a different name.
81 LLVM_ABI static Status copyWithNewName(const Status &In,
82 const Twine &NewName);
84 const Twine &NewName);
85
86 /// Returns the name that should be used for this file or directory.
87 StringRef getName() const { return Name; }
88
89 /// @name Status interface from llvm::sys::fs
90 /// @{
91 llvm::sys::fs::file_type getType() const { return Type; }
92 llvm::sys::fs::perms getPermissions() const { return Perms; }
94 llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
95 uint32_t getUser() const { return User; }
96 uint32_t getGroup() const { return Group; }
97 uint64_t getSize() const { return Size; }
98 /// @}
99 /// @name Status queries
100 /// These are static queries in llvm::sys::fs.
101 /// @{
102 LLVM_ABI bool equivalent(const Status &Other) const;
103 LLVM_ABI bool isDirectory() const;
104 LLVM_ABI bool isRegularFile() const;
105 LLVM_ABI bool isOther() const;
106 LLVM_ABI bool isSymlink() const;
107 LLVM_ABI bool isStatusKnown() const;
108 LLVM_ABI bool exists() const;
109 /// @}
110};
111
112/// Represents an open file.
114public:
115 /// Destroy the file after closing it (if open).
116 /// Sub-classes should generally call close() inside their destructors. We
117 /// cannot do that from the base class, since close is virtual.
118 virtual ~File();
119
120 /// Get the status of the file.
122
123 /// Get the name of the file
125 if (auto Status = status())
126 return Status->getName().str();
127 else
128 return Status.getError();
129 }
130
131 /// Get the contents of the file as a \p MemoryBuffer.
133 getBuffer(const Twine &Name, int64_t FileSize = -1,
134 bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
135
136 /// Closes the file.
137 virtual std::error_code close() = 0;
138
139 // Get the same file with a different path.
141 getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P);
142
143protected:
144 // Set the file's underlying path.
145 virtual void setPath(const Twine &Path) {}
146};
147
148/// A member of a directory, yielded by a directory_iterator.
149/// Only information available on most platforms is included.
151 std::string Path;
153
154public:
155 directory_entry() = default;
157 : Path(std::move(Path)), Type(Type) {}
158
159 llvm::StringRef path() const { return Path; }
160 llvm::sys::fs::file_type type() const { return Type; }
161};
162
163namespace detail {
164
165/// An interface for virtual file systems to provide an iterator over the
166/// (non-recursive) contents of a directory.
168 virtual ~DirIterImpl();
169
170 /// Sets \c CurrentEntry to the next entry in the directory on success,
171 /// to directory_entry() at end, or returns a system-defined \c error_code.
172 virtual std::error_code increment() = 0;
173
175};
176
177} // namespace detail
178
179/// An input iterator over the entries in a virtual path, similar to
180/// llvm::sys::fs::directory_iterator.
182 std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
183
184public:
185 directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
186 : Impl(std::move(I)) {
187 assert(Impl.get() != nullptr && "requires non-null implementation");
188 if (Impl->CurrentEntry.path().empty())
189 Impl.reset(); // Normalize the end iterator to Impl == nullptr.
190 }
191
192 /// Construct an 'end' iterator.
194
195 /// Equivalent to operator++, with an error code.
196 directory_iterator &increment(std::error_code &EC) {
197 assert(Impl && "attempting to increment past end");
198 EC = Impl->increment();
199 if (Impl->CurrentEntry.path().empty())
200 Impl.reset(); // Normalize the end iterator to Impl == nullptr.
201 return *this;
202 }
203
204 const directory_entry &operator*() const { return Impl->CurrentEntry; }
205 const directory_entry *operator->() const { return &Impl->CurrentEntry; }
206
207 bool operator==(const directory_iterator &RHS) const {
208 if (Impl && RHS.Impl)
209 return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path();
210 return !Impl && !RHS.Impl;
211 }
212 bool operator!=(const directory_iterator &RHS) const {
213 return !(*this == RHS);
214 }
215};
216
217class FileSystem;
218
219namespace detail {
220
221/// Keeps state for the recursive_directory_iterator.
223 std::vector<directory_iterator> Stack;
224 bool HasNoPushRequest = false;
225};
226
227} // end namespace detail
228
229/// An input iterator over the recursive contents of a virtual path,
230/// similar to llvm::sys::fs::recursive_directory_iterator.
232 FileSystem *FS;
233 std::shared_ptr<detail::RecDirIterState>
234 State; // Input iterator semantics on copy.
235
236public:
238 std::error_code &EC);
239
240 /// Construct an 'end' iterator.
242
243 /// Equivalent to operator++, with an error code.
244 LLVM_ABI recursive_directory_iterator &increment(std::error_code &EC);
245
246 const directory_entry &operator*() const { return *State->Stack.back(); }
247 const directory_entry *operator->() const { return &*State->Stack.back(); }
248
250 return State == Other.State; // identity
251 }
253 return !(*this == RHS);
254 }
255
256 /// Gets the current level. Starting path is at level 0.
257 int level() const {
258 assert(!State->Stack.empty() &&
259 "Cannot get level without any iteration state");
260 return State->Stack.size() - 1;
261 }
262
263 void no_push() { State->HasNoPushRequest = true; }
264};
265
266/// The virtual file system interface.
268 public RTTIExtends<FileSystem, RTTIRoot> {
269public:
270 static const char ID;
271 ~FileSystem() override;
272
273 /// Get the status of the entry at \p Path, if one exists.
274 virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
275
276 /// Get a \p File object for the text file at \p Path, if one exists.
278 openFileForRead(const Twine &Path) = 0;
279
280 /// Get a \p File object for the binary file at \p Path, if one exists.
281 /// Some non-ascii based file systems perform encoding conversions
282 /// when reading as a text file, and this function should be used if
283 /// a file's bytes should be read as-is. On most filesystems, this
284 /// is the same behaviour as openFileForRead.
287 return openFileForRead(Path);
288 }
289
290 /// This is a convenience method that opens a file, gets its content and then
291 /// closes the file.
292 /// The IsText parameter is used to distinguish whether the file should be
293 /// opened as a binary or text file.
295 getBufferForFile(const Twine &Name, int64_t FileSize = -1,
296 bool RequiresNullTerminator = true, bool IsVolatile = false,
297 bool IsText = true);
298
299 /// Get a directory_iterator for \p Dir.
300 /// \note The 'end' iterator is directory_iterator().
302 std::error_code &EC) = 0;
303
304 /// Set the working directory. This will affect all following operations on
305 /// this file system and may propagate down for nested file systems.
306 virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
307
308 /// Get the working directory of this file system.
310
311 /// Gets real path of \p Path e.g. collapse all . and .. patterns, resolve
312 /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`.
313 /// This returns errc::operation_not_permitted if not implemented by subclass.
314 virtual std::error_code getRealPath(const Twine &Path,
315 SmallVectorImpl<char> &Output);
316
317 /// Check whether \p Path exists. By default this uses \c status(), but
318 /// filesystems may provide a more efficient implementation if available.
319 virtual bool exists(const Twine &Path);
320
321 /// Is the file mounted on a local filesystem?
322 virtual std::error_code isLocal(const Twine &Path, bool &Result);
323
324 /// Make \a Path an absolute path.
325 ///
326 /// Makes \a Path absolute using the current directory if it is not already.
327 /// An empty \a Path will result in the current directory.
328 ///
329 /// /absolute/path => /absolute/path
330 /// relative/../path => <current-directory>/relative/../path
331 ///
332 /// \param Path A path that is modified to be an absolute path.
333 /// \returns success if \a path has been made absolute, otherwise a
334 /// platform-specific error_code.
335 virtual std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
336
337 /// \returns true if \p A and \p B represent the same file, or an error or
338 /// false if they do not.
340
343 unsigned IndentLevel = 0) const {
344 printImpl(OS, Type, IndentLevel);
345 }
346
348 virtual void visitChildFileSystems(VisitCallbackTy Callback) {}
349 void visit(VisitCallbackTy Callback) {
350 Callback(*this);
351 visitChildFileSystems(Callback);
352 }
353
354#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
355 LLVM_DUMP_METHOD void dump() const;
356#endif
357
358protected:
360 unsigned IndentLevel) const {
361 printIndent(OS, IndentLevel);
362 OS << "FileSystem\n";
363 }
364
365 void printIndent(raw_ostream &OS, unsigned IndentLevel) const {
366 for (unsigned i = 0; i < IndentLevel; ++i)
367 OS << " ";
368 }
369};
370
371/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
372/// the operating system.
373/// The working directory is linked to the process's working directory.
374/// (This is usually thread-hostile).
375/// This may only be called outside the IO sandbox.
377
378/// Create an \p vfs::FileSystem for the 'real' file system, as seen by
379/// the operating system.
380/// It has its own working directory, independent of (but initially equal to)
381/// that of the process.
382/// This may only be called outside the IO sandbox.
383LLVM_ABI std::unique_ptr<FileSystem> createPhysicalFileSystem();
384
385/// A file system that allows overlaying one \p AbstractFileSystem on top
386/// of another.
387///
388/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
389/// one merged file system. When there is a directory that exists in more than
390/// one file system, the \p OverlayFileSystem contains a directory containing
391/// the union of their contents. The attributes (permissions, etc.) of the
392/// top-most (most recently added) directory are used. When there is a file
393/// that exists in more than one file system, the file in the top-most file
394/// system overrides the other(s).
396 : public RTTIExtends<OverlayFileSystem, FileSystem> {
397 using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>;
398
399 /// The stack of file systems, implemented as a list in order of
400 /// their addition.
401 FileSystemList FSList;
402
403public:
404 static const char ID;
406
407 /// Pushes a file system on top of the stack.
409
410 llvm::ErrorOr<Status> status(const Twine &Path) override;
411 bool exists(const Twine &Path) override;
413 openFileForRead(const Twine &Path) override;
414 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
416 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
417 std::error_code isLocal(const Twine &Path, bool &Result) override;
418 std::error_code getRealPath(const Twine &Path,
419 SmallVectorImpl<char> &Output) override;
420
427
428 /// Get an iterator pointing to the most recently added file system.
429 iterator overlays_begin() { return FSList.rbegin(); }
430 const_iterator overlays_begin() const { return FSList.rbegin(); }
431
432 /// Get an iterator pointing one-past the least recently added file system.
433 iterator overlays_end() { return FSList.rend(); }
434 const_iterator overlays_end() const { return FSList.rend(); }
435
436 /// Get an iterator pointing to the least recently added file system.
437 reverse_iterator overlays_rbegin() { return FSList.begin(); }
438 const_reverse_iterator overlays_rbegin() const { return FSList.begin(); }
439
440 /// Get an iterator pointing one-past the most recently added file system.
441 reverse_iterator overlays_rend() { return FSList.end(); }
442 const_reverse_iterator overlays_rend() const { return FSList.end(); }
443
444 range overlays_range() { return llvm::reverse(FSList); }
445 const_range overlays_range() const { return llvm::reverse(FSList); }
446
447protected:
448 void printImpl(raw_ostream &OS, PrintType Type,
449 unsigned IndentLevel) const override;
450 void visitChildFileSystems(VisitCallbackTy Callback) override;
451};
452
453/// By default, this delegates all calls to the underlying file system. This
454/// is useful when derived file systems want to override some calls and still
455/// proxy other calls.
457 : public RTTIExtends<ProxyFileSystem, FileSystem> {
458public:
459 static const char ID;
462
463 llvm::ErrorOr<Status> status(const Twine &Path) override {
464 return FS->status(Path);
465 }
466 bool exists(const Twine &Path) override { return FS->exists(Path); }
468 openFileForRead(const Twine &Path) override {
469 return FS->openFileForRead(Path);
470 }
471 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
472 return FS->dir_begin(Dir, EC);
473 }
475 return FS->getCurrentWorkingDirectory();
476 }
477 std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
478 return FS->setCurrentWorkingDirectory(Path);
479 }
480 std::error_code getRealPath(const Twine &Path,
481 SmallVectorImpl<char> &Output) override {
482 return FS->getRealPath(Path, Output);
483 }
484 std::error_code isLocal(const Twine &Path, bool &Result) override {
485 return FS->isLocal(Path, Result);
486 }
487
488protected:
489 FileSystem &getUnderlyingFS() const { return *FS; }
490 void visitChildFileSystems(VisitCallbackTy Callback) override {
491 if (FS) {
492 Callback(*FS);
493 FS->visitChildFileSystems(Callback);
494 }
495 }
496
497private:
499
500 void anchor() override;
501};
502
503namespace detail {
504
505class InMemoryDirectory;
506class InMemoryNode;
507
521
524 Value;
525
526public:
529 : Value(std::make_pair(Name, Node)) {}
530 NamedNodeOrError(std::error_code EC) : Value(EC) {}
531 NamedNodeOrError(llvm::errc EC) : Value(EC) {}
532
533 StringRef getName() const { return (*Value).first; }
534 explicit operator bool() const { return static_cast<bool>(Value); }
535 operator std::error_code() const { return Value.getError(); }
536 std::error_code getError() const { return Value.getError(); }
537 const detail::InMemoryNode *operator*() const { return (*Value).second; }
538};
539
540} // namespace detail
541
542/// An in-memory file system.
544 : public RTTIExtends<InMemoryFileSystem, FileSystem> {
545 std::unique_ptr<detail::InMemoryDirectory> Root;
546 std::string WorkingDirectory;
547 bool UseNormalizedPaths = true;
548
549public:
550 static const char ID;
551
552private:
555
556 /// Create node with \p MakeNode and add it into this filesystem at \p Path.
557 bool addFile(const Twine &Path, time_t ModificationTime,
558 std::unique_ptr<llvm::MemoryBuffer> Buffer,
559 std::optional<uint32_t> User, std::optional<uint32_t> Group,
560 std::optional<llvm::sys::fs::file_type> Type,
561 std::optional<llvm::sys::fs::perms> Perms, MakeNodeFn MakeNode);
562
563 /// Looks up the in-memory node for the path \p P.
564 /// If \p FollowFinalSymlink is true, the returned node is guaranteed to
565 /// not be a symlink and its path may differ from \p P.
566 detail::NamedNodeOrError lookupNode(const Twine &P, bool FollowFinalSymlink,
567 size_t SymlinkDepth = 0) const;
568
569 class DirIterator;
570
571public:
572 explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
574
575 /// Add a file containing a buffer or a directory to the VFS with a
576 /// path. The VFS owns the buffer. If present, User, Group, Type
577 /// and Perms apply to the newly-created file or directory.
578 /// \return true if the file or directory was successfully added,
579 /// false if the file or directory already exists in the file system with
580 /// different contents.
581 bool addFile(const Twine &Path, time_t ModificationTime,
582 std::unique_ptr<llvm::MemoryBuffer> Buffer,
583 std::optional<uint32_t> User = std::nullopt,
584 std::optional<uint32_t> Group = std::nullopt,
585 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
586 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
587
588 /// Add a hard link to a file.
589 ///
590 /// Here hard links are not intended to be fully equivalent to the classical
591 /// filesystem. Both the hard link and the file share the same buffer and
592 /// status (and thus have the same UniqueID). Because of this there is no way
593 /// to distinguish between the link and the file after the link has been
594 /// added.
595 ///
596 /// The \p Target path must be an existing file or a hardlink. The
597 /// \p NewLink file must not have been added before. The \p Target
598 /// path must not be a directory. The \p NewLink node is added as a hard
599 /// link which points to the resolved file of \p Target node.
600 /// \return true if the above condition is satisfied and hardlink was
601 /// successfully created, false otherwise.
602 bool addHardLink(const Twine &NewLink, const Twine &Target);
603
604 /// Arbitrary max depth to search through symlinks. We can get into problems
605 /// if a link links to a link that links back to the link, for example.
606 static constexpr size_t MaxSymlinkDepth = 16;
607
608 /// Add a symbolic link. Unlike a HardLink, because \p Target doesn't need
609 /// to refer to a file (or refer to anything, as it happens). Also, an
610 /// in-memory directory for \p Target isn't automatically created.
611 bool
612 addSymbolicLink(const Twine &NewLink, const Twine &Target,
613 time_t ModificationTime,
614 std::optional<uint32_t> User = std::nullopt,
615 std::optional<uint32_t> Group = std::nullopt,
616 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
617
618 /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
619 /// If present, User, Group, Type and Perms apply to the newly-created file
620 /// or directory.
621 /// \return true if the file or directory was successfully added,
622 /// false if the file or directory already exists in the file system with
623 /// different contents.
624 bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
625 const llvm::MemoryBufferRef &Buffer,
626 std::optional<uint32_t> User = std::nullopt,
627 std::optional<uint32_t> Group = std::nullopt,
628 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
629 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
630
631 std::string toString() const;
632
633 /// Return true if this file system normalizes . and .. in paths.
634 bool useNormalizedPaths() const { return UseNormalizedPaths; }
635
636 llvm::ErrorOr<Status> status(const Twine &Path) override;
638 openFileForRead(const Twine &Path) override;
639 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
640
642 return WorkingDirectory;
643 }
644 /// Canonicalizes \p Path by combining with the current working
645 /// directory and normalizing the path (e.g. remove dots). If the current
646 /// working directory is not set, this returns errc::operation_not_permitted.
647 ///
648 /// This doesn't resolve symlinks as they are not supported in in-memory file
649 /// system.
650 std::error_code getRealPath(const Twine &Path,
651 SmallVectorImpl<char> &Output) override;
652 std::error_code isLocal(const Twine &Path, bool &Result) override;
653 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
654
655protected:
656 void printImpl(raw_ostream &OS, PrintType Type,
657 unsigned IndentLevel) const override;
658};
659
660/// Get a globally unique ID for a virtual file or directory.
662
663/// Gets a \p FileSystem for a virtual file system described in YAML
664/// format.
665LLVM_ABI std::unique_ptr<FileSystem>
666getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
668 StringRef YAMLFilePath, void *DiagContext = nullptr,
670
672 template <typename T1, typename T2>
673 YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory = false)
674 : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)),
676 std::string VPath;
677 std::string RPath;
678 bool IsDirectory = false;
679};
680
683
684/// A virtual file system parsed from a YAML file.
685///
686/// Currently, this class allows creating virtual files and directories. Virtual
687/// files map to existing external files in \c ExternalFS, and virtual
688/// directories may either map to existing directories in \c ExternalFS or list
689/// their contents in the form of other virtual directories and/or files.
690///
691/// The basic structure of the parsed file is:
692/// \verbatim
693/// {
694/// 'version': <version number>,
695/// <optional configuration>
696/// 'roots': [
697/// <directory entries>
698/// ]
699/// }
700/// \endverbatim
701/// The roots may be absolute or relative. If relative they will be made
702/// absolute against either current working directory or the directory where
703/// the Overlay YAML file is located, depending on the 'root-relative'
704/// configuration.
705///
706/// All configuration options are optional.
707/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
708/// 'use-external-names': <boolean, default=true>
709/// 'root-relative': <string, one of 'cwd' or 'overlay-dir', default='cwd'>
710/// 'overlay-relative': <boolean, default=false>
711/// 'fallthrough': <boolean, default=true, deprecated - use 'redirecting-with'
712/// instead>
713/// 'redirecting-with': <string, one of 'fallthrough', 'fallback', or
714/// 'redirect-only', default='fallthrough'>
715///
716/// To clarify, 'root-relative' option will prepend the current working
717/// directory, or the overlay directory to the 'roots->name' field only if
718/// 'roots->name' is a relative path. On the other hand, when 'overlay-relative'
719/// is set to 'true', external paths will always be prepended with the overlay
720/// directory, even if external paths are not relative paths. The
721/// 'root-relative' option has no interaction with the 'overlay-relative'
722/// option.
723///
724/// Virtual directories that list their contents are represented as
725/// \verbatim
726/// {
727/// 'type': 'directory',
728/// 'name': <string>,
729/// 'contents': [ <file or directory entries> ]
730/// }
731/// \endverbatim
732/// The default attributes for such virtual directories are:
733/// \verbatim
734/// MTime = now() when created
735/// Perms = 0777
736/// User = Group = 0
737/// Size = 0
738/// UniqueID = unspecified unique value
739/// \endverbatim
740/// When a path prefix matches such a directory, the next component in the path
741/// is matched against the entries in the 'contents' array.
742///
743/// Re-mapped directories, on the other hand, are represented as
744/// /// \verbatim
745/// {
746/// 'type': 'directory-remap',
747/// 'name': <string>,
748/// 'use-external-name': <boolean>, # Optional
749/// 'external-contents': <path to external directory>
750/// }
751/// \endverbatim
752/// and inherit their attributes from the external directory. When a path
753/// prefix matches such an entry, the unmatched components are appended to the
754/// 'external-contents' path, and the resulting path is looked up in the
755/// external file system instead.
756///
757/// Re-mapped files are represented as
758/// \verbatim
759/// {
760/// 'type': 'file',
761/// 'name': <string>,
762/// 'use-external-name': <boolean>, # Optional
763/// 'external-contents': <path to external file>
764/// }
765/// \endverbatim
766/// Their attributes and file contents are determined by looking up the file at
767/// their 'external-contents' path in the external file system.
768///
769/// For 'file', 'directory' and 'directory-remap' entries the 'name' field may
770/// contain multiple path components (e.g. /path/to/file). However, any
771/// directory in such a path that contains more than one child must be uniquely
772/// represented by a 'directory' entry.
773///
774/// When the 'use-external-name' field is set, calls to \a vfs::File::status()
775/// give the external (remapped) filesystem name instead of the name the file
776/// was accessed by. This is an intentional leak through the \a
777/// RedirectingFileSystem abstraction layer. It enables clients to discover
778/// (and use) the external file location when communicating with users or tools
779/// that don't use the same VFS overlay.
780///
781/// FIXME: 'use-external-name' causes behaviour that's inconsistent with how
782/// "real" filesystems behave. Maybe there should be a separate channel for
783/// this information.
784class LLVM_ABI RedirectingFileSystem
785 : public RTTIExtends<RedirectingFileSystem, vfs::FileSystem> {
786public:
787 static const char ID;
790
791 /// The type of redirection to perform.
792 enum class RedirectKind {
793 /// Lookup the redirected path first (ie. the one specified in
794 /// 'external-contents') and if that fails "fallthrough" to a lookup of the
795 /// originally provided path.
797 /// Lookup the provided path first and if that fails, "fallback" to a
798 /// lookup of the redirected path.
800 /// Only lookup the redirected path, do not lookup the originally provided
801 /// path.
803 };
804
805 /// The type of relative path used by Roots.
806 enum class RootRelativeKind {
807 /// The roots are relative to the current working directory.
809 /// The roots are relative to the directory where the Overlay YAML file
810 // locates.
812 };
813
814 /// A single file or directory in the VFS.
815 class Entry {
816 EntryKind Kind;
817 std::string Name;
818
819 public:
820 Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
821 virtual ~Entry() = default;
822
823 StringRef getName() const { return Name; }
824 EntryKind getKind() const { return Kind; }
825 };
826
827 /// A directory in the vfs with explicitly specified contents.
828 class DirectoryEntry : public Entry {
829 std::vector<std::unique_ptr<Entry>> Contents;
830 Status S;
831
832 public:
833 /// Constructs a directory entry with explicitly specified contents.
834 DirectoryEntry(StringRef Name, std::vector<std::unique_ptr<Entry>> Contents,
835 Status S)
836 : Entry(EK_Directory, Name), Contents(std::move(Contents)),
837 S(std::move(S)) {}
838
839 /// Constructs an empty directory entry.
841 : Entry(EK_Directory, Name), S(std::move(S)) {}
842
843 Status getStatus() { return S; }
844
845 void addContent(std::unique_ptr<Entry> Content) {
846 Contents.push_back(std::move(Content));
847 }
848
849 Entry *getLastContent() const { return Contents.back().get(); }
850
851 using iterator = decltype(Contents)::iterator;
852
853 iterator contents_begin() { return Contents.begin(); }
854 iterator contents_end() { return Contents.end(); }
855
856 static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
857 };
858
859 /// A file or directory in the vfs that is mapped to a file or directory in
860 /// the external filesystem.
861 class RemapEntry : public Entry {
862 std::string ExternalContentsPath;
863 NameKind UseName;
864
865 protected:
866 RemapEntry(EntryKind K, StringRef Name, StringRef ExternalContentsPath,
867 NameKind UseName)
868 : Entry(K, Name), ExternalContentsPath(ExternalContentsPath),
869 UseName(UseName) {}
870
871 public:
872 StringRef getExternalContentsPath() const { return ExternalContentsPath; }
873
874 /// Whether to use the external path as the name for this file or directory.
875 bool useExternalName(bool GlobalUseExternalName) const {
876 return UseName == NK_NotSet ? GlobalUseExternalName
877 : (UseName == NK_External);
878 }
879
880 NameKind getUseName() const { return UseName; }
881
882 static bool classof(const Entry *E) {
883 switch (E->getKind()) {
885 [[fallthrough]];
886 case EK_File:
887 return true;
888 case EK_Directory:
889 return false;
890 }
891 llvm_unreachable("invalid entry kind");
892 }
893 };
894
895 /// A directory in the vfs that maps to a directory in the external file
896 /// system.
898 public:
899 DirectoryRemapEntry(StringRef Name, StringRef ExternalContentsPath,
900 NameKind UseName)
901 : RemapEntry(EK_DirectoryRemap, Name, ExternalContentsPath, UseName) {}
902
903 static bool classof(const Entry *E) {
904 return E->getKind() == EK_DirectoryRemap;
905 }
906 };
907
908 /// A file in the vfs that maps to a file in the external file system.
909 class FileEntry : public RemapEntry {
910 public:
911 FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
912 : RemapEntry(EK_File, Name, ExternalContentsPath, UseName) {}
913
914 static bool classof(const Entry *E) { return E->getKind() == EK_File; }
915 };
916
917 /// Represents the result of a path lookup into the RedirectingFileSystem.
919 /// Chain of parent directory entries for \c E.
921
922 /// The entry the looked-up path corresponds to.
924
925 private:
926 /// When the found Entry is a DirectoryRemapEntry, stores the path in the
927 /// external file system that the looked-up path in the virtual file system
928 // corresponds to.
929 std::optional<std::string> ExternalRedirect;
930
931 public:
934
935 /// If the found Entry maps the input path to a path in the external
936 /// file system (i.e. it is a FileEntry or DirectoryRemapEntry), returns
937 /// that path.
938 std::optional<StringRef> getExternalRedirect() const {
940 return StringRef(*ExternalRedirect);
941 if (auto *FE = dyn_cast<FileEntry>(E))
942 return FE->getExternalContentsPath();
943 return std::nullopt;
944 }
945
946 /// Get the (canonical) path of the found entry. This uses the as-written
947 /// path components from the VFS specification.
948 LLVM_ABI void getPath(llvm::SmallVectorImpl<char> &Path) const;
949 };
950
951private:
954
955 /// Canonicalize path by removing ".", "..", "./", components. This is
956 /// a VFS request, do not bother about symlinks in the path components
957 /// but canonicalize in order to perform the correct entry search.
958 std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const;
959
960 /// Get the File status, or error, from the underlying external file system.
961 /// This returns the status with the originally requested name, while looking
962 /// up the entry using a potentially different path.
963 ErrorOr<Status> getExternalStatus(const Twine &LookupPath,
964 const Twine &OriginalPath) const;
965
966 /// Make \a Path an absolute path.
967 ///
968 /// Makes \a Path absolute using the \a WorkingDir if it is not already.
969 ///
970 /// /absolute/path => /absolute/path
971 /// relative/../path => <WorkingDir>/relative/../path
972 ///
973 /// \param WorkingDir A path that will be used as the base Dir if \a Path
974 /// is not already absolute.
975 /// \param Path A path that is modified to be an absolute path.
976 /// \returns success if \a path has been made absolute, otherwise a
977 /// platform-specific error_code.
978 std::error_code makeAbsolute(StringRef WorkingDir,
979 SmallVectorImpl<char> &Path) const;
980
981 // In a RedirectingFileSystem, keys can be specified in Posix or Windows
982 // style (or even a mixture of both), so this comparison helper allows
983 // slashes (representing a root) to match backslashes (and vice versa). Note
984 // that, other than the root, path components should not contain slashes or
985 // backslashes.
986 bool pathComponentMatches(llvm::StringRef lhs, llvm::StringRef rhs) const {
987 if ((CaseSensitive ? lhs == rhs : lhs.equals_insensitive(rhs)))
988 return true;
989 return (lhs == "/" && rhs == "\\") || (lhs == "\\" && rhs == "/");
990 }
991
992 /// The root(s) of the virtual file system.
993 std::vector<std::unique_ptr<Entry>> Roots;
994
995 /// The current working directory of the file system.
996 std::string WorkingDirectory;
997
998 /// The file system to use for external references.
1000
1001 /// This represents the directory path that the YAML file is located.
1002 /// This will be prefixed to each 'external-contents' if IsRelativeOverlay
1003 /// is set. This will also be prefixed to each 'roots->name' if RootRelative
1004 /// is set to RootRelativeKind::OverlayDir and the path is relative.
1005 std::string OverlayFileDir;
1006
1007 /// @name Configuration
1008 /// @{
1009
1010 /// Whether to perform case-sensitive comparisons.
1011 ///
1012 /// Currently, case-insensitive matching only works correctly with ASCII.
1013 bool CaseSensitive = is_style_posix(sys::path::Style::native);
1014
1015 /// IsRelativeOverlay marks whether a OverlayFileDir path must
1016 /// be prefixed in every 'external-contents' when reading from YAML files.
1017 bool IsRelativeOverlay = false;
1018
1019 /// Whether to use to use the value of 'external-contents' for the
1020 /// names of files. This global value is overridable on a per-file basis.
1021 bool UseExternalNames = true;
1022
1023 /// True if this FS has redirected a lookup. This does not include
1024 /// fallthrough.
1025 mutable bool HasBeenUsed = false;
1026
1027 /// Used to enable or disable updating `HasBeenUsed`.
1028 bool UsageTrackingActive = false;
1029
1030 /// Determines the lookups to perform, as well as their order. See
1031 /// \c RedirectKind for details.
1032 RedirectKind Redirection = RedirectKind::Fallthrough;
1033
1034 /// Determine the prefix directory if the roots are relative paths. See
1035 /// \c RootRelativeKind for details.
1036 RootRelativeKind RootRelative = RootRelativeKind::CWD;
1037 /// @}
1038
1040
1041 // Explicitly non-copyable.
1043 RedirectingFileSystem &operator=(RedirectingFileSystem const &) = delete;
1044
1045 /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly recursing
1046 /// into the contents of \p From if it is a directory. Returns a LookupResult
1047 /// giving the matched entry and, if that entry is a FileEntry or
1048 /// DirectoryRemapEntry, the path it redirects to in the external file system.
1050 lookupPathImpl(llvm::sys::path::const_iterator Start,
1051 llvm::sys::path::const_iterator End, Entry *From,
1052 llvm::SmallVectorImpl<Entry *> &Entries) const;
1053
1054 /// Get the status for a path with the provided \c LookupResult.
1055 ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath,
1056 const LookupResult &Result);
1057
1058public:
1059 /// Looks up \p Path in \c Roots and returns a LookupResult giving the
1060 /// matched entry and, if the entry was a FileEntry or DirectoryRemapEntry,
1061 /// the path it redirects to in the external file system.
1062 ErrorOr<LookupResult> lookupPath(StringRef Path) const;
1063
1064 /// Parses \p Buffer, which is expected to be in YAML format and
1065 /// returns a virtual file system representing its contents.
1066 static std::unique_ptr<RedirectingFileSystem>
1067 create(std::unique_ptr<MemoryBuffer> Buffer,
1069 void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1070
1071 /// Redirect each of the remapped files from first to second.
1072 static std::unique_ptr<RedirectingFileSystem>
1073 create(ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1074 bool UseExternalNames, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1075
1076 ErrorOr<Status> status(const Twine &Path) override;
1077 bool exists(const Twine &Path) override;
1078 ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
1079
1080 std::error_code getRealPath(const Twine &Path,
1081 SmallVectorImpl<char> &Output) override;
1082
1083 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
1084
1085 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
1086
1087 std::error_code isLocal(const Twine &Path, bool &Result) override;
1088
1089 std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const override;
1090
1091 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
1092
1093 void setOverlayFileDir(StringRef PrefixDir);
1094
1095 StringRef getOverlayFileDir() const;
1096
1097 /// Sets the redirection kind to \c Fallthrough if true or \c RedirectOnly
1098 /// otherwise. Will removed in the future, use \c setRedirection instead.
1099 void setFallthrough(bool Fallthrough);
1100
1101 void setRedirection(RedirectingFileSystem::RedirectKind Kind);
1102
1103 std::vector<llvm::StringRef> getRoots() const;
1104
1105 bool hasBeenUsed() const { return HasBeenUsed; };
1106 void clearHasBeenUsed() { HasBeenUsed = false; }
1107
1108 void setUsageTrackingActive(bool Active) { UsageTrackingActive = Active; }
1109
1110 void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel = 0) const;
1111
1112protected:
1113 void printImpl(raw_ostream &OS, PrintType Type,
1114 unsigned IndentLevel) const override;
1115 void visitChildFileSystems(VisitCallbackTy Callback) override;
1116};
1117
1118/// Collect all pairs of <virtual path, real path> entries from the
1119/// \p VFS. This is used by the module dependency collector to forward
1120/// the entries into the reproducer output VFS YAML file.
1121LLVM_ABI void
1122collectVFSEntries(RedirectingFileSystem &VFS,
1123 SmallVectorImpl<YAMLVFSEntry> &CollectedEntries);
1124
1126 std::vector<YAMLVFSEntry> Mappings;
1127 std::optional<bool> IsCaseSensitive;
1128 std::optional<bool> IsOverlayRelative;
1129 std::optional<bool> UseExternalNames;
1130 std::string OverlayDir;
1131
1132 void addEntry(StringRef VirtualPath, StringRef RealPath, bool IsDirectory);
1133
1134public:
1135 YAMLVFSWriter() = default;
1136
1137 LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath);
1138 LLVM_ABI void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath);
1139
1140 void setCaseSensitivity(bool CaseSensitive) {
1141 IsCaseSensitive = CaseSensitive;
1142 }
1143
1144 void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
1145
1146 void setOverlayDir(StringRef OverlayDirectory) {
1147 IsOverlayRelative = true;
1148 OverlayDir.assign(OverlayDirectory.str());
1149 }
1150
1151 const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
1152
1154};
1155
1156/// File system that tracks the number of calls to the underlying file system.
1157/// This is particularly useful when wrapped around \c RealFileSystem to add
1158/// lightweight tracking of expensive syscalls.
1160 : public llvm::RTTIExtends<TracingFileSystem, ProxyFileSystem> {
1161public:
1162 static const char ID;
1163
1164 std::size_t NumStatusCalls = 0;
1166 std::size_t NumDirBeginCalls = 0;
1167 std::size_t NumGetRealPathCalls = 0;
1168 std::size_t NumExistsCalls = 0;
1169 std::size_t NumIsLocalCalls = 0;
1170
1173
1174 ErrorOr<Status> status(const Twine &Path) override {
1176 return ProxyFileSystem::status(Path);
1177 }
1178
1183
1184 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
1186 return ProxyFileSystem::dir_begin(Dir, EC);
1187 }
1188
1189 std::error_code getRealPath(const Twine &Path,
1190 SmallVectorImpl<char> &Output) override {
1192 return ProxyFileSystem::getRealPath(Path, Output);
1193 }
1194
1195 bool exists(const Twine &Path) override {
1197 return ProxyFileSystem::exists(Path);
1198 }
1199
1200 std::error_code isLocal(const Twine &Path, bool &Result) override {
1202 return ProxyFileSystem::isLocal(Path, Result);
1203 }
1204
1205protected:
1206 void printImpl(raw_ostream &OS, PrintType Type,
1207 unsigned IndentLevel) const override;
1208};
1209
1210} // namespace vfs
1211} // namespace llvm
1212
1213#endif // LLVM_SUPPORT_VIRTUALFILESYSTEM_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
Provides ErrorOr<T> smart pointer.
static void makeAbsolute(vfs::FileSystem &VFS, SmallVectorImpl< char > &Path)
Make Path absolute.
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
#define I(x, y, z)
Definition MD5.cpp:57
static const char * toString(MIToken::TokenKind TokenKind)
Definition MIParser.cpp:625
#define T1
static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)
#define P(N)
This file defines the SmallVector class.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Value * RHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Represents either an error or a value T.
Definition ErrorOr.h:56
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Inheritance utility for extensible RTTI.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
std::reverse_iterator< const_iterator > const_reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition SourceMgr.h:49
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:225
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition StringRef.h:172
Target - Wrapper for Target specific information.
A thread-safe version of RefCountedBase.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Represents the result of a call to sys::fs::status().
Definition FileSystem.h:222
The virtual file system interface.
llvm::function_ref< void(FileSystem &)> VisitCallbackTy
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
virtual bool exists(const Twine &Path)
Check whether Path exists.
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForReadBinary(const Twine &Path)
Get a File object for the binary file at Path, if one exists.
virtual std::error_code setCurrentWorkingDirectory(const Twine &Path)=0
Set the working directory.
virtual void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0
Get a File object for the text file at Path, if one exists.
virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output)
Gets real path of Path e.g.
virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC)=0
Get a directory_iterator for Dir.
void printIndent(raw_ostream &OS, unsigned IndentLevel) const
void print(raw_ostream &OS, PrintType Type=PrintType::Contents, unsigned IndentLevel=0) const
virtual void visitChildFileSystems(VisitCallbackTy Callback)
void visit(VisitCallbackTy Callback)
llvm::ErrorOr< bool > equivalent(const Twine &A, const Twine &B)
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
Represents an open file.
static ErrorOr< std::unique_ptr< File > > getWithPath(ErrorOr< std::unique_ptr< File > > Result, const Twine &P)
virtual llvm::ErrorOr< Status > status()=0
Get the status of the file.
virtual llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBuffer(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)=0
Get the contents of the file as a MemoryBuffer.
virtual llvm::ErrorOr< std::string > getName()
Get the name of the file.
virtual void setPath(const Twine &Path)
virtual ~File()
Destroy the file after closing it (if open).
virtual std::error_code close()=0
Closes the file.
Adaptor from InMemoryDir::iterator to directory_iterator.
static constexpr size_t MaxSymlinkDepth
Arbitrary max depth to search through symlinks.
InMemoryFileSystem(bool UseNormalizedPaths=true)
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
bool addHardLink(const Twine &NewLink, const Twine &Target)
Add a hard link to a file.
bool addFileNoOwn(const Twine &Path, time_t ModificationTime, const llvm::MemoryBufferRef &Buffer, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::file_type > Type=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)
Add a buffer to the VFS with a path.
bool addSymbolicLink(const Twine &NewLink, const Twine &Target, time_t ModificationTime, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)
Add a symbolic link.
const_iterator overlays_end() const
const_iterator overlays_begin() const
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
reverse_iterator overlays_rbegin()
Get an iterator pointing to the least recently added file system.
const_range overlays_range() const
const_reverse_iterator overlays_rend() const
iterator_range< iterator > range
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
reverse_iterator overlays_rend()
Get an iterator pointing one-past the most recently added file system.
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
FileSystemList::const_reverse_iterator const_iterator
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
FileSystemList::const_iterator const_reverse_iterator
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
std::error_code isLocal(const Twine &Path, bool &Result) override
FileSystemList::iterator reverse_iterator
bool exists(const Twine &Path) override
llvm::ErrorOr< Status > status(const Twine &Path) override
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
iterator_range< const_iterator > const_range
const_reverse_iterator overlays_rbegin() const
FileSystemList::reverse_iterator iterator
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
void visitChildFileSystems(VisitCallbackTy Callback) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
llvm::ErrorOr< Status > status(const Twine &Path) override
bool exists(const Twine &Path) override
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
std::error_code isLocal(const Twine &Path, bool &Result) override
ProxyFileSystem(IntrusiveRefCntPtr< FileSystem > FS)
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
FileSystem & getUnderlyingFS() const
Directory iterator implementation for RedirectingFileSystem's directory entries.
A helper class to hold the common YAML parsing state.
DirectoryEntry(StringRef Name, Status S)
Constructs an empty directory entry.
DirectoryEntry(StringRef Name, std::vector< std::unique_ptr< Entry > > Contents, Status S)
Constructs a directory entry with explicitly specified contents.
void addContent(std::unique_ptr< Entry > Content)
DirectoryRemapEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
A single file or directory in the VFS.
FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
RemapEntry(EntryKind K, StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
bool useExternalName(bool GlobalUseExternalName) const
Whether to use the external path as the name for this file or directory.
A virtual file system parsed from a YAML file.
RootRelativeKind
The type of relative path used by Roots.
@ OverlayDir
The roots are relative to the directory where the Overlay YAML file.
@ CWD
The roots are relative to the current working directory.
RedirectKind
The type of redirection to perform.
@ Fallthrough
Lookup the redirected path first (ie.
@ Fallback
Lookup the provided path first and if that fails, "fallback" to a lookup of the redirected path.
@ RedirectOnly
Only lookup the redirected path, do not lookup the originally provided path.
The result of a status operation.
llvm::sys::fs::perms getPermissions() const
llvm::sys::fs::UniqueID getUniqueID() const
uint32_t getUser() const
LLVM_ABI bool equivalent(const Status &Other) const
static LLVM_ABI Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
uint64_t getSize() const
LLVM_ABI bool isStatusKnown() const
LLVM_ABI bool exists() const
bool ExposesExternalVFSPath
Whether this entity has an external path different from the virtual path, and the external path is ex...
uint32_t getGroup() const
static LLVM_ABI Status copyWithNewSize(const Status &In, uint64_t NewSize)
Get a copy of a Status with a different size.
LLVM_ABI bool isOther() const
LLVM_ABI bool isSymlink() const
llvm::sys::TimePoint getLastModificationTime() const
llvm::sys::fs::file_type getType() const
LLVM_ABI bool isRegularFile() const
LLVM_ABI bool isDirectory() const
StringRef getName() const
Returns the name that should be used for this file or directory.
bool exists(const Twine &Path) override
TracingFileSystem(llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
ErrorOr< Status > status(const Twine &Path) override
std::error_code isLocal(const Twine &Path, bool &Result) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath)
void setCaseSensitivity(bool CaseSensitive)
void setOverlayDir(StringRef OverlayDirectory)
const std::vector< YAMLVFSEntry > & getMappings() const
LLVM_ABI void write(llvm::raw_ostream &OS)
LLVM_ABI void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)
void setUseExternalNames(bool UseExtNames)
The in memory file system is a tree of Nodes.
const detail::InMemoryNode * operator*() const
NamedNodeOrError(llvm::SmallString< 128 > Name, const detail::InMemoryNode *Node)
A member of a directory, yielded by a directory_iterator.
directory_entry()=default
directory_entry(std::string Path, llvm::sys::fs::file_type Type)
llvm::StringRef path() const
llvm::sys::fs::file_type type() const
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
directory_iterator(std::shared_ptr< detail::DirIterImpl > I)
bool operator==(const directory_iterator &RHS) const
const directory_entry * operator->() const
const directory_entry & operator*() const
directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
bool operator!=(const directory_iterator &RHS) const
directory_iterator()=default
Construct an 'end' iterator.
const directory_entry & operator*() const
LLVM_ABI recursive_directory_iterator(FileSystem &FS, const Twine &Path, std::error_code &EC)
recursive_directory_iterator()=default
Construct an 'end' iterator.
bool operator!=(const recursive_directory_iterator &RHS) const
bool operator==(const recursive_directory_iterator &Other) const
int level() const
Gets the current level. Starting path is at level 0.
LLVM_ABI recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
const directory_entry * operator->() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
file_type
An enumeration for the file system's view of the type.
Definition FileSystem.h:62
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition Chrono.h:34
LLVM_ABI void collectVFSEntries(RedirectingFileSystem &VFS, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries)
Collect all pairs of <virtual path, real path> entries from the VFS.
LLVM_ABI std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.
LLVM_ABI llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
LLVM_ABI std::unique_ptr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
errc
Definition Errc.h:35
auto reverse(ContainerTy &&C)
Definition STLExtras.h:406
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Other
Any other memory.
Definition ModRef.h:68
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1879
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
std::optional< StringRef > getExternalRedirect() const
If the found Entry maps the input path to a path in the external file system (i.e.
Entry * E
The entry the looked-up path corresponds to.
LLVM_ABI LookupResult(Entry *E, sys::path::const_iterator Start, sys::path::const_iterator End)
llvm::SmallVector< Entry *, 32 > Parents
Chain of parent directory entries for E.
YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory=false)
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
virtual std::error_code increment()=0
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
std::unique_ptr< llvm::MemoryBuffer > Buffer
Keeps state for the recursive_directory_iterator.
std::vector< directory_iterator > Stack