LLVM 19.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"
22#include "llvm/Support/Errc.h"
23#include "llvm/Support/Error.h"
27#include "llvm/Support/Path.h"
29#include <cassert>
30#include <cstdint>
31#include <ctime>
32#include <memory>
33#include <optional>
34#include <stack>
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 static Status copyWithNewSize(const Status &In, uint64_t NewSize);
80 /// Get a copy of a Status with a different name.
81 static Status copyWithNewName(const Status &In, const Twine &NewName);
83 const Twine &NewName);
84
85 /// Returns the name that should be used for this file or directory.
86 StringRef getName() const { return Name; }
87
88 /// @name Status interface from llvm::sys::fs
89 /// @{
91 llvm::sys::fs::perms getPermissions() const { return Perms; }
93 llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
94 uint32_t getUser() const { return User; }
95 uint32_t getGroup() const { return Group; }
96 uint64_t getSize() const { return Size; }
97 /// @}
98 /// @name Status queries
99 /// These are static queries in llvm::sys::fs.
100 /// @{
101 bool equivalent(const Status &Other) const;
102 bool isDirectory() const;
103 bool isRegularFile() const;
104 bool isOther() const;
105 bool isSymlink() const;
106 bool isStatusKnown() const;
107 bool exists() const;
108 /// @}
109};
110
111/// Represents an open file.
112class File {
113public:
114 /// Destroy the file after closing it (if open).
115 /// Sub-classes should generally call close() inside their destructors. We
116 /// cannot do that from the base class, since close is virtual.
117 virtual ~File();
118
119 /// Get the status of the file.
121
122 /// Get the name of the file
124 if (auto Status = status())
125 return Status->getName().str();
126 else
127 return Status.getError();
128 }
129
130 /// Get the contents of the file as a \p MemoryBuffer.
132 getBuffer(const Twine &Name, int64_t FileSize = -1,
133 bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
134
135 /// Closes the file.
136 virtual std::error_code close() = 0;
137
138 // Get the same file with a different path.
140 getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P);
141
142protected:
143 // Set the file's underlying path.
144 virtual void setPath(const Twine &Path) {}
145};
146
147/// A member of a directory, yielded by a directory_iterator.
148/// Only information available on most platforms is included.
150 std::string Path;
152
153public:
154 directory_entry() = default;
156 : Path(std::move(Path)), Type(Type) {}
157
158 llvm::StringRef path() const { return Path; }
160};
161
162namespace detail {
163
164/// An interface for virtual file systems to provide an iterator over the
165/// (non-recursive) contents of a directory.
167 virtual ~DirIterImpl();
168
169 /// Sets \c CurrentEntry to the next entry in the directory on success,
170 /// to directory_entry() at end, or returns a system-defined \c error_code.
171 virtual std::error_code increment() = 0;
172
174};
175
176} // namespace detail
177
178/// An input iterator over the entries in a virtual path, similar to
179/// llvm::sys::fs::directory_iterator.
181 std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
182
183public:
184 directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
185 : Impl(std::move(I)) {
186 assert(Impl.get() != nullptr && "requires non-null implementation");
187 if (Impl->CurrentEntry.path().empty())
188 Impl.reset(); // Normalize the end iterator to Impl == nullptr.
189 }
190
191 /// Construct an 'end' iterator.
193
194 /// Equivalent to operator++, with an error code.
195 directory_iterator &increment(std::error_code &EC) {
196 assert(Impl && "attempting to increment past end");
197 EC = Impl->increment();
198 if (Impl->CurrentEntry.path().empty())
199 Impl.reset(); // Normalize the end iterator to Impl == nullptr.
200 return *this;
201 }
202
203 const directory_entry &operator*() const { return Impl->CurrentEntry; }
204 const directory_entry *operator->() const { return &Impl->CurrentEntry; }
205
206 bool operator==(const directory_iterator &RHS) const {
207 if (Impl && RHS.Impl)
208 return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path();
209 return !Impl && !RHS.Impl;
210 }
211 bool operator!=(const directory_iterator &RHS) const {
212 return !(*this == RHS);
213 }
214};
215
216class FileSystem;
217
218namespace detail {
219
220/// Keeps state for the recursive_directory_iterator.
222 std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
223 bool HasNoPushRequest = false;
224};
225
226} // end namespace detail
227
228/// An input iterator over the recursive contents of a virtual path,
229/// similar to llvm::sys::fs::recursive_directory_iterator.
231 FileSystem *FS;
232 std::shared_ptr<detail::RecDirIterState>
233 State; // Input iterator semantics on copy.
234
235public:
237 std::error_code &EC);
238
239 /// Construct an 'end' iterator.
241
242 /// Equivalent to operator++, with an error code.
243 recursive_directory_iterator &increment(std::error_code &EC);
244
245 const directory_entry &operator*() const { return *State->Stack.top(); }
246 const directory_entry *operator->() const { return &*State->Stack.top(); }
247
249 return State == Other.State; // identity
250 }
252 return !(*this == RHS);
253 }
254
255 /// Gets the current level. Starting path is at level 0.
256 int level() const {
257 assert(!State->Stack.empty() &&
258 "Cannot get level without any iteration state");
259 return State->Stack.size() - 1;
260 }
261
262 void no_push() { State->HasNoPushRequest = true; }
263};
264
265/// The virtual file system interface.
267 public RTTIExtends<FileSystem, RTTIRoot> {
268public:
269 static const char ID;
270 virtual ~FileSystem();
271
272 /// Get the status of the entry at \p Path, if one exists.
273 virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
274
275 /// Get a \p File object for the file at \p Path, if one exists.
277 openFileForRead(const Twine &Path) = 0;
278
279 /// This is a convenience method that opens a file, gets its content and then
280 /// closes the file.
282 getBufferForFile(const Twine &Name, int64_t FileSize = -1,
283 bool RequiresNullTerminator = true, bool IsVolatile = false);
284
285 /// Get a directory_iterator for \p Dir.
286 /// \note The 'end' iterator is directory_iterator().
288 std::error_code &EC) = 0;
289
290 /// Set the working directory. This will affect all following operations on
291 /// this file system and may propagate down for nested file systems.
292 virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
293
294 /// Get the working directory of this file system.
296
297 /// Gets real path of \p Path e.g. collapse all . and .. patterns, resolve
298 /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`.
299 /// This returns errc::operation_not_permitted if not implemented by subclass.
300 virtual std::error_code getRealPath(const Twine &Path,
301 SmallVectorImpl<char> &Output);
302
303 /// Check whether \p Path exists. By default this uses \c status(), but
304 /// filesystems may provide a more efficient implementation if available.
305 virtual bool exists(const Twine &Path);
306
307 /// Is the file mounted on a local filesystem?
308 virtual std::error_code isLocal(const Twine &Path, bool &Result);
309
310 /// Make \a Path an absolute path.
311 ///
312 /// Makes \a Path absolute using the current directory if it is not already.
313 /// An empty \a Path will result in the current directory.
314 ///
315 /// /absolute/path => /absolute/path
316 /// relative/../path => <current-directory>/relative/../path
317 ///
318 /// \param Path A path that is modified to be an absolute path.
319 /// \returns success if \a path has been made absolute, otherwise a
320 /// platform-specific error_code.
321 virtual std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
322
323 /// \returns true if \p A and \p B represent the same file, or an error or
324 /// false if they do not.
326
329 unsigned IndentLevel = 0) const {
330 printImpl(OS, Type, IndentLevel);
331 }
332
334 virtual void visitChildFileSystems(VisitCallbackTy Callback) {}
335 void visit(VisitCallbackTy Callback) {
336 Callback(*this);
337 visitChildFileSystems(Callback);
338 }
339
340#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
341 LLVM_DUMP_METHOD void dump() const;
342#endif
343
344protected:
346 unsigned IndentLevel) const {
347 printIndent(OS, IndentLevel);
348 OS << "FileSystem\n";
349 }
350
351 void printIndent(raw_ostream &OS, unsigned IndentLevel) const {
352 for (unsigned i = 0; i < IndentLevel; ++i)
353 OS << " ";
354 }
355};
356
357/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
358/// the operating system.
359/// The working directory is linked to the process's working directory.
360/// (This is usually thread-hostile).
362
363/// Create an \p vfs::FileSystem for the 'real' file system, as seen by
364/// the operating system.
365/// It has its own working directory, independent of (but initially equal to)
366/// that of the process.
367std::unique_ptr<FileSystem> createPhysicalFileSystem();
368
369/// A file system that allows overlaying one \p AbstractFileSystem on top
370/// of another.
371///
372/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
373/// one merged file system. When there is a directory that exists in more than
374/// one file system, the \p OverlayFileSystem contains a directory containing
375/// the union of their contents. The attributes (permissions, etc.) of the
376/// top-most (most recently added) directory are used. When there is a file
377/// that exists in more than one file system, the file in the top-most file
378/// system overrides the other(s).
379class OverlayFileSystem : public RTTIExtends<OverlayFileSystem, FileSystem> {
381
382 /// The stack of file systems, implemented as a list in order of
383 /// their addition.
384 FileSystemList FSList;
385
386public:
387 static const char ID;
389
390 /// Pushes a file system on top of the stack.
392
393 llvm::ErrorOr<Status> status(const Twine &Path) override;
394 bool exists(const Twine &Path) override;
396 openFileForRead(const Twine &Path) override;
397 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
399 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
400 std::error_code isLocal(const Twine &Path, bool &Result) override;
401 std::error_code getRealPath(const Twine &Path,
402 SmallVectorImpl<char> &Output) override;
403
410
411 /// Get an iterator pointing to the most recently added file system.
412 iterator overlays_begin() { return FSList.rbegin(); }
413 const_iterator overlays_begin() const { return FSList.rbegin(); }
414
415 /// Get an iterator pointing one-past the least recently added file system.
416 iterator overlays_end() { return FSList.rend(); }
417 const_iterator overlays_end() const { return FSList.rend(); }
418
419 /// Get an iterator pointing to the least recently added file system.
421 const_reverse_iterator overlays_rbegin() const { return FSList.begin(); }
422
423 /// Get an iterator pointing one-past the most recently added file system.
424 reverse_iterator overlays_rend() { return FSList.end(); }
425 const_reverse_iterator overlays_rend() const { return FSList.end(); }
426
427 range overlays_range() { return llvm::reverse(FSList); }
428 const_range overlays_range() const { return llvm::reverse(FSList); }
429
430protected:
431 void printImpl(raw_ostream &OS, PrintType Type,
432 unsigned IndentLevel) const override;
433 void visitChildFileSystems(VisitCallbackTy Callback) override;
434};
435
436/// By default, this delegates all calls to the underlying file system. This
437/// is useful when derived file systems want to override some calls and still
438/// proxy other calls.
439class ProxyFileSystem : public RTTIExtends<ProxyFileSystem, FileSystem> {
440public:
441 static const char ID;
443 : FS(std::move(FS)) {}
444
445 llvm::ErrorOr<Status> status(const Twine &Path) override {
446 return FS->status(Path);
447 }
448 bool exists(const Twine &Path) override { return FS->exists(Path); }
450 openFileForRead(const Twine &Path) override {
451 return FS->openFileForRead(Path);
452 }
453 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
454 return FS->dir_begin(Dir, EC);
455 }
457 return FS->getCurrentWorkingDirectory();
458 }
459 std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
460 return FS->setCurrentWorkingDirectory(Path);
461 }
462 std::error_code getRealPath(const Twine &Path,
463 SmallVectorImpl<char> &Output) override {
464 return FS->getRealPath(Path, Output);
465 }
466 std::error_code isLocal(const Twine &Path, bool &Result) override {
467 return FS->isLocal(Path, Result);
468 }
469
470protected:
471 FileSystem &getUnderlyingFS() const { return *FS; }
472 void visitChildFileSystems(VisitCallbackTy Callback) override {
473 if (FS) {
474 Callback(*FS);
475 FS->visitChildFileSystems(Callback);
476 }
477 }
478
479private:
481
482 virtual void anchor() override;
483};
484
485namespace detail {
486
487class InMemoryDirectory;
488class InMemoryNode;
489
495 std::unique_ptr<llvm::MemoryBuffer> Buffer;
500
501 Status makeStatus() const;
502};
503
506 Value;
507
508public:
511 : Value(std::make_pair(Name, Node)) {}
512 NamedNodeOrError(std::error_code EC) : Value(EC) {}
514
515 StringRef getName() const { return (*Value).first; }
516 explicit operator bool() const { return static_cast<bool>(Value); }
517 operator std::error_code() const { return Value.getError(); }
518 std::error_code getError() const { return Value.getError(); }
519 const detail::InMemoryNode *operator*() const { return (*Value).second; }
520};
521
522} // namespace detail
523
524/// An in-memory file system.
525class InMemoryFileSystem : public RTTIExtends<InMemoryFileSystem, FileSystem> {
526 std::unique_ptr<detail::InMemoryDirectory> Root;
527 std::string WorkingDirectory;
528 bool UseNormalizedPaths = true;
529
530public:
531 static const char ID;
532
533private:
536
537 /// Create node with \p MakeNode and add it into this filesystem at \p Path.
538 bool addFile(const Twine &Path, time_t ModificationTime,
539 std::unique_ptr<llvm::MemoryBuffer> Buffer,
540 std::optional<uint32_t> User, std::optional<uint32_t> Group,
541 std::optional<llvm::sys::fs::file_type> Type,
542 std::optional<llvm::sys::fs::perms> Perms, MakeNodeFn MakeNode);
543
544 /// Looks up the in-memory node for the path \p P.
545 /// If \p FollowFinalSymlink is true, the returned node is guaranteed to
546 /// not be a symlink and its path may differ from \p P.
547 detail::NamedNodeOrError lookupNode(const Twine &P, bool FollowFinalSymlink,
548 size_t SymlinkDepth = 0) const;
549
550 class DirIterator;
551
552public:
553 explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
555
556 /// Add a file containing a buffer or a directory to the VFS with a
557 /// path. The VFS owns the buffer. If present, User, Group, Type
558 /// and Perms apply to the newly-created file or directory.
559 /// \return true if the file or directory was successfully added,
560 /// false if the file or directory already exists in the file system with
561 /// different contents.
562 bool addFile(const Twine &Path, time_t ModificationTime,
563 std::unique_ptr<llvm::MemoryBuffer> Buffer,
564 std::optional<uint32_t> User = std::nullopt,
565 std::optional<uint32_t> Group = std::nullopt,
566 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
567 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
568
569 /// Add a hard link to a file.
570 ///
571 /// Here hard links are not intended to be fully equivalent to the classical
572 /// filesystem. Both the hard link and the file share the same buffer and
573 /// status (and thus have the same UniqueID). Because of this there is no way
574 /// to distinguish between the link and the file after the link has been
575 /// added.
576 ///
577 /// The \p Target path must be an existing file or a hardlink. The
578 /// \p NewLink file must not have been added before. The \p Target
579 /// path must not be a directory. The \p NewLink node is added as a hard
580 /// link which points to the resolved file of \p Target node.
581 /// \return true if the above condition is satisfied and hardlink was
582 /// successfully created, false otherwise.
583 bool addHardLink(const Twine &NewLink, const Twine &Target);
584
585 /// Arbitrary max depth to search through symlinks. We can get into problems
586 /// if a link links to a link that links back to the link, for example.
587 static constexpr size_t MaxSymlinkDepth = 16;
588
589 /// Add a symbolic link. Unlike a HardLink, because \p Target doesn't need
590 /// to refer to a file (or refer to anything, as it happens). Also, an
591 /// in-memory directory for \p Target isn't automatically created.
592 bool
593 addSymbolicLink(const Twine &NewLink, const Twine &Target,
594 time_t ModificationTime,
595 std::optional<uint32_t> User = std::nullopt,
596 std::optional<uint32_t> Group = std::nullopt,
597 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
598
599 /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
600 /// If present, User, Group, Type and Perms apply to the newly-created file
601 /// or directory.
602 /// \return true if the file or directory was successfully added,
603 /// false if the file or directory already exists in the file system with
604 /// different contents.
605 bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
606 const llvm::MemoryBufferRef &Buffer,
607 std::optional<uint32_t> User = std::nullopt,
608 std::optional<uint32_t> Group = std::nullopt,
609 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
610 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
611
612 std::string toString() const;
613
614 /// Return true if this file system normalizes . and .. in paths.
615 bool useNormalizedPaths() const { return UseNormalizedPaths; }
616
617 llvm::ErrorOr<Status> status(const Twine &Path) override;
619 openFileForRead(const Twine &Path) override;
620 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
621
623 return WorkingDirectory;
624 }
625 /// Canonicalizes \p Path by combining with the current working
626 /// directory and normalizing the path (e.g. remove dots). If the current
627 /// working directory is not set, this returns errc::operation_not_permitted.
628 ///
629 /// This doesn't resolve symlinks as they are not supported in in-memory file
630 /// system.
631 std::error_code getRealPath(const Twine &Path,
632 SmallVectorImpl<char> &Output) override;
633 std::error_code isLocal(const Twine &Path, bool &Result) override;
634 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
635
636protected:
637 void printImpl(raw_ostream &OS, PrintType Type,
638 unsigned IndentLevel) const override;
639};
640
641/// Get a globally unique ID for a virtual file or directory.
643
644/// Gets a \p FileSystem for a virtual file system described in YAML
645/// format.
646std::unique_ptr<FileSystem>
647getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
649 StringRef YAMLFilePath, void *DiagContext = nullptr,
651
653 template <typename T1, typename T2>
654 YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory = false)
655 : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)),
657 std::string VPath;
658 std::string RPath;
659 bool IsDirectory = false;
660};
661
664
665/// A virtual file system parsed from a YAML file.
666///
667/// Currently, this class allows creating virtual files and directories. Virtual
668/// files map to existing external files in \c ExternalFS, and virtual
669/// directories may either map to existing directories in \c ExternalFS or list
670/// their contents in the form of other virtual directories and/or files.
671///
672/// The basic structure of the parsed file is:
673/// \verbatim
674/// {
675/// 'version': <version number>,
676/// <optional configuration>
677/// 'roots': [
678/// <directory entries>
679/// ]
680/// }
681/// \endverbatim
682/// The roots may be absolute or relative. If relative they will be made
683/// absolute against either current working directory or the directory where
684/// the Overlay YAML file is located, depending on the 'root-relative'
685/// configuration.
686///
687/// All configuration options are optional.
688/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
689/// 'use-external-names': <boolean, default=true>
690/// 'root-relative': <string, one of 'cwd' or 'overlay-dir', default='cwd'>
691/// 'overlay-relative': <boolean, default=false>
692/// 'fallthrough': <boolean, default=true, deprecated - use 'redirecting-with'
693/// instead>
694/// 'redirecting-with': <string, one of 'fallthrough', 'fallback', or
695/// 'redirect-only', default='fallthrough'>
696///
697/// To clarify, 'root-relative' option will prepend the current working
698/// directory, or the overlay directory to the 'roots->name' field only if
699/// 'roots->name' is a relative path. On the other hand, when 'overlay-relative'
700/// is set to 'true', external paths will always be prepended with the overlay
701/// directory, even if external paths are not relative paths. The
702/// 'root-relative' option has no interaction with the 'overlay-relative'
703/// option.
704///
705/// Virtual directories that list their contents are represented as
706/// \verbatim
707/// {
708/// 'type': 'directory',
709/// 'name': <string>,
710/// 'contents': [ <file or directory entries> ]
711/// }
712/// \endverbatim
713/// The default attributes for such virtual directories are:
714/// \verbatim
715/// MTime = now() when created
716/// Perms = 0777
717/// User = Group = 0
718/// Size = 0
719/// UniqueID = unspecified unique value
720/// \endverbatim
721/// When a path prefix matches such a directory, the next component in the path
722/// is matched against the entries in the 'contents' array.
723///
724/// Re-mapped directories, on the other hand, are represented as
725/// /// \verbatim
726/// {
727/// 'type': 'directory-remap',
728/// 'name': <string>,
729/// 'use-external-name': <boolean>, # Optional
730/// 'external-contents': <path to external directory>
731/// }
732/// \endverbatim
733/// and inherit their attributes from the external directory. When a path
734/// prefix matches such an entry, the unmatched components are appended to the
735/// 'external-contents' path, and the resulting path is looked up in the
736/// external file system instead.
737///
738/// Re-mapped files are represented as
739/// \verbatim
740/// {
741/// 'type': 'file',
742/// 'name': <string>,
743/// 'use-external-name': <boolean>, # Optional
744/// 'external-contents': <path to external file>
745/// }
746/// \endverbatim
747/// Their attributes and file contents are determined by looking up the file at
748/// their 'external-contents' path in the external file system.
749///
750/// For 'file', 'directory' and 'directory-remap' entries the 'name' field may
751/// contain multiple path components (e.g. /path/to/file). However, any
752/// directory in such a path that contains more than one child must be uniquely
753/// represented by a 'directory' entry.
754///
755/// When the 'use-external-name' field is set, calls to \a vfs::File::status()
756/// give the external (remapped) filesystem name instead of the name the file
757/// was accessed by. This is an intentional leak through the \a
758/// RedirectingFileSystem abstraction layer. It enables clients to discover
759/// (and use) the external file location when communicating with users or tools
760/// that don't use the same VFS overlay.
761///
762/// FIXME: 'use-external-name' causes behaviour that's inconsistent with how
763/// "real" filesystems behave. Maybe there should be a separate channel for
764/// this information.
766 : public RTTIExtends<RedirectingFileSystem, vfs::FileSystem> {
767public:
768 static const char ID;
771
772 /// The type of redirection to perform.
773 enum class RedirectKind {
774 /// Lookup the redirected path first (ie. the one specified in
775 /// 'external-contents') and if that fails "fallthrough" to a lookup of the
776 /// originally provided path.
778 /// Lookup the provided path first and if that fails, "fallback" to a
779 /// lookup of the redirected path.
780 Fallback,
781 /// Only lookup the redirected path, do not lookup the originally provided
782 /// path.
784 };
785
786 /// The type of relative path used by Roots.
787 enum class RootRelativeKind {
788 /// The roots are relative to the current working directory.
789 CWD,
790 /// The roots are relative to the directory where the Overlay YAML file
791 // locates.
793 };
794
795 /// A single file or directory in the VFS.
796 class Entry {
797 EntryKind Kind;
798 std::string Name;
799
800 public:
801 Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
802 virtual ~Entry() = default;
803
804 StringRef getName() const { return Name; }
805 EntryKind getKind() const { return Kind; }
806 };
807
808 /// A directory in the vfs with explicitly specified contents.
809 class DirectoryEntry : public Entry {
810 std::vector<std::unique_ptr<Entry>> Contents;
811 Status S;
812
813 public:
814 /// Constructs a directory entry with explicitly specified contents.
815 DirectoryEntry(StringRef Name, std::vector<std::unique_ptr<Entry>> Contents,
816 Status S)
817 : Entry(EK_Directory, Name), Contents(std::move(Contents)),
818 S(std::move(S)) {}
819
820 /// Constructs an empty directory entry.
822 : Entry(EK_Directory, Name), S(std::move(S)) {}
823
824 Status getStatus() { return S; }
825
826 void addContent(std::unique_ptr<Entry> Content) {
827 Contents.push_back(std::move(Content));
828 }
829
830 Entry *getLastContent() const { return Contents.back().get(); }
831
832 using iterator = decltype(Contents)::iterator;
833
834 iterator contents_begin() { return Contents.begin(); }
835 iterator contents_end() { return Contents.end(); }
836
837 static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
838 };
839
840 /// A file or directory in the vfs that is mapped to a file or directory in
841 /// the external filesystem.
842 class RemapEntry : public Entry {
843 std::string ExternalContentsPath;
844 NameKind UseName;
845
846 protected:
847 RemapEntry(EntryKind K, StringRef Name, StringRef ExternalContentsPath,
848 NameKind UseName)
849 : Entry(K, Name), ExternalContentsPath(ExternalContentsPath),
850 UseName(UseName) {}
851
852 public:
853 StringRef getExternalContentsPath() const { return ExternalContentsPath; }
854
855 /// Whether to use the external path as the name for this file or directory.
856 bool useExternalName(bool GlobalUseExternalName) const {
857 return UseName == NK_NotSet ? GlobalUseExternalName
858 : (UseName == NK_External);
859 }
860
861 NameKind getUseName() const { return UseName; }
862
863 static bool classof(const Entry *E) {
864 switch (E->getKind()) {
866 [[fallthrough]];
867 case EK_File:
868 return true;
869 case EK_Directory:
870 return false;
871 }
872 llvm_unreachable("invalid entry kind");
873 }
874 };
875
876 /// A directory in the vfs that maps to a directory in the external file
877 /// system.
879 public:
880 DirectoryRemapEntry(StringRef Name, StringRef ExternalContentsPath,
881 NameKind UseName)
882 : RemapEntry(EK_DirectoryRemap, Name, ExternalContentsPath, UseName) {}
883
884 static bool classof(const Entry *E) {
885 return E->getKind() == EK_DirectoryRemap;
886 }
887 };
888
889 /// A file in the vfs that maps to a file in the external file system.
890 class FileEntry : public RemapEntry {
891 public:
892 FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
893 : RemapEntry(EK_File, Name, ExternalContentsPath, UseName) {}
894
895 static bool classof(const Entry *E) { return E->getKind() == EK_File; }
896 };
897
898 /// Represents the result of a path lookup into the RedirectingFileSystem.
900 /// Chain of parent directory entries for \c E.
902
903 /// The entry the looked-up path corresponds to.
905
906 private:
907 /// When the found Entry is a DirectoryRemapEntry, stores the path in the
908 /// external file system that the looked-up path in the virtual file system
909 // corresponds to.
910 std::optional<std::string> ExternalRedirect;
911
912 public:
915
916 /// If the found Entry maps the input path to a path in the external
917 /// file system (i.e. it is a FileEntry or DirectoryRemapEntry), returns
918 /// that path.
919 std::optional<StringRef> getExternalRedirect() const {
920 if (isa<DirectoryRemapEntry>(E))
921 return StringRef(*ExternalRedirect);
922 if (auto *FE = dyn_cast<FileEntry>(E))
923 return FE->getExternalContentsPath();
924 return std::nullopt;
925 }
926
927 /// Get the (canonical) path of the found entry. This uses the as-written
928 /// path components from the VFS specification.
929 void getPath(llvm::SmallVectorImpl<char> &Path) const;
930 };
931
932private:
935
936 /// Canonicalize path by removing ".", "..", "./", components. This is
937 /// a VFS request, do not bother about symlinks in the path components
938 /// but canonicalize in order to perform the correct entry search.
939 std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const;
940
941 /// Get the File status, or error, from the underlying external file system.
942 /// This returns the status with the originally requested name, while looking
943 /// up the entry using a potentially different path.
944 ErrorOr<Status> getExternalStatus(const Twine &LookupPath,
945 const Twine &OriginalPath) const;
946
947 /// Make \a Path an absolute path.
948 ///
949 /// Makes \a Path absolute using the \a WorkingDir if it is not already.
950 ///
951 /// /absolute/path => /absolute/path
952 /// relative/../path => <WorkingDir>/relative/../path
953 ///
954 /// \param WorkingDir A path that will be used as the base Dir if \a Path
955 /// is not already absolute.
956 /// \param Path A path that is modified to be an absolute path.
957 /// \returns success if \a path has been made absolute, otherwise a
958 /// platform-specific error_code.
959 std::error_code makeAbsolute(StringRef WorkingDir,
960 SmallVectorImpl<char> &Path) const;
961
962 // In a RedirectingFileSystem, keys can be specified in Posix or Windows
963 // style (or even a mixture of both), so this comparison helper allows
964 // slashes (representing a root) to match backslashes (and vice versa). Note
965 // that, other than the root, path components should not contain slashes or
966 // backslashes.
967 bool pathComponentMatches(llvm::StringRef lhs, llvm::StringRef rhs) const {
968 if ((CaseSensitive ? lhs == rhs : lhs.equals_insensitive(rhs)))
969 return true;
970 return (lhs == "/" && rhs == "\\") || (lhs == "\\" && rhs == "/");
971 }
972
973 /// The root(s) of the virtual file system.
974 std::vector<std::unique_ptr<Entry>> Roots;
975
976 /// The current working directory of the file system.
977 std::string WorkingDirectory;
978
979 /// The file system to use for external references.
981
982 /// This represents the directory path that the YAML file is located.
983 /// This will be prefixed to each 'external-contents' if IsRelativeOverlay
984 /// is set. This will also be prefixed to each 'roots->name' if RootRelative
985 /// is set to RootRelativeKind::OverlayDir and the path is relative.
986 std::string OverlayFileDir;
987
988 /// @name Configuration
989 /// @{
990
991 /// Whether to perform case-sensitive comparisons.
992 ///
993 /// Currently, case-insensitive matching only works correctly with ASCII.
994 bool CaseSensitive = is_style_posix(sys::path::Style::native);
995
996 /// IsRelativeOverlay marks whether a OverlayFileDir path must
997 /// be prefixed in every 'external-contents' when reading from YAML files.
998 bool IsRelativeOverlay = false;
999
1000 /// Whether to use to use the value of 'external-contents' for the
1001 /// names of files. This global value is overridable on a per-file basis.
1002 bool UseExternalNames = true;
1003
1004 /// True if this FS has redirected a lookup. This does not include
1005 /// fallthrough.
1006 mutable bool HasBeenUsed = false;
1007
1008 /// Used to enable or disable updating `HasBeenUsed`.
1009 bool UsageTrackingActive = false;
1010
1011 /// Determines the lookups to perform, as well as their order. See
1012 /// \c RedirectKind for details.
1014
1015 /// Determine the prefix directory if the roots are relative paths. See
1016 /// \c RootRelativeKind for details.
1018 /// @}
1019
1021
1022 /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly recursing
1023 /// into the contents of \p From if it is a directory. Returns a LookupResult
1024 /// giving the matched entry and, if that entry is a FileEntry or
1025 /// DirectoryRemapEntry, the path it redirects to in the external file system.
1027 lookupPathImpl(llvm::sys::path::const_iterator Start,
1029 llvm::SmallVectorImpl<Entry *> &Entries) const;
1030
1031 /// Get the status for a path with the provided \c LookupResult.
1032 ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath,
1033 const LookupResult &Result);
1034
1035public:
1036 /// Looks up \p Path in \c Roots and returns a LookupResult giving the
1037 /// matched entry and, if the entry was a FileEntry or DirectoryRemapEntry,
1038 /// the path it redirects to in the external file system.
1040
1041 /// Parses \p Buffer, which is expected to be in YAML format and
1042 /// returns a virtual file system representing its contents.
1043 static std::unique_ptr<RedirectingFileSystem>
1044 create(std::unique_ptr<MemoryBuffer> Buffer,
1046 void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1047
1048 /// Redirect each of the remapped files from first to second.
1049 static std::unique_ptr<RedirectingFileSystem>
1050 create(ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1051 bool UseExternalNames, FileSystem &ExternalFS);
1052
1053 ErrorOr<Status> status(const Twine &Path) override;
1054 bool exists(const Twine &Path) override;
1056
1057 std::error_code getRealPath(const Twine &Path,
1058 SmallVectorImpl<char> &Output) override;
1059
1061
1062 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
1063
1064 std::error_code isLocal(const Twine &Path, bool &Result) override;
1065
1066 std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const override;
1067
1068 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
1069
1070 void setOverlayFileDir(StringRef PrefixDir);
1071
1073
1074 /// Sets the redirection kind to \c Fallthrough if true or \c RedirectOnly
1075 /// otherwise. Will removed in the future, use \c setRedirection instead.
1076 void setFallthrough(bool Fallthrough);
1077
1079
1080 std::vector<llvm::StringRef> getRoots() const;
1081
1082 bool hasBeenUsed() const { return HasBeenUsed; };
1083 void clearHasBeenUsed() { HasBeenUsed = false; }
1084
1085 void setUsageTrackingActive(bool Active) { UsageTrackingActive = Active; }
1086
1087 void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel = 0) const;
1088
1089protected:
1091 unsigned IndentLevel) const override;
1092 void visitChildFileSystems(VisitCallbackTy Callback) override;
1093};
1094
1095/// Collect all pairs of <virtual path, real path> entries from the
1096/// \p YAMLFilePath. This is used by the module dependency collector to forward
1097/// the entries into the reproducer output VFS YAML file.
1099 std::unique_ptr<llvm::MemoryBuffer> Buffer,
1101 SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
1102 void *DiagContext = nullptr,
1104
1106 std::vector<YAMLVFSEntry> Mappings;
1107 std::optional<bool> IsCaseSensitive;
1108 std::optional<bool> IsOverlayRelative;
1109 std::optional<bool> UseExternalNames;
1110 std::string OverlayDir;
1111
1112 void addEntry(StringRef VirtualPath, StringRef RealPath, bool IsDirectory);
1113
1114public:
1115 YAMLVFSWriter() = default;
1116
1117 void addFileMapping(StringRef VirtualPath, StringRef RealPath);
1118 void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath);
1119
1120 void setCaseSensitivity(bool CaseSensitive) {
1121 IsCaseSensitive = CaseSensitive;
1122 }
1123
1124 void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
1125
1126 void setOverlayDir(StringRef OverlayDirectory) {
1127 IsOverlayRelative = true;
1128 OverlayDir.assign(OverlayDirectory.str());
1129 }
1130
1131 const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
1132
1133 void write(llvm::raw_ostream &OS);
1134};
1135
1136} // namespace vfs
1137} // namespace llvm
1138
1139#endif // LLVM_SUPPORT_VIRTUALFILESYSTEM_H
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_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:537
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
#define T1
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallVector class.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1060
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:586
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: SmallVector.h:267
std::reverse_iterator< iterator > reverse_iterator
Definition: SmallVector.h:268
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:43
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::string str() const
str - 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:81
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:74
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:52
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:226
The virtual file system interface.
llvm::function_ref< void(FileSystem &)> VisitCallbackTy
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
virtual bool exists(const Twine &Path)
Check whether Path exists.
virtual std::error_code setCurrentWorkingDirectory(const Twine &Path)=0
Set the working directory.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
This is a convenience method that opens a file, gets its content and then closes the file.
virtual void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
static const char ID
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0
Get a File object for the 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
LLVM_DUMP_METHOD void dump() const
void print(raw_ostream &OS, PrintType Type=PrintType::Contents, unsigned IndentLevel=0) const
virtual void visitChildFileSystems(VisitCallbackTy Callback)
void visit(VisitCallbackTy Callback)
llvm::ErrorOr< bool > equivalent(const Twine &A, const Twine &B)
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
Represents an open file.
static ErrorOr< std::unique_ptr< File > > getWithPath(ErrorOr< std::unique_ptr< File > > Result, const Twine &P)
virtual llvm::ErrorOr< Status > status()=0
Get the status of the file.
virtual llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBuffer(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)=0
Get the contents of the file as a MemoryBuffer.
virtual llvm::ErrorOr< std::string > getName()
Get the name of the file.
virtual void setPath(const Twine &Path)
virtual ~File()
Destroy the file after closing it (if open).
virtual std::error_code close()=0
Closes the file.
Adaptor from InMemoryDir::iterator to directory_iterator.
An in-memory file system.
std::error_code isLocal(const Twine &Path, bool &Result) override
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Canonicalizes Path by combining with the current working directory and normalizing the path (e....
static constexpr size_t MaxSymlinkDepth
Arbitrary max depth to search through symlinks.
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
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.
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
llvm::ErrorOr< Status > status(const Twine &Path) override
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
A file system that allows overlaying one AbstractFileSystem on top of another.
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
void visitChildFileSystems(VisitCallbackTy Callback) override
const_reverse_iterator overlays_rend() const
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
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
std::error_code isLocal(const Twine &Path, bool &Result) override
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.
const_reverse_iterator overlays_rbegin() const
FileSystemList::reverse_iterator iterator
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
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.
@ OverlayDir
The roots are relative to the directory where the Overlay YAML file.
@ CWD
The roots are relative to the current working directory.
bool exists(const Twine &Path) override
Check whether Path exists.
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
std::vector< llvm::StringRef > getRoots() const
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
ErrorOr< LookupResult > lookupPath(StringRef Path) const
Looks up Path in Roots and returns a LookupResult giving the matched entry and, if the entry was a Fi...
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.
void setFallthrough(bool Fallthrough)
Sets the redirection kind to Fallthrough if true or RedirectOnly otherwise.
void visitChildFileSystems(VisitCallbackTy Callback) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Gets real path of Path e.g.
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
void setOverlayFileDir(StringRef PrefixDir)
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
void setRedirection(RedirectingFileSystem::RedirectKind Kind)
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
static std::unique_ptr< RedirectingFileSystem > create(std::unique_ptr< MemoryBuffer > Buffer, SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext, IntrusiveRefCntPtr< FileSystem > ExternalFS)
Parses Buffer, which is expected to be in YAML format and returns a virtual file system representing ...
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel=0) const
The result of a status operation.
llvm::sys::fs::perms getPermissions() const
llvm::sys::fs::UniqueID getUniqueID() const
uint32_t getUser() const
bool equivalent(const Status &Other) const
static Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
uint64_t getSize() const
bool isStatusKnown() 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 Status copyWithNewSize(const Status &In, uint64_t NewSize)
Get a copy of a Status with a different size.
llvm::sys::TimePoint getLastModificationTime() const
llvm::sys::fs::file_type getType() const
bool isRegularFile() const
bool isDirectory() const
StringRef getName() const
Returns the name that should be used for this file or directory.
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)
void addFileMapping(StringRef VirtualPath, StringRef RealPath)
void setCaseSensitivity(bool CaseSensitive)
void setOverlayDir(StringRef OverlayDirectory)
const std::vector< YAMLVFSEntry > & getMappings() const
void write(llvm::raw_ostream &OS)
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.
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:66
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition: Chrono.h:34
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.
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.
std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.
llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
errc
Definition: Errc.h:35
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:419
@ 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:1849
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
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.
void getPath(llvm::SmallVectorImpl< char > &Path) const
Get the (canonical) path of the found entry.
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::stack< directory_iterator, std::vector< directory_iterator > > Stack