LLVM 24.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"
31#include <atomic>
32#include <cassert>
33#include <cstdint>
34#include <ctime>
35#include <memory>
36#include <optional>
37#include <string>
38#include <system_error>
39#include <utility>
40#include <vector>
41
42namespace llvm {
43
44class MemoryBuffer;
45class MemoryBufferRef;
46class Twine;
47
48namespace vfs {
49
50/// The result of a \p status operation.
51class Status {
52 std::string Name;
55 uint32_t User;
56 uint32_t Group;
57 uint64_t Size;
60
61public:
62 /// Whether this entity has an external path different from the virtual path,
63 /// and the external path is exposed by leaking it through the abstraction.
64 /// For example, a RedirectingFileSystem will set this for paths where
65 /// UseExternalName is true.
66 ///
67 /// FIXME: Currently the external path is exposed by replacing the virtual
68 /// path in this Status object. Instead, we should leave the path in the
69 /// Status intact (matching the requested virtual path) - see
70 /// FileManager::getFileRef for how we plan to fix this.
72
73 Status() = default;
76 llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
79
80 /// Get a copy of a Status with a different size.
81 LLVM_ABI static Status copyWithNewSize(const Status &In, uint64_t NewSize);
82 /// Get a copy of a Status with a different name.
83 LLVM_ABI static Status copyWithNewName(const Status &In,
84 const Twine &NewName);
86 const Twine &NewName);
87
88 /// Returns the name that should be used for this file or directory.
89 StringRef getName() const { return Name; }
90
91 /// @name Status interface from llvm::sys::fs
92 /// @{
93 llvm::sys::fs::file_type getType() const { return Type; }
94 llvm::sys::fs::perms getPermissions() const { return Perms; }
96 llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
97 uint32_t getUser() const { return User; }
98 uint32_t getGroup() const { return Group; }
99 uint64_t getSize() const { return Size; }
100 /// @}
101 /// @name Status queries
102 /// These are static queries in llvm::sys::fs.
103 /// @{
104 LLVM_ABI bool equivalent(const Status &Other) const;
105 LLVM_ABI bool isDirectory() const;
106 LLVM_ABI bool isRegularFile() const;
107 LLVM_ABI bool isOther() const;
108 LLVM_ABI bool isSymlink() const;
109 LLVM_ABI bool isStatusKnown() const;
110 LLVM_ABI bool exists() const;
111 /// @}
112};
113
114/// Represents an open file.
116public:
117 /// Destroy the file after closing it (if open).
118 /// Sub-classes should generally call close() inside their destructors. We
119 /// cannot do that from the base class, since close is virtual.
120 virtual ~File();
121
122 /// Get the status of the file.
124
125 /// Get the name of the file
127 if (auto Status = status())
128 return Status->getName().str();
129 else
130 return Status.getError();
131 }
132
133 /// Get the contents of the file as a \p MemoryBuffer.
135 getBuffer(const Twine &Name, int64_t FileSize = -1,
136 bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
137
138 /// Closes the file.
139 virtual std::error_code close() = 0;
140
141 // Get the same file with a different path.
143 getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P);
144
145protected:
146 // Set the file's underlying path.
147 virtual void setPath(const Twine &Path) {}
148};
149
150/// A member of a directory, yielded by a directory_iterator.
151/// Only information available on most platforms is included.
153 std::string Path;
155
156public:
157 directory_entry() = default;
159 : Path(std::move(Path)), Type(Type) {}
160
161 llvm::StringRef path() const { return Path; }
162 llvm::sys::fs::file_type type() const { return Type; }
163};
164
165namespace detail {
166
167/// An interface for virtual file systems to provide an iterator over the
168/// (non-recursive) contents of a directory.
170 virtual ~DirIterImpl();
171
172 /// Sets \c CurrentEntry to the next entry in the directory on success,
173 /// to directory_entry() at end, or returns a system-defined \c error_code.
174 virtual std::error_code increment() = 0;
175
177};
178
179} // namespace detail
180
181/// An input iterator over the entries in a virtual path, similar to
182/// llvm::sys::fs::directory_iterator.
184 std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
185
186public:
187 directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
188 : Impl(std::move(I)) {
189 assert(Impl.get() != nullptr && "requires non-null implementation");
190 if (Impl->CurrentEntry.path().empty())
191 Impl.reset(); // Normalize the end iterator to Impl == nullptr.
192 }
193
194 /// Construct an 'end' iterator.
196
197 /// Equivalent to operator++, with an error code.
198 directory_iterator &increment(std::error_code &EC) {
199 assert(Impl && "attempting to increment past end");
200 EC = Impl->increment();
201 if (Impl->CurrentEntry.path().empty())
202 Impl.reset(); // Normalize the end iterator to Impl == nullptr.
203 return *this;
204 }
205
206 const directory_entry &operator*() const { return Impl->CurrentEntry; }
207 const directory_entry *operator->() const { return &Impl->CurrentEntry; }
208
209 bool operator==(const directory_iterator &RHS) const {
210 if (Impl && RHS.Impl)
211 return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path();
212 return !Impl && !RHS.Impl;
213 }
214 bool operator!=(const directory_iterator &RHS) const {
215 return !(*this == RHS);
216 }
217};
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 /// Collect the paths in the real file system that contribute to a potentially
318 /// virtual directory when iterated via \a dir_begin. This can be used for
319 /// directory watching.
320 ///
321 /// Only paths that are OS-level visible are returned, so in memory and other
322 /// such entirely virtual filesystems contribute no paths.
323 virtual void
326
327 /// Check whether \p Path exists. By default this uses \c status(), but
328 /// filesystems may provide a more efficient implementation if available.
329 virtual bool exists(const Twine &Path);
330
331 /// Is the file mounted on a local filesystem?
332 virtual std::error_code isLocal(const Twine &Path, bool &Result);
333
334 /// Make \a Path an absolute path.
335 ///
336 /// Makes \a Path absolute using the current directory if it is not already.
337 /// An empty \a Path will result in the current directory.
338 ///
339 /// /absolute/path => /absolute/path
340 /// relative/../path => <current-directory>/relative/../path
341 ///
342 /// \param Path A path that is modified to be an absolute path.
343 /// \returns success if \a path has been made absolute, otherwise a
344 /// platform-specific error_code.
345 virtual std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
346
347 /// \returns true if \p A and \p B represent the same file, or an error or
348 /// false if they do not.
349 llvm::ErrorOr<bool> equivalent(const Twine &A, const Twine &B);
350
353 unsigned IndentLevel = 0) const {
354 printImpl(OS, Type, IndentLevel);
355 }
356
358 virtual void visitChildFileSystems(VisitCallbackTy Callback) {}
359 void visit(VisitCallbackTy Callback) {
360 Callback(*this);
361 visitChildFileSystems(Callback);
362 }
363
364#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
365 LLVM_DUMP_METHOD void dump() const;
366#endif
367
368protected:
370 unsigned IndentLevel) const {
371 printIndent(OS, IndentLevel);
372 OS << "FileSystem\n";
373 }
374
375 void printIndent(raw_ostream &OS, unsigned IndentLevel) const {
376 for (unsigned i = 0; i < IndentLevel; ++i)
377 OS << " ";
378 }
379};
380
381/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
382/// the operating system.
383/// The working directory is linked to the process's working directory.
384/// (This is usually thread-hostile).
385/// This may only be called outside the IO sandbox.
387
388/// Create an \p vfs::FileSystem for the 'real' file system, as seen by
389/// the operating system.
390/// It has its own working directory, independent of (but initially equal to)
391/// that of the process.
392/// This may only be called outside the IO sandbox.
393LLVM_ABI std::unique_ptr<FileSystem> createPhysicalFileSystem();
394
395/// A file system that allows overlaying one \p AbstractFileSystem on top
396/// of another.
397///
398/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
399/// one merged file system. When there is a directory that exists in more than
400/// one file system, the \p OverlayFileSystem contains a directory containing
401/// the union of their contents. The attributes (permissions, etc.) of the
402/// top-most (most recently added) directory are used. When there is a file
403/// that exists in more than one file system, the file in the top-most file
404/// system overrides the other(s).
406 : public RTTIExtends<OverlayFileSystem, FileSystem> {
407 using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>;
408
409 /// The stack of file systems, implemented as a list in order of
410 /// their addition.
411 FileSystemList FSList;
412
413public:
414 static const char ID;
416
417 /// Pushes a file system on top of the stack.
419
420 llvm::ErrorOr<Status> status(const Twine &Path) override;
421 bool exists(const Twine &Path) override;
423 openFileForRead(const Twine &Path) override;
424 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
426 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
427 std::error_code isLocal(const Twine &Path, bool &Result) override;
428 std::error_code getRealPath(const Twine &Path,
429 SmallVectorImpl<char> &Output) override;
430 void
432 SmallVectorImpl<std::string> &Out) override;
433
440
441 /// Get an iterator pointing to the most recently added file system.
442 iterator overlays_begin() { return FSList.rbegin(); }
443 const_iterator overlays_begin() const { return FSList.rbegin(); }
444
445 /// Get an iterator pointing one-past the least recently added file system.
446 iterator overlays_end() { return FSList.rend(); }
447 const_iterator overlays_end() const { return FSList.rend(); }
448
449 /// Get an iterator pointing to the least recently added file system.
450 reverse_iterator overlays_rbegin() { return FSList.begin(); }
451 const_reverse_iterator overlays_rbegin() const { return FSList.begin(); }
452
453 /// Get an iterator pointing one-past the most recently added file system.
454 reverse_iterator overlays_rend() { return FSList.end(); }
455 const_reverse_iterator overlays_rend() const { return FSList.end(); }
456
457 range overlays_range() { return llvm::reverse(FSList); }
458 const_range overlays_range() const { return llvm::reverse(FSList); }
459
460protected:
461 void printImpl(raw_ostream &OS, PrintType Type,
462 unsigned IndentLevel) const override;
463 void visitChildFileSystems(VisitCallbackTy Callback) override;
464};
465
466/// By default, this delegates all calls to the underlying file system. This
467/// is useful when derived file systems want to override some calls and still
468/// proxy other calls.
470 : public RTTIExtends<ProxyFileSystem, FileSystem> {
471public:
472 static const char ID;
475
476 llvm::ErrorOr<Status> status(const Twine &Path) override {
477 return FS->status(Path);
478 }
479 bool exists(const Twine &Path) override { return FS->exists(Path); }
481 openFileForRead(const Twine &Path) override {
482 return FS->openFileForRead(Path);
483 }
484 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
485 return FS->dir_begin(Dir, EC);
486 }
488 return FS->getCurrentWorkingDirectory();
489 }
490 std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
491 return FS->setCurrentWorkingDirectory(Path);
492 }
493 std::error_code getRealPath(const Twine &Path,
494 SmallVectorImpl<char> &Output) override {
495 return FS->getRealPath(Path, Output);
496 }
497 void
499 SmallVectorImpl<std::string> &Out) override {
500 return FS->getDirectoryContentRealSources(Dir, Out);
501 }
502 std::error_code isLocal(const Twine &Path, bool &Result) override {
503 return FS->isLocal(Path, Result);
504 }
505
506protected:
507 FileSystem &getUnderlyingFS() const { return *FS; }
508 void visitChildFileSystems(VisitCallbackTy Callback) override {
509 if (FS) {
510 Callback(*FS);
511 FS->visitChildFileSystems(Callback);
512 }
513 }
514
515private:
517
518 void anchor() override;
519};
520
521namespace detail {
522
523class InMemoryDirectory;
524class InMemoryNode;
525
539
542 Value;
543
544public:
547 : Value(std::make_pair(Name, Node)) {}
548 NamedNodeOrError(std::error_code EC) : Value(EC) {}
549 NamedNodeOrError(llvm::errc EC) : Value(EC) {}
550
551 StringRef getName() const { return (*Value).first; }
552 explicit operator bool() const { return static_cast<bool>(Value); }
553 operator std::error_code() const { return Value.getError(); }
554 std::error_code getError() const { return Value.getError(); }
555 const detail::InMemoryNode *operator*() const { return (*Value).second; }
556};
557
558} // namespace detail
559
560/// An in-memory file system.
562 : public RTTIExtends<InMemoryFileSystem, FileSystem> {
563 std::unique_ptr<detail::InMemoryDirectory> Root;
564 std::string WorkingDirectory;
565 bool UseNormalizedPaths = true;
566
567public:
568 static const char ID;
569
570private:
573
574 /// Create node with \p MakeNode and add it into this filesystem at \p Path.
575 bool addFile(const Twine &Path, time_t ModificationTime,
576 std::unique_ptr<llvm::MemoryBuffer> Buffer,
577 std::optional<uint32_t> User, std::optional<uint32_t> Group,
578 std::optional<llvm::sys::fs::file_type> Type,
579 std::optional<llvm::sys::fs::perms> Perms, MakeNodeFn MakeNode);
580
581 /// Looks up the in-memory node for the path \p P.
582 /// If \p FollowFinalSymlink is true, the returned node is guaranteed to
583 /// not be a symlink and its path may differ from \p P.
584 detail::NamedNodeOrError lookupNode(const Twine &P, bool FollowFinalSymlink,
585 size_t SymlinkDepth = 0) const;
586
587 class DirIterator;
588
589public:
590 explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
592
593 /// Add a file containing a buffer or a directory to the VFS with a
594 /// path. The VFS owns the buffer. If present, User, Group, Type
595 /// and Perms apply to the newly-created file or directory.
596 /// \return true if the file or directory was successfully added,
597 /// false if the file or directory already exists in the file system with
598 /// different contents.
599 bool addFile(const Twine &Path, time_t ModificationTime,
600 std::unique_ptr<llvm::MemoryBuffer> Buffer,
601 std::optional<uint32_t> User = std::nullopt,
602 std::optional<uint32_t> Group = std::nullopt,
603 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
604 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
605
606 /// Add a hard link to a file.
607 ///
608 /// Here hard links are not intended to be fully equivalent to the classical
609 /// filesystem. Both the hard link and the file share the same buffer and
610 /// status (and thus have the same UniqueID). Because of this there is no way
611 /// to distinguish between the link and the file after the link has been
612 /// added.
613 ///
614 /// The \p Target path must be an existing file or a hardlink. The
615 /// \p NewLink file must not have been added before. The \p Target
616 /// path must not be a directory. The \p NewLink node is added as a hard
617 /// link which points to the resolved file of \p Target node.
618 /// \return true if the above condition is satisfied and hardlink was
619 /// successfully created, false otherwise.
620 bool addHardLink(const Twine &NewLink, const Twine &Target);
621
622 /// Arbitrary max depth to search through symlinks. We can get into problems
623 /// if a link links to a link that links back to the link, for example.
624 static constexpr size_t MaxSymlinkDepth = 16;
625
626 /// Add a symbolic link. Unlike a HardLink, because \p Target doesn't need
627 /// to refer to a file (or refer to anything, as it happens). Also, an
628 /// in-memory directory for \p Target isn't automatically created.
629 bool
630 addSymbolicLink(const Twine &NewLink, const Twine &Target,
631 time_t ModificationTime,
632 std::optional<uint32_t> User = std::nullopt,
633 std::optional<uint32_t> Group = std::nullopt,
634 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
635
636 /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
637 /// If present, User, Group, Type and Perms apply to the newly-created file
638 /// or directory.
639 /// \return true if the file or directory was successfully added,
640 /// false if the file or directory already exists in the file system with
641 /// different contents.
642 bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
643 const llvm::MemoryBufferRef &Buffer,
644 std::optional<uint32_t> User = std::nullopt,
645 std::optional<uint32_t> Group = std::nullopt,
646 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
647 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
648
649 std::string toString() const;
650
651 /// Return true if this file system normalizes . and .. in paths.
652 bool useNormalizedPaths() const { return UseNormalizedPaths; }
653
654 llvm::ErrorOr<Status> status(const Twine &Path) override;
656 openFileForRead(const Twine &Path) override;
657 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
658
660 return WorkingDirectory;
661 }
662 /// Canonicalizes \p Path by combining with the current working
663 /// directory and normalizing the path (e.g. remove dots). If the current
664 /// working directory is not set, this returns errc::operation_not_permitted.
665 ///
666 /// This doesn't resolve symlinks as they are not supported in in-memory file
667 /// system.
668 std::error_code getRealPath(const Twine &Path,
669 SmallVectorImpl<char> &Output) override;
670 std::error_code isLocal(const Twine &Path, bool &Result) override;
671 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
672
673protected:
674 void printImpl(raw_ostream &OS, PrintType Type,
675 unsigned IndentLevel) const override;
676};
677
678/// Get a globally unique ID for a virtual file or directory.
680
681/// Gets a \p FileSystem for a virtual file system described in YAML
682/// format.
683LLVM_ABI std::unique_ptr<FileSystem>
684getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
686 StringRef YAMLFilePath, void *DiagContext = nullptr,
688
690 template <typename T1, typename T2>
691 YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory = false)
692 : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)),
694 std::string VPath;
695 std::string RPath;
696 bool IsDirectory = false;
697};
698
701
702/// A virtual file system parsed from a YAML file.
703///
704/// Currently, this class allows creating virtual files and directories. Virtual
705/// files map to existing external files in \c ExternalFS, and virtual
706/// directories may either map to existing directories in \c ExternalFS or list
707/// their contents in the form of other virtual directories and/or files.
708///
709/// The basic structure of the parsed file is:
710/// \verbatim
711/// {
712/// 'version': <version number>,
713/// <optional configuration>
714/// 'roots': [
715/// <directory entries>
716/// ]
717/// }
718/// \endverbatim
719/// The roots may be absolute or relative. If relative they will be made
720/// absolute against either current working directory or the directory where
721/// the Overlay YAML file is located, depending on the 'root-relative'
722/// configuration.
723///
724/// All configuration options are optional.
725/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
726/// 'use-external-names': <boolean, default=true>
727/// 'root-relative': <string, one of 'cwd' or 'overlay-dir', default='cwd'>
728/// 'overlay-relative': <boolean, default=false>
729/// 'fallthrough': <boolean, default=true, deprecated - use 'redirecting-with'
730/// instead>
731/// 'redirecting-with': <string, one of 'fallthrough', 'fallback', or
732/// 'redirect-only', default='fallthrough'>
733///
734/// To clarify, 'root-relative' option will prepend the current working
735/// directory, or the overlay directory to the 'roots->name' field only if
736/// 'roots->name' is a relative path. On the other hand, when 'overlay-relative'
737/// is set to 'true', external paths will always be prepended with the overlay
738/// directory, even if external paths are not relative paths. The
739/// 'root-relative' option has no interaction with the 'overlay-relative'
740/// option.
741///
742/// Virtual directories that list their contents are represented as
743/// \verbatim
744/// {
745/// 'type': 'directory',
746/// 'name': <string>,
747/// 'contents': [ <file or directory entries> ]
748/// }
749/// \endverbatim
750/// The default attributes for such virtual directories are:
751/// \verbatim
752/// MTime = now() when created
753/// Perms = 0777
754/// User = Group = 0
755/// Size = 0
756/// UniqueID = unspecified unique value
757/// \endverbatim
758/// When a path prefix matches such a directory, the next component in the path
759/// is matched against the entries in the 'contents' array.
760///
761/// Re-mapped directories, on the other hand, are represented as
762/// /// \verbatim
763/// {
764/// 'type': 'directory-remap',
765/// 'name': <string>,
766/// 'use-external-name': <boolean>, # Optional
767/// 'external-contents': <path to external directory>
768/// }
769/// \endverbatim
770/// and inherit their attributes from the external directory. When a path
771/// prefix matches such an entry, the unmatched components are appended to the
772/// 'external-contents' path, and the resulting path is looked up in the
773/// external file system instead.
774///
775/// Re-mapped files are represented as
776/// \verbatim
777/// {
778/// 'type': 'file',
779/// 'name': <string>,
780/// 'use-external-name': <boolean>, # Optional
781/// 'external-contents': <path to external file>
782/// }
783/// \endverbatim
784/// Their attributes and file contents are determined by looking up the file at
785/// their 'external-contents' path in the external file system.
786///
787/// For 'file', 'directory' and 'directory-remap' entries the 'name' field may
788/// contain multiple path components (e.g. /path/to/file). However, any
789/// directory in such a path that contains more than one child must be uniquely
790/// represented by a 'directory' entry.
791///
792/// When the 'use-external-name' field is set, calls to \a vfs::File::status()
793/// give the external (remapped) filesystem name instead of the name the file
794/// was accessed by. This is an intentional leak through the \a
795/// RedirectingFileSystem abstraction layer. It enables clients to discover
796/// (and use) the external file location when communicating with users or tools
797/// that don't use the same VFS overlay.
798///
799/// FIXME: 'use-external-name' causes behaviour that's inconsistent with how
800/// "real" filesystems behave. Maybe there should be a separate channel for
801/// this information.
802class LLVM_ABI RedirectingFileSystem
803 : public RTTIExtends<RedirectingFileSystem, vfs::FileSystem> {
804public:
805 static const char ID;
808
809 /// The type of redirection to perform.
810 enum class RedirectKind {
811 /// Lookup the redirected path first (ie. the one specified in
812 /// 'external-contents') and if that fails "fallthrough" to a lookup of the
813 /// originally provided path.
815 /// Lookup the provided path first and if that fails, "fallback" to a
816 /// lookup of the redirected path.
818 /// Only lookup the redirected path, do not lookup the originally provided
819 /// path.
821 };
822
823 /// The type of relative path used by Roots.
824 enum class RootRelativeKind {
825 /// The roots are relative to the current working directory.
827 /// The roots are relative to the directory where the Overlay YAML file
828 // locates.
830 };
831
832 /// A single file or directory in the VFS.
833 class Entry {
834 EntryKind Kind;
835 std::string Name;
836
837 public:
838 Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
839 virtual ~Entry() = default;
840
841 StringRef getName() const { return Name; }
842 EntryKind getKind() const { return Kind; }
843 };
844
845 /// A directory in the vfs with explicitly specified contents.
846 class DirectoryEntry : public Entry {
847 std::vector<std::unique_ptr<Entry>> Contents;
848 Status S;
849
850 public:
851 /// Constructs a directory entry with explicitly specified contents.
852 DirectoryEntry(StringRef Name, std::vector<std::unique_ptr<Entry>> Contents,
853 Status S)
854 : Entry(EK_Directory, Name), Contents(std::move(Contents)),
855 S(std::move(S)) {}
856
857 /// Constructs an empty directory entry.
859 : Entry(EK_Directory, Name), S(std::move(S)) {}
860
861 Status getStatus() { return S; }
862
863 void addContent(std::unique_ptr<Entry> Content) {
864 Contents.push_back(std::move(Content));
865 }
866
867 Entry *getLastContent() const { return Contents.back().get(); }
868
869 using iterator = decltype(Contents)::iterator;
870
871 iterator contents_begin() { return Contents.begin(); }
872 iterator contents_end() { return Contents.end(); }
873
874 static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
875 };
876
877 /// A file or directory in the vfs that is mapped to a file or directory in
878 /// the external filesystem.
879 class RemapEntry : public Entry {
880 std::string ExternalContentsPath;
881 NameKind UseName;
882
883 protected:
884 RemapEntry(EntryKind K, StringRef Name, StringRef ExternalContentsPath,
885 NameKind UseName)
886 : Entry(K, Name), ExternalContentsPath(ExternalContentsPath),
887 UseName(UseName) {}
888
889 public:
890 StringRef getExternalContentsPath() const { return ExternalContentsPath; }
891
892 /// Whether to use the external path as the name for this file or directory.
893 bool useExternalName(bool GlobalUseExternalName) const {
894 return UseName == NK_NotSet ? GlobalUseExternalName
895 : (UseName == NK_External);
896 }
897
898 NameKind getUseName() const { return UseName; }
899
900 static bool classof(const Entry *E) {
901 switch (E->getKind()) {
903 [[fallthrough]];
904 case EK_File:
905 return true;
906 case EK_Directory:
907 return false;
908 }
909 llvm_unreachable("invalid entry kind");
910 }
911 };
912
913 /// A directory in the vfs that maps to a directory in the external file
914 /// system.
916 public:
917 DirectoryRemapEntry(StringRef Name, StringRef ExternalContentsPath,
918 NameKind UseName)
919 : RemapEntry(EK_DirectoryRemap, Name, ExternalContentsPath, UseName) {}
920
921 static bool classof(const Entry *E) {
922 return E->getKind() == EK_DirectoryRemap;
923 }
924 };
925
926 /// A file in the vfs that maps to a file in the external file system.
927 class FileEntry : public RemapEntry {
928 public:
929 FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
930 : RemapEntry(EK_File, Name, ExternalContentsPath, UseName) {}
931
932 static bool classof(const Entry *E) { return E->getKind() == EK_File; }
933 };
934
935 /// Represents the result of a path lookup into the RedirectingFileSystem.
937 /// Chain of parent directory entries for \c E.
939
940 /// The entry the looked-up path corresponds to.
942
943 private:
944 /// When the found Entry is a DirectoryRemapEntry, stores the path in the
945 /// external file system that the looked-up path in the virtual file system
946 // corresponds to.
947 std::optional<std::string> ExternalRedirect;
948
949 public:
952
953 /// If the found Entry maps the input path to a path in the external
954 /// file system (i.e. it is a FileEntry or DirectoryRemapEntry), returns
955 /// that path.
956 std::optional<StringRef> getExternalRedirect() const {
958 return StringRef(*ExternalRedirect);
959 if (auto *FE = dyn_cast<FileEntry>(E))
960 return FE->getExternalContentsPath();
961 return std::nullopt;
962 }
963
964 /// Get the (canonical) path of the found entry. This uses the as-written
965 /// path components from the VFS specification.
966 LLVM_ABI void getPath(llvm::SmallVectorImpl<char> &Path) const;
967 };
968
969private:
972
973 /// Canonicalize path by removing ".", "..", "./", components. This is
974 /// a VFS request, do not bother about symlinks in the path components
975 /// but canonicalize in order to perform the correct entry search.
976 std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const;
977
978 /// Get the File status, or error, from the underlying external file system.
979 /// This returns the status with the originally requested name, while looking
980 /// up the entry using a potentially different path.
981 ErrorOr<Status> getExternalStatus(const Twine &LookupPath,
982 const Twine &OriginalPath) const;
983
984 /// Make \a Path an absolute path.
985 ///
986 /// Makes \a Path absolute using the \a WorkingDir if it is not already.
987 ///
988 /// /absolute/path => /absolute/path
989 /// relative/../path => <WorkingDir>/relative/../path
990 ///
991 /// \param WorkingDir A path that will be used as the base Dir if \a Path
992 /// is not already absolute.
993 /// \param Path A path that is modified to be an absolute path.
994 /// \returns success if \a path has been made absolute, otherwise a
995 /// platform-specific error_code.
996 std::error_code makeAbsolute(StringRef WorkingDir,
997 SmallVectorImpl<char> &Path) const;
998
999 // In a RedirectingFileSystem, keys can be specified in Posix or Windows
1000 // style (or even a mixture of both), so this comparison helper allows
1001 // slashes (representing a root) to match backslashes (and vice versa). Note
1002 // that, other than the root, path components should not contain slashes or
1003 // backslashes.
1004 bool pathComponentMatches(llvm::StringRef lhs, llvm::StringRef rhs) const {
1005 if ((CaseSensitive ? lhs == rhs : lhs.equals_insensitive(rhs)))
1006 return true;
1007 return (lhs == "/" && rhs == "\\") || (lhs == "\\" && rhs == "/");
1008 }
1009
1010 /// The root(s) of the virtual file system.
1011 std::vector<std::unique_ptr<Entry>> Roots;
1012
1013 /// The current working directory of the file system.
1014 std::string WorkingDirectory;
1015
1016 /// The file system to use for external references.
1018
1019 /// This represents the directory path that the YAML file is located.
1020 /// This will be prefixed to each 'external-contents' if IsRelativeOverlay
1021 /// is set. This will also be prefixed to each 'roots->name' if RootRelative
1022 /// is set to RootRelativeKind::OverlayDir and the path is relative.
1023 std::string OverlayFileDir;
1024
1025 /// @name Configuration
1026 /// @{
1027
1028 /// Whether to perform case-sensitive comparisons.
1029 ///
1030 /// Currently, case-insensitive matching only works correctly with ASCII.
1031 bool CaseSensitive = is_style_posix(sys::path::Style::native);
1032
1033 /// IsRelativeOverlay marks whether a OverlayFileDir path must
1034 /// be prefixed in every 'external-contents' when reading from YAML files.
1035 bool IsRelativeOverlay = false;
1036
1037 /// Whether to use to use the value of 'external-contents' for the
1038 /// names of files. This global value is overridable on a per-file basis.
1039 bool UseExternalNames = true;
1040
1041 /// True if this FS has redirected a lookup. This does not include
1042 /// fallthrough.
1043 mutable bool HasBeenUsed = false;
1044
1045 /// Used to enable or disable updating `HasBeenUsed`.
1046 bool UsageTrackingActive = false;
1047
1048 /// Determines the lookups to perform, as well as their order. See
1049 /// \c RedirectKind for details.
1050 RedirectKind Redirection = RedirectKind::Fallthrough;
1051
1052 /// Determine the prefix directory if the roots are relative paths. See
1053 /// \c RootRelativeKind for details.
1054 RootRelativeKind RootRelative = RootRelativeKind::CWD;
1055 /// @}
1056
1058
1059 // Explicitly non-copyable.
1061 RedirectingFileSystem &operator=(RedirectingFileSystem const &) = delete;
1062
1063 /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly recursing
1064 /// into the contents of \p From if it is a directory. Returns a LookupResult
1065 /// giving the matched entry and, if that entry is a FileEntry or
1066 /// DirectoryRemapEntry, the path it redirects to in the external file system.
1068 lookupPathImpl(llvm::sys::path::const_iterator Start,
1069 llvm::sys::path::const_iterator End, Entry *From,
1070 llvm::SmallVectorImpl<Entry *> &Entries) const;
1071
1072 /// Get the status for a path with the provided \c LookupResult.
1073 ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath,
1074 const LookupResult &Result);
1075
1076public:
1077 /// Looks up \p Path in \c Roots and returns a LookupResult giving the
1078 /// matched entry and, if the entry was a FileEntry or DirectoryRemapEntry,
1079 /// the path it redirects to in the external file system.
1080 ErrorOr<LookupResult> lookupPath(StringRef Path) const;
1081
1082 /// Parses \p Buffer, which is expected to be in YAML format and
1083 /// returns a virtual file system representing its contents.
1084 static std::unique_ptr<RedirectingFileSystem>
1085 create(std::unique_ptr<MemoryBuffer> Buffer,
1087 void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1088
1089 /// Redirect each of the remapped files from first to second.
1090 static std::unique_ptr<RedirectingFileSystem>
1091 create(ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1092 bool UseExternalNames, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1093
1094 ErrorOr<Status> status(const Twine &Path) override;
1095 bool exists(const Twine &Path) override;
1096 ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
1097
1098 std::error_code getRealPath(const Twine &Path,
1099 SmallVectorImpl<char> &Output) override;
1100
1101 void
1102 getDirectoryContentRealSources(const Twine &Dir,
1103 SmallVectorImpl<std::string> &Out) override;
1104
1105 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
1106
1107 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
1108
1109 std::error_code isLocal(const Twine &Path, bool &Result) override;
1110
1111 std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const override;
1112
1113 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
1114
1115 void setOverlayFileDir(StringRef PrefixDir);
1116
1117 StringRef getOverlayFileDir() const;
1118
1119 /// Sets the redirection kind to \c Fallthrough if true or \c RedirectOnly
1120 /// otherwise. Will removed in the future, use \c setRedirection instead.
1121 void setFallthrough(bool Fallthrough);
1122
1123 void setRedirection(RedirectingFileSystem::RedirectKind Kind);
1124
1125 std::vector<llvm::StringRef> getRoots() const;
1126
1127 bool hasBeenUsed() const { return HasBeenUsed; };
1128 void clearHasBeenUsed() { HasBeenUsed = false; }
1129
1130 void setUsageTrackingActive(bool Active) { UsageTrackingActive = Active; }
1131
1132 void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel = 0) const;
1133
1134protected:
1135 void printImpl(raw_ostream &OS, PrintType Type,
1136 unsigned IndentLevel) const override;
1137 void visitChildFileSystems(VisitCallbackTy Callback) override;
1138};
1139
1140/// Collect all pairs of <virtual path, real path> entries from the
1141/// \p VFS. This is used by the module dependency collector to forward
1142/// the entries into the reproducer output VFS YAML file.
1143LLVM_ABI void
1144collectVFSEntries(RedirectingFileSystem &VFS,
1145 SmallVectorImpl<YAMLVFSEntry> &CollectedEntries);
1146
1148 std::vector<YAMLVFSEntry> Mappings;
1149 std::optional<bool> IsCaseSensitive;
1150 std::optional<bool> IsOverlayRelative;
1151 std::optional<bool> UseExternalNames;
1152 std::string OverlayDir;
1153
1154 void addEntry(StringRef VirtualPath, StringRef RealPath, bool IsDirectory);
1155
1156public:
1157 YAMLVFSWriter() = default;
1158
1159 LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath);
1160 LLVM_ABI void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath);
1161
1162 void setCaseSensitivity(bool CaseSensitive) {
1163 IsCaseSensitive = CaseSensitive;
1164 }
1165
1166 void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
1167
1168 void setOverlayDir(StringRef OverlayDirectory) {
1169 IsOverlayRelative = true;
1170 OverlayDir.assign(OverlayDirectory.str());
1171 }
1172
1173 const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
1174
1176};
1177
1178/// File system that tracks the number of calls to the underlying file system.
1179/// This is particularly useful when wrapped around \c RealFileSystem to add
1180/// lightweight tracking of expensive syscalls.
1181///
1182/// Templated on the counter type so callers can choose between non-atomic
1183/// counters (suitable for single-threaded tracing) and atomic counters
1184/// (suitable for tracing under concurrent access). Use the
1185/// \c TracingFileSystem and \c AtomicTracingFileSystem aliases below.
1186template <typename CounterT>
1188 : public llvm::RTTIExtends<TracingFileSystemImpl<CounterT>,
1189 ProxyFileSystem> {
1190public:
1191 inline static const char ID = 0;
1192
1193 CounterT NumStatusCalls = 0;
1195 CounterT NumDirBeginCalls = 0;
1197 CounterT NumExistsCalls = 0;
1198 CounterT NumIsLocalCalls = 0;
1199
1203
1204 ErrorOr<Status> status(const Twine &Path) override {
1206 return ProxyFileSystem::status(Path);
1207 }
1208
1213
1214 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
1216 return ProxyFileSystem::dir_begin(Dir, EC);
1217 }
1218
1219 std::error_code getRealPath(const Twine &Path,
1220 SmallVectorImpl<char> &Output) override {
1222 return ProxyFileSystem::getRealPath(Path, Output);
1223 }
1224
1225 bool exists(const Twine &Path) override {
1227 return ProxyFileSystem::exists(Path);
1228 }
1229
1230 std::error_code isLocal(const Twine &Path, bool &Result) override {
1232 return ProxyFileSystem::isLocal(Path, Result);
1233 }
1234
1235protected:
1237 unsigned IndentLevel) const override {
1238 FileSystem::printIndent(OS, IndentLevel);
1239 OS << "TracingFileSystem\n";
1241 return;
1242
1243 FileSystem::printIndent(OS, IndentLevel);
1244 OS << "NumStatusCalls=" << static_cast<std::size_t>(NumStatusCalls) << "\n";
1245 FileSystem::printIndent(OS, IndentLevel);
1246 OS << "NumOpenFileForReadCalls="
1247 << static_cast<std::size_t>(NumOpenFileForReadCalls) << "\n";
1248 FileSystem::printIndent(OS, IndentLevel);
1249 OS << "NumDirBeginCalls=" << static_cast<std::size_t>(NumDirBeginCalls)
1250 << "\n";
1251 FileSystem::printIndent(OS, IndentLevel);
1252 OS << "NumGetRealPathCalls="
1253 << static_cast<std::size_t>(NumGetRealPathCalls) << "\n";
1254 FileSystem::printIndent(OS, IndentLevel);
1255 OS << "NumExistsCalls=" << static_cast<std::size_t>(NumExistsCalls) << "\n";
1256 FileSystem::printIndent(OS, IndentLevel);
1257 OS << "NumIsLocalCalls=" << static_cast<std::size_t>(NumIsLocalCalls)
1258 << "\n";
1259
1262 this->getUnderlyingFS().print(OS, Type, IndentLevel + 1);
1263 }
1264};
1265
1266/// Single-threaded tracing filesystem. Counters are plain \c std::size_t and
1267/// must not be incremented concurrently.
1269
1270/// Concurrent-safe tracing filesystem. Counters are \c std::atomic<std::size_t>
1271/// so the proxy can be shared across threads.
1273
1274} // namespace vfs
1275} // namespace llvm
1276
1277#endif // LLVM_SUPPORT_VIRTUALFILESYSTEM_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
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:215
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:686
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:608
#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)
Contains the forward declaration for vfs::FileSystem, as well as the IntrusiveRefCntPtrInfo specializ...
Value * RHS
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:46
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition StringRef.h:170
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:46
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:214
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 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 void getDirectoryContentRealSources(const Twine &Dir, SmallVectorImpl< std::string > &Out)
Collect the paths in the real file system that contribute to a potentially virtual directory when ite...
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)
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
void getDirectoryContentRealSources(const Twine &Dir, SmallVectorImpl< std::string > &Out) 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
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)
void getDirectoryContentRealSources(const Twine &Dir, SmallVectorImpl< std::string > &Out) override
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.
File system that tracks the number of calls to the underlying file system.
void printImpl(raw_ostream &OS, FileSystem::PrintType Type, unsigned IndentLevel) const override
TracingFileSystemImpl(llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
std::error_code isLocal(const Twine &Path, bool &Result) override
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
bool exists(const Twine &Path) override
ErrorOr< Status > status(const Twine &Path) 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:54
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition Chrono.h:34
TracingFileSystemImpl< std::atomic< std::size_t > > AtomicTracingFileSystem
Concurrent-safe tracing filesystem.
TracingFileSystemImpl< std::size_t > TracingFileSystem
Single-threaded tracing filesystem.
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:408
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:1933
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
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