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;
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;
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 /// @{
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; }
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 virtual ~FileSystem();
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.
339 llvm::ErrorOr<bool> equivalent(const Twine &A, const Twine &B);
340
341 enum class PrintType { Summary, Contents, RecursiveContents };
342 void print(raw_ostream &OS, PrintType Type = PrintType::Contents,
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).
376
377/// Create an \p vfs::FileSystem for the 'real' file system, as seen by
378/// the operating system.
379/// It has its own working directory, independent of (but initially equal to)
380/// that of the process.
381LLVM_ABI std::unique_ptr<FileSystem> createPhysicalFileSystem();
382
383/// A file system that allows overlaying one \p AbstractFileSystem on top
384/// of another.
385///
386/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
387/// one merged file system. When there is a directory that exists in more than
388/// one file system, the \p OverlayFileSystem contains a directory containing
389/// the union of their contents. The attributes (permissions, etc.) of the
390/// top-most (most recently added) directory are used. When there is a file
391/// that exists in more than one file system, the file in the top-most file
392/// system overrides the other(s).
394 : public RTTIExtends<OverlayFileSystem, FileSystem> {
396
397 /// The stack of file systems, implemented as a list in order of
398 /// their addition.
399 FileSystemList FSList;
400
401public:
402 static const char ID;
404
405 /// Pushes a file system on top of the stack.
406 void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
407
408 llvm::ErrorOr<Status> status(const Twine &Path) override;
409 bool exists(const Twine &Path) override;
411 openFileForRead(const Twine &Path) override;
412 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
413 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
414 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
415 std::error_code isLocal(const Twine &Path, bool &Result) override;
416 std::error_code getRealPath(const Twine &Path,
417 SmallVectorImpl<char> &Output) override;
418
425
426 /// Get an iterator pointing to the most recently added file system.
427 iterator overlays_begin() { return FSList.rbegin(); }
428 const_iterator overlays_begin() const { return FSList.rbegin(); }
429
430 /// Get an iterator pointing one-past the least recently added file system.
431 iterator overlays_end() { return FSList.rend(); }
432 const_iterator overlays_end() const { return FSList.rend(); }
433
434 /// Get an iterator pointing to the least recently added file system.
436 const_reverse_iterator overlays_rbegin() const { return FSList.begin(); }
437
438 /// Get an iterator pointing one-past the most recently added file system.
439 reverse_iterator overlays_rend() { return FSList.end(); }
440 const_reverse_iterator overlays_rend() const { return FSList.end(); }
441
442 range overlays_range() { return llvm::reverse(FSList); }
443 const_range overlays_range() const { return llvm::reverse(FSList); }
444
445protected:
446 void printImpl(raw_ostream &OS, PrintType Type,
447 unsigned IndentLevel) const override;
448 void visitChildFileSystems(VisitCallbackTy Callback) override;
449};
450
451/// By default, this delegates all calls to the underlying file system. This
452/// is useful when derived file systems want to override some calls and still
453/// proxy other calls.
455 : public RTTIExtends<ProxyFileSystem, FileSystem> {
456public:
457 static const char ID;
459 : FS(std::move(FS)) {}
460
461 llvm::ErrorOr<Status> status(const Twine &Path) override {
462 return FS->status(Path);
463 }
464 bool exists(const Twine &Path) override { return FS->exists(Path); }
466 openFileForRead(const Twine &Path) override {
467 return FS->openFileForRead(Path);
468 }
469 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
470 return FS->dir_begin(Dir, EC);
471 }
473 return FS->getCurrentWorkingDirectory();
474 }
475 std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
476 return FS->setCurrentWorkingDirectory(Path);
477 }
478 std::error_code getRealPath(const Twine &Path,
479 SmallVectorImpl<char> &Output) override {
480 return FS->getRealPath(Path, Output);
481 }
482 std::error_code isLocal(const Twine &Path, bool &Result) override {
483 return FS->isLocal(Path, Result);
484 }
485
486protected:
487 FileSystem &getUnderlyingFS() const { return *FS; }
488 void visitChildFileSystems(VisitCallbackTy Callback) override {
489 if (FS) {
490 Callback(*FS);
491 FS->visitChildFileSystems(Callback);
492 }
493 }
494
495private:
497
498 virtual void anchor() override;
499};
500
501namespace detail {
502
503class InMemoryDirectory;
504class InMemoryNode;
505
511 std::unique_ptr<llvm::MemoryBuffer> Buffer;
516
517 LLVM_ABI Status makeStatus() const;
518};
519
522 Value;
523
524public:
527 : Value(std::make_pair(Name, Node)) {}
528 NamedNodeOrError(std::error_code EC) : Value(EC) {}
530
531 StringRef getName() const { return (*Value).first; }
532 explicit operator bool() const { return static_cast<bool>(Value); }
533 operator std::error_code() const { return Value.getError(); }
534 std::error_code getError() const { return Value.getError(); }
535 const detail::InMemoryNode *operator*() const { return (*Value).second; }
536};
537
538} // namespace detail
539
540/// An in-memory file system.
542 : public RTTIExtends<InMemoryFileSystem, FileSystem> {
543 std::unique_ptr<detail::InMemoryDirectory> Root;
544 std::string WorkingDirectory;
545 bool UseNormalizedPaths = true;
546
547public:
548 static const char ID;
549
550private:
553
554 /// Create node with \p MakeNode and add it into this filesystem at \p Path.
555 bool addFile(const Twine &Path, time_t ModificationTime,
556 std::unique_ptr<llvm::MemoryBuffer> Buffer,
557 std::optional<uint32_t> User, std::optional<uint32_t> Group,
558 std::optional<llvm::sys::fs::file_type> Type,
559 std::optional<llvm::sys::fs::perms> Perms, MakeNodeFn MakeNode);
560
561 /// Looks up the in-memory node for the path \p P.
562 /// If \p FollowFinalSymlink is true, the returned node is guaranteed to
563 /// not be a symlink and its path may differ from \p P.
564 detail::NamedNodeOrError lookupNode(const Twine &P, bool FollowFinalSymlink,
565 size_t SymlinkDepth = 0) const;
566
567 class DirIterator;
568
569public:
570 explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
572
573 /// Add a file containing a buffer or a directory to the VFS with a
574 /// path. The VFS owns the buffer. If present, User, Group, Type
575 /// and Perms apply to the newly-created file or directory.
576 /// \return true if the file or directory was successfully added,
577 /// false if the file or directory already exists in the file system with
578 /// different contents.
579 bool addFile(const Twine &Path, time_t ModificationTime,
580 std::unique_ptr<llvm::MemoryBuffer> Buffer,
581 std::optional<uint32_t> User = std::nullopt,
582 std::optional<uint32_t> Group = std::nullopt,
583 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
584 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
585
586 /// Add a hard link to a file.
587 ///
588 /// Here hard links are not intended to be fully equivalent to the classical
589 /// filesystem. Both the hard link and the file share the same buffer and
590 /// status (and thus have the same UniqueID). Because of this there is no way
591 /// to distinguish between the link and the file after the link has been
592 /// added.
593 ///
594 /// The \p Target path must be an existing file or a hardlink. The
595 /// \p NewLink file must not have been added before. The \p Target
596 /// path must not be a directory. The \p NewLink node is added as a hard
597 /// link which points to the resolved file of \p Target node.
598 /// \return true if the above condition is satisfied and hardlink was
599 /// successfully created, false otherwise.
600 bool addHardLink(const Twine &NewLink, const Twine &Target);
601
602 /// Arbitrary max depth to search through symlinks. We can get into problems
603 /// if a link links to a link that links back to the link, for example.
604 static constexpr size_t MaxSymlinkDepth = 16;
605
606 /// Add a symbolic link. Unlike a HardLink, because \p Target doesn't need
607 /// to refer to a file (or refer to anything, as it happens). Also, an
608 /// in-memory directory for \p Target isn't automatically created.
609 bool
610 addSymbolicLink(const Twine &NewLink, const Twine &Target,
611 time_t ModificationTime,
612 std::optional<uint32_t> User = std::nullopt,
613 std::optional<uint32_t> Group = std::nullopt,
614 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
615
616 /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
617 /// If present, User, Group, Type and Perms apply to the newly-created file
618 /// or directory.
619 /// \return true if the file or directory was successfully added,
620 /// false if the file or directory already exists in the file system with
621 /// different contents.
622 bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
623 const llvm::MemoryBufferRef &Buffer,
624 std::optional<uint32_t> User = std::nullopt,
625 std::optional<uint32_t> Group = std::nullopt,
626 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
627 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
628
629 std::string toString() const;
630
631 /// Return true if this file system normalizes . and .. in paths.
632 bool useNormalizedPaths() const { return UseNormalizedPaths; }
633
634 llvm::ErrorOr<Status> status(const Twine &Path) override;
636 openFileForRead(const Twine &Path) override;
637 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
638
640 return WorkingDirectory;
641 }
642 /// Canonicalizes \p Path by combining with the current working
643 /// directory and normalizing the path (e.g. remove dots). If the current
644 /// working directory is not set, this returns errc::operation_not_permitted.
645 ///
646 /// This doesn't resolve symlinks as they are not supported in in-memory file
647 /// system.
648 std::error_code getRealPath(const Twine &Path,
649 SmallVectorImpl<char> &Output) override;
650 std::error_code isLocal(const Twine &Path, bool &Result) override;
651 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
652
653protected:
654 void printImpl(raw_ostream &OS, PrintType Type,
655 unsigned IndentLevel) const override;
656};
657
658/// Get a globally unique ID for a virtual file or directory.
660
661/// Gets a \p FileSystem for a virtual file system described in YAML
662/// format.
663LLVM_ABI std::unique_ptr<FileSystem>
664getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
666 StringRef YAMLFilePath, void *DiagContext = nullptr,
668
670 template <typename T1, typename T2>
671 YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory = false)
672 : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)),
674 std::string VPath;
675 std::string RPath;
676 bool IsDirectory = false;
677};
678
681
682/// A virtual file system parsed from a YAML file.
683///
684/// Currently, this class allows creating virtual files and directories. Virtual
685/// files map to existing external files in \c ExternalFS, and virtual
686/// directories may either map to existing directories in \c ExternalFS or list
687/// their contents in the form of other virtual directories and/or files.
688///
689/// The basic structure of the parsed file is:
690/// \verbatim
691/// {
692/// 'version': <version number>,
693/// <optional configuration>
694/// 'roots': [
695/// <directory entries>
696/// ]
697/// }
698/// \endverbatim
699/// The roots may be absolute or relative. If relative they will be made
700/// absolute against either current working directory or the directory where
701/// the Overlay YAML file is located, depending on the 'root-relative'
702/// configuration.
703///
704/// All configuration options are optional.
705/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
706/// 'use-external-names': <boolean, default=true>
707/// 'root-relative': <string, one of 'cwd' or 'overlay-dir', default='cwd'>
708/// 'overlay-relative': <boolean, default=false>
709/// 'fallthrough': <boolean, default=true, deprecated - use 'redirecting-with'
710/// instead>
711/// 'redirecting-with': <string, one of 'fallthrough', 'fallback', or
712/// 'redirect-only', default='fallthrough'>
713///
714/// To clarify, 'root-relative' option will prepend the current working
715/// directory, or the overlay directory to the 'roots->name' field only if
716/// 'roots->name' is a relative path. On the other hand, when 'overlay-relative'
717/// is set to 'true', external paths will always be prepended with the overlay
718/// directory, even if external paths are not relative paths. The
719/// 'root-relative' option has no interaction with the 'overlay-relative'
720/// option.
721///
722/// Virtual directories that list their contents are represented as
723/// \verbatim
724/// {
725/// 'type': 'directory',
726/// 'name': <string>,
727/// 'contents': [ <file or directory entries> ]
728/// }
729/// \endverbatim
730/// The default attributes for such virtual directories are:
731/// \verbatim
732/// MTime = now() when created
733/// Perms = 0777
734/// User = Group = 0
735/// Size = 0
736/// UniqueID = unspecified unique value
737/// \endverbatim
738/// When a path prefix matches such a directory, the next component in the path
739/// is matched against the entries in the 'contents' array.
740///
741/// Re-mapped directories, on the other hand, are represented as
742/// /// \verbatim
743/// {
744/// 'type': 'directory-remap',
745/// 'name': <string>,
746/// 'use-external-name': <boolean>, # Optional
747/// 'external-contents': <path to external directory>
748/// }
749/// \endverbatim
750/// and inherit their attributes from the external directory. When a path
751/// prefix matches such an entry, the unmatched components are appended to the
752/// 'external-contents' path, and the resulting path is looked up in the
753/// external file system instead.
754///
755/// Re-mapped files are represented as
756/// \verbatim
757/// {
758/// 'type': 'file',
759/// 'name': <string>,
760/// 'use-external-name': <boolean>, # Optional
761/// 'external-contents': <path to external file>
762/// }
763/// \endverbatim
764/// Their attributes and file contents are determined by looking up the file at
765/// their 'external-contents' path in the external file system.
766///
767/// For 'file', 'directory' and 'directory-remap' entries the 'name' field may
768/// contain multiple path components (e.g. /path/to/file). However, any
769/// directory in such a path that contains more than one child must be uniquely
770/// represented by a 'directory' entry.
771///
772/// When the 'use-external-name' field is set, calls to \a vfs::File::status()
773/// give the external (remapped) filesystem name instead of the name the file
774/// was accessed by. This is an intentional leak through the \a
775/// RedirectingFileSystem abstraction layer. It enables clients to discover
776/// (and use) the external file location when communicating with users or tools
777/// that don't use the same VFS overlay.
778///
779/// FIXME: 'use-external-name' causes behaviour that's inconsistent with how
780/// "real" filesystems behave. Maybe there should be a separate channel for
781/// this information.
783 : public RTTIExtends<RedirectingFileSystem, vfs::FileSystem> {
784public:
785 static const char ID;
786 enum EntryKind { EK_Directory, EK_DirectoryRemap, EK_File };
787 enum NameKind { NK_NotSet, NK_External, NK_Virtual };
788
789 /// The type of redirection to perform.
790 enum class RedirectKind {
791 /// Lookup the redirected path first (ie. the one specified in
792 /// 'external-contents') and if that fails "fallthrough" to a lookup of the
793 /// originally provided path.
794 Fallthrough,
795 /// Lookup the provided path first and if that fails, "fallback" to a
796 /// lookup of the redirected path.
797 Fallback,
798 /// Only lookup the redirected path, do not lookup the originally provided
799 /// path.
800 RedirectOnly
801 };
802
803 /// The type of relative path used by Roots.
804 enum class RootRelativeKind {
805 /// The roots are relative to the current working directory.
806 CWD,
807 /// The roots are relative to the directory where the Overlay YAML file
808 // locates.
809 OverlayDir
810 };
811
812 /// A single file or directory in the VFS.
813 class Entry {
814 EntryKind Kind;
815 std::string Name;
816
817 public:
819 virtual ~Entry() = default;
820
821 StringRef getName() const { return Name; }
822 EntryKind getKind() const { return Kind; }
823 };
824
825 /// A directory in the vfs with explicitly specified contents.
826 class DirectoryEntry : public Entry {
827 std::vector<std::unique_ptr<Entry>> Contents;
828 Status S;
829
830 public:
831 /// Constructs a directory entry with explicitly specified contents.
832 DirectoryEntry(StringRef Name, std::vector<std::unique_ptr<Entry>> Contents,
833 Status S)
834 : Entry(EK_Directory, Name), Contents(std::move(Contents)),
835 S(std::move(S)) {}
836
837 /// Constructs an empty directory entry.
839 : Entry(EK_Directory, Name), S(std::move(S)) {}
840
841 Status getStatus() { return S; }
842
843 void addContent(std::unique_ptr<Entry> Content) {
844 Contents.push_back(std::move(Content));
845 }
846
847 Entry *getLastContent() const { return Contents.back().get(); }
848
849 using iterator = decltype(Contents)::iterator;
850
851 iterator contents_begin() { return Contents.begin(); }
852 iterator contents_end() { return Contents.end(); }
853
854 static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
855 };
856
857 /// A file or directory in the vfs that is mapped to a file or directory in
858 /// the external filesystem.
859 class RemapEntry : public Entry {
860 std::string ExternalContentsPath;
861 NameKind UseName;
862
863 protected:
864 RemapEntry(EntryKind K, StringRef Name, StringRef ExternalContentsPath,
865 NameKind UseName)
866 : Entry(K, Name), ExternalContentsPath(ExternalContentsPath),
867 UseName(UseName) {}
868
869 public:
870 StringRef getExternalContentsPath() const { return ExternalContentsPath; }
871
872 /// Whether to use the external path as the name for this file or directory.
873 bool useExternalName(bool GlobalUseExternalName) const {
874 return UseName == NK_NotSet ? GlobalUseExternalName
875 : (UseName == NK_External);
876 }
877
878 NameKind getUseName() const { return UseName; }
879
880 static bool classof(const Entry *E) {
881 switch (E->getKind()) {
882 case EK_DirectoryRemap:
883 [[fallthrough]];
884 case EK_File:
885 return true;
886 case EK_Directory:
887 return false;
888 }
889 llvm_unreachable("invalid entry kind");
890 }
891 };
892
893 /// A directory in the vfs that maps to a directory in the external file
894 /// system.
896 public:
898 NameKind UseName)
899 : RemapEntry(EK_DirectoryRemap, Name, ExternalContentsPath, UseName) {}
900
901 static bool classof(const Entry *E) {
902 return E->getKind() == EK_DirectoryRemap;
903 }
904 };
905
906 /// A file in the vfs that maps to a file in the external file system.
907 class FileEntry : public RemapEntry {
908 public:
909 FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
910 : RemapEntry(EK_File, Name, ExternalContentsPath, UseName) {}
911
912 static bool classof(const Entry *E) { return E->getKind() == EK_File; }
913 };
914
915 /// Represents the result of a path lookup into the RedirectingFileSystem.
917 /// Chain of parent directory entries for \c E.
919
920 /// The entry the looked-up path corresponds to.
922
923 private:
924 /// When the found Entry is a DirectoryRemapEntry, stores the path in the
925 /// external file system that the looked-up path in the virtual file system
926 // corresponds to.
927 std::optional<std::string> ExternalRedirect;
928
929 public:
932
933 /// If the found Entry maps the input path to a path in the external
934 /// file system (i.e. it is a FileEntry or DirectoryRemapEntry), returns
935 /// that path.
936 std::optional<StringRef> getExternalRedirect() const {
937 if (isa<DirectoryRemapEntry>(E))
938 return StringRef(*ExternalRedirect);
939 if (auto *FE = dyn_cast<FileEntry>(E))
940 return FE->getExternalContentsPath();
941 return std::nullopt;
942 }
943
944 /// Get the (canonical) path of the found entry. This uses the as-written
945 /// path components from the VFS specification.
946 LLVM_ABI void getPath(llvm::SmallVectorImpl<char> &Path) const;
947 };
948
949private:
952
953 /// Canonicalize path by removing ".", "..", "./", components. This is
954 /// a VFS request, do not bother about symlinks in the path components
955 /// but canonicalize in order to perform the correct entry search.
956 std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const;
957
958 /// Get the File status, or error, from the underlying external file system.
959 /// This returns the status with the originally requested name, while looking
960 /// up the entry using a potentially different path.
961 ErrorOr<Status> getExternalStatus(const Twine &LookupPath,
962 const Twine &OriginalPath) const;
963
964 /// Make \a Path an absolute path.
965 ///
966 /// Makes \a Path absolute using the \a WorkingDir if it is not already.
967 ///
968 /// /absolute/path => /absolute/path
969 /// relative/../path => <WorkingDir>/relative/../path
970 ///
971 /// \param WorkingDir A path that will be used as the base Dir if \a Path
972 /// is not already absolute.
973 /// \param Path A path that is modified to be an absolute path.
974 /// \returns success if \a path has been made absolute, otherwise a
975 /// platform-specific error_code.
976 std::error_code makeAbsolute(StringRef WorkingDir,
977 SmallVectorImpl<char> &Path) const;
978
979 // In a RedirectingFileSystem, keys can be specified in Posix or Windows
980 // style (or even a mixture of both), so this comparison helper allows
981 // slashes (representing a root) to match backslashes (and vice versa). Note
982 // that, other than the root, path components should not contain slashes or
983 // backslashes.
984 bool pathComponentMatches(llvm::StringRef lhs, llvm::StringRef rhs) const {
985 if ((CaseSensitive ? lhs == rhs : lhs.equals_insensitive(rhs)))
986 return true;
987 return (lhs == "/" && rhs == "\\") || (lhs == "\\" && rhs == "/");
988 }
989
990 /// The root(s) of the virtual file system.
991 std::vector<std::unique_ptr<Entry>> Roots;
992
993 /// The current working directory of the file system.
994 std::string WorkingDirectory;
995
996 /// The file system to use for external references.
998
999 /// This represents the directory path that the YAML file is located.
1000 /// This will be prefixed to each 'external-contents' if IsRelativeOverlay
1001 /// is set. This will also be prefixed to each 'roots->name' if RootRelative
1002 /// is set to RootRelativeKind::OverlayDir and the path is relative.
1003 std::string OverlayFileDir;
1004
1005 /// @name Configuration
1006 /// @{
1007
1008 /// Whether to perform case-sensitive comparisons.
1009 ///
1010 /// Currently, case-insensitive matching only works correctly with ASCII.
1011 bool CaseSensitive = is_style_posix(sys::path::Style::native);
1012
1013 /// IsRelativeOverlay marks whether a OverlayFileDir path must
1014 /// be prefixed in every 'external-contents' when reading from YAML files.
1015 bool IsRelativeOverlay = false;
1016
1017 /// Whether to use to use the value of 'external-contents' for the
1018 /// names of files. This global value is overridable on a per-file basis.
1019 bool UseExternalNames = true;
1020
1021 /// True if this FS has redirected a lookup. This does not include
1022 /// fallthrough.
1023 mutable bool HasBeenUsed = false;
1024
1025 /// Used to enable or disable updating `HasBeenUsed`.
1026 bool UsageTrackingActive = false;
1027
1028 /// Determines the lookups to perform, as well as their order. See
1029 /// \c RedirectKind for details.
1030 RedirectKind Redirection = RedirectKind::Fallthrough;
1031
1032 /// Determine the prefix directory if the roots are relative paths. See
1033 /// \c RootRelativeKind for details.
1034 RootRelativeKind RootRelative = RootRelativeKind::CWD;
1035 /// @}
1036
1038
1039 // Explicitly non-copyable.
1041 RedirectingFileSystem &operator=(RedirectingFileSystem const &) = delete;
1042
1043 /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly recursing
1044 /// into the contents of \p From if it is a directory. Returns a LookupResult
1045 /// giving the matched entry and, if that entry is a FileEntry or
1046 /// DirectoryRemapEntry, the path it redirects to in the external file system.
1048 lookupPathImpl(llvm::sys::path::const_iterator Start,
1050 llvm::SmallVectorImpl<Entry *> &Entries) const;
1051
1052 /// Get the status for a path with the provided \c LookupResult.
1053 ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath,
1054 const LookupResult &Result);
1055
1056public:
1057 /// Looks up \p Path in \c Roots and returns a LookupResult giving the
1058 /// matched entry and, if the entry was a FileEntry or DirectoryRemapEntry,
1059 /// the path it redirects to in the external file system.
1060 ErrorOr<LookupResult> lookupPath(StringRef Path) const;
1061
1062 /// Parses \p Buffer, which is expected to be in YAML format and
1063 /// returns a virtual file system representing its contents.
1064 static std::unique_ptr<RedirectingFileSystem>
1065 create(std::unique_ptr<MemoryBuffer> Buffer,
1067 void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1068
1069 /// Redirect each of the remapped files from first to second.
1070 static std::unique_ptr<RedirectingFileSystem>
1071 create(ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1072 bool UseExternalNames, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1073
1074 ErrorOr<Status> status(const Twine &Path) override;
1075 bool exists(const Twine &Path) override;
1076 ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
1077
1078 std::error_code getRealPath(const Twine &Path,
1079 SmallVectorImpl<char> &Output) override;
1080
1081 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
1082
1083 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
1084
1085 std::error_code isLocal(const Twine &Path, bool &Result) override;
1086
1087 std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const override;
1088
1089 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
1090
1091 void setOverlayFileDir(StringRef PrefixDir);
1092
1093 StringRef getOverlayFileDir() const;
1094
1095 /// Sets the redirection kind to \c Fallthrough if true or \c RedirectOnly
1096 /// otherwise. Will removed in the future, use \c setRedirection instead.
1097 void setFallthrough(bool Fallthrough);
1098
1099 void setRedirection(RedirectingFileSystem::RedirectKind Kind);
1100
1101 std::vector<llvm::StringRef> getRoots() const;
1102
1103 bool hasBeenUsed() const { return HasBeenUsed; };
1104 void clearHasBeenUsed() { HasBeenUsed = false; }
1105
1106 void setUsageTrackingActive(bool Active) { UsageTrackingActive = Active; }
1107
1108 void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel = 0) const;
1109
1110protected:
1111 void printImpl(raw_ostream &OS, PrintType Type,
1112 unsigned IndentLevel) const override;
1113 void visitChildFileSystems(VisitCallbackTy Callback) override;
1114};
1115
1116/// Collect all pairs of <virtual path, real path> entries from the
1117/// \p YAMLFilePath. This is used by the module dependency collector to forward
1118/// the entries into the reproducer output VFS YAML file.
1120 std::unique_ptr<llvm::MemoryBuffer> Buffer,
1122 SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
1123 void *DiagContext = nullptr,
1125
1127 std::vector<YAMLVFSEntry> Mappings;
1128 std::optional<bool> IsCaseSensitive;
1129 std::optional<bool> IsOverlayRelative;
1130 std::optional<bool> UseExternalNames;
1131 std::string OverlayDir;
1132
1133 void addEntry(StringRef VirtualPath, StringRef RealPath, bool IsDirectory);
1134
1135public:
1136 YAMLVFSWriter() = default;
1137
1138 LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath);
1139 LLVM_ABI void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath);
1140
1141 void setCaseSensitivity(bool CaseSensitive) {
1142 IsCaseSensitive = CaseSensitive;
1143 }
1144
1145 void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
1146
1147 void setOverlayDir(StringRef OverlayDirectory) {
1148 IsOverlayRelative = true;
1149 OverlayDir.assign(OverlayDirectory.str());
1150 }
1151
1152 const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
1153
1155};
1156
1157/// File system that tracks the number of calls to the underlying file system.
1158/// This is particularly useful when wrapped around \c RealFileSystem to add
1159/// lightweight tracking of expensive syscalls.
1161 : public llvm::RTTIExtends<TracingFileSystem, ProxyFileSystem> {
1162public:
1163 static const char ID;
1164
1165 std::size_t NumStatusCalls = 0;
1166 std::size_t NumOpenFileForReadCalls = 0;
1167 std::size_t NumDirBeginCalls = 0;
1168 std::size_t NumGetRealPathCalls = 0;
1169 std::size_t NumExistsCalls = 0;
1170 std::size_t NumIsLocalCalls = 0;
1171
1173 : RTTIExtends(std::move(FS)) {}
1174
1175 ErrorOr<Status> status(const Twine &Path) override {
1176 ++NumStatusCalls;
1177 return ProxyFileSystem::status(Path);
1178 }
1179
1181 ++NumOpenFileForReadCalls;
1182 return ProxyFileSystem::openFileForRead(Path);
1183 }
1184
1185 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
1186 ++NumDirBeginCalls;
1187 return ProxyFileSystem::dir_begin(Dir, EC);
1188 }
1189
1190 std::error_code getRealPath(const Twine &Path,
1191 SmallVectorImpl<char> &Output) override {
1192 ++NumGetRealPathCalls;
1193 return ProxyFileSystem::getRealPath(Path, Output);
1194 }
1195
1196 bool exists(const Twine &Path) override {
1197 ++NumExistsCalls;
1198 return ProxyFileSystem::exists(Path);
1199 }
1200
1201 std::error_code isLocal(const Twine &Path, bool &Result) override {
1202 ++NumIsLocalCalls;
1203 return ProxyFileSystem::isLocal(Path, Result);
1204 }
1205
1206protected:
1207 void printImpl(raw_ostream &OS, PrintType Type,
1208 unsigned IndentLevel) const override;
1209};
1210
1211} // namespace vfs
1212} // namespace llvm
1213
1214#endif // LLVM_SUPPORT_VIRTUALFILESYSTEM_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-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
T Content
std::string Name
bool End
Definition: ELF_riscv.cpp:480
Provides ErrorOr<T> smart pointer.
static void makeAbsolute(SmallVectorImpl< char > &Path)
Make Path absolute.
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
#define I(x, y, z)
Definition: MD5.cpp:58
static const char * toString(MIToken::TokenKind TokenKind)
Definition: MIParser.cpp:624
#define T1
static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)
#define P(N)
raw_pwrite_stream & OS
This file defines the SmallVector class.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1059
Value * RHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
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...
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...
Definition: SmallVector.h:574
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: SmallVector.h:255
std::reverse_iterator< iterator > reverse_iterator
Definition: SmallVector.h:256
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:44
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:233
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition: StringRef.h:180
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
LLVM Value Representation.
Definition: Value.h:75
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.
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
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
static const char ID
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 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)
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
Represents an open file.
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.
An in-memory file system.
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
A file system that allows overlaying one AbstractFileSystem on top of another.
const_iterator overlays_end() const
const_iterator overlays_begin() const
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
reverse_iterator overlays_rend()
Get an iterator pointing one-past the most recently added file system.
FileSystemList::const_reverse_iterator const_iterator
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
const_reverse_iterator overlays_rbegin() const
FileSystemList::reverse_iterator iterator
By default, this delegates all calls to the underlying file system.
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.
A directory in the vfs with explicitly specified contents.
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)
A directory in the vfs that maps to a directory in the external file system.
DirectoryRemapEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
A single file or directory in the VFS.
Entry(EntryKind K, StringRef Name)
A file in the vfs that maps to a file in the external file system.
FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
A file or directory in the vfs that is mapped to a file or directory in the external filesystem.
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.
RedirectKind
The type of redirection to perform.
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 Status(const Twine &Name, llvm::sys::fs::UniqueID UID, llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group, uint64_t Size, llvm::sys::fs::file_type Type, llvm::sys::fs::perms Perms)
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.
File system that tracks the number of calls to the underlying file system.
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.
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
const directory_entry & operator*() const
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 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 void collectVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Collect all pairs of <virtual path, real path> entries from the YAMLFilePath.
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.
Definition: AddressRanges.h:18
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
errc
Definition: Errc.h:35
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:428
@ Other
Any other memory.
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:1886
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
Represents the result of a path lookup into the RedirectingFileSystem.
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::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