File indexing completed on 2026-05-10 08:44:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_VIRTUALFILESYSTEM_H
0015 #define LLVM_SUPPORT_VIRTUALFILESYSTEM_H
0016
0017 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0018 #include "llvm/ADT/STLFunctionalExtras.h"
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include "llvm/Support/Chrono.h"
0022 #include "llvm/Support/Errc.h"
0023 #include "llvm/Support/Error.h"
0024 #include "llvm/Support/ErrorOr.h"
0025 #include "llvm/Support/ExtensibleRTTI.h"
0026 #include "llvm/Support/FileSystem.h"
0027 #include "llvm/Support/Path.h"
0028 #include "llvm/Support/SourceMgr.h"
0029 #include <cassert>
0030 #include <cstdint>
0031 #include <ctime>
0032 #include <memory>
0033 #include <optional>
0034 #include <string>
0035 #include <system_error>
0036 #include <utility>
0037 #include <vector>
0038
0039 namespace llvm {
0040
0041 class MemoryBuffer;
0042 class MemoryBufferRef;
0043 class Twine;
0044
0045 namespace vfs {
0046
0047
0048 class Status {
0049 std::string Name;
0050 llvm::sys::fs::UniqueID UID;
0051 llvm::sys::TimePoint<> MTime;
0052 uint32_t User;
0053 uint32_t Group;
0054 uint64_t Size;
0055 llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::status_error;
0056 llvm::sys::fs::perms Perms;
0057
0058 public:
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 bool ExposesExternalVFSPath = false;
0069
0070 Status() = default;
0071 Status(const llvm::sys::fs::file_status &Status);
0072 Status(const Twine &Name, llvm::sys::fs::UniqueID UID,
0073 llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
0074 uint64_t Size, llvm::sys::fs::file_type Type,
0075 llvm::sys::fs::perms Perms);
0076
0077
0078 static Status copyWithNewSize(const Status &In, uint64_t NewSize);
0079
0080 static Status copyWithNewName(const Status &In, const Twine &NewName);
0081 static Status copyWithNewName(const llvm::sys::fs::file_status &In,
0082 const Twine &NewName);
0083
0084
0085 StringRef getName() const { return Name; }
0086
0087
0088
0089 llvm::sys::fs::file_type getType() const { return Type; }
0090 llvm::sys::fs::perms getPermissions() const { return Perms; }
0091 llvm::sys::TimePoint<> getLastModificationTime() const { return MTime; }
0092 llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
0093 uint32_t getUser() const { return User; }
0094 uint32_t getGroup() const { return Group; }
0095 uint64_t getSize() const { return Size; }
0096
0097
0098
0099
0100 bool equivalent(const Status &Other) const;
0101 bool isDirectory() const;
0102 bool isRegularFile() const;
0103 bool isOther() const;
0104 bool isSymlink() const;
0105 bool isStatusKnown() const;
0106 bool exists() const;
0107
0108 };
0109
0110
0111 class File {
0112 public:
0113
0114
0115
0116 virtual ~File();
0117
0118
0119 virtual llvm::ErrorOr<Status> status() = 0;
0120
0121
0122 virtual llvm::ErrorOr<std::string> getName() {
0123 if (auto Status = status())
0124 return Status->getName().str();
0125 else
0126 return Status.getError();
0127 }
0128
0129
0130 virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
0131 getBuffer(const Twine &Name, int64_t FileSize = -1,
0132 bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
0133
0134
0135 virtual std::error_code close() = 0;
0136
0137
0138 static ErrorOr<std::unique_ptr<File>>
0139 getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P);
0140
0141 protected:
0142
0143 virtual void setPath(const Twine &Path) {}
0144 };
0145
0146
0147
0148 class directory_entry {
0149 std::string Path;
0150 llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::type_unknown;
0151
0152 public:
0153 directory_entry() = default;
0154 directory_entry(std::string Path, llvm::sys::fs::file_type Type)
0155 : Path(std::move(Path)), Type(Type) {}
0156
0157 llvm::StringRef path() const { return Path; }
0158 llvm::sys::fs::file_type type() const { return Type; }
0159 };
0160
0161 namespace detail {
0162
0163
0164
0165 struct DirIterImpl {
0166 virtual ~DirIterImpl();
0167
0168
0169
0170 virtual std::error_code increment() = 0;
0171
0172 directory_entry CurrentEntry;
0173 };
0174
0175 }
0176
0177
0178
0179 class directory_iterator {
0180 std::shared_ptr<detail::DirIterImpl> Impl;
0181
0182 public:
0183 directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
0184 : Impl(std::move(I)) {
0185 assert(Impl.get() != nullptr && "requires non-null implementation");
0186 if (Impl->CurrentEntry.path().empty())
0187 Impl.reset();
0188 }
0189
0190
0191 directory_iterator() = default;
0192
0193
0194 directory_iterator &increment(std::error_code &EC) {
0195 assert(Impl && "attempting to increment past end");
0196 EC = Impl->increment();
0197 if (Impl->CurrentEntry.path().empty())
0198 Impl.reset();
0199 return *this;
0200 }
0201
0202 const directory_entry &operator*() const { return Impl->CurrentEntry; }
0203 const directory_entry *operator->() const { return &Impl->CurrentEntry; }
0204
0205 bool operator==(const directory_iterator &RHS) const {
0206 if (Impl && RHS.Impl)
0207 return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path();
0208 return !Impl && !RHS.Impl;
0209 }
0210 bool operator!=(const directory_iterator &RHS) const {
0211 return !(*this == RHS);
0212 }
0213 };
0214
0215 class FileSystem;
0216
0217 namespace detail {
0218
0219
0220 struct RecDirIterState {
0221 std::vector<directory_iterator> Stack;
0222 bool HasNoPushRequest = false;
0223 };
0224
0225 }
0226
0227
0228
0229 class recursive_directory_iterator {
0230 FileSystem *FS;
0231 std::shared_ptr<detail::RecDirIterState>
0232 State;
0233
0234 public:
0235 recursive_directory_iterator(FileSystem &FS, const Twine &Path,
0236 std::error_code &EC);
0237
0238
0239 recursive_directory_iterator() = default;
0240
0241
0242 recursive_directory_iterator &increment(std::error_code &EC);
0243
0244 const directory_entry &operator*() const { return *State->Stack.back(); }
0245 const directory_entry *operator->() const { return &*State->Stack.back(); }
0246
0247 bool operator==(const recursive_directory_iterator &Other) const {
0248 return State == Other.State;
0249 }
0250 bool operator!=(const recursive_directory_iterator &RHS) const {
0251 return !(*this == RHS);
0252 }
0253
0254
0255 int level() const {
0256 assert(!State->Stack.empty() &&
0257 "Cannot get level without any iteration state");
0258 return State->Stack.size() - 1;
0259 }
0260
0261 void no_push() { State->HasNoPushRequest = true; }
0262 };
0263
0264
0265 class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem>,
0266 public RTTIExtends<FileSystem, RTTIRoot> {
0267 public:
0268 static const char ID;
0269 virtual ~FileSystem();
0270
0271
0272 virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
0273
0274
0275 virtual llvm::ErrorOr<std::unique_ptr<File>>
0276 openFileForRead(const Twine &Path) = 0;
0277
0278
0279
0280
0281
0282
0283 virtual llvm::ErrorOr<std::unique_ptr<File>>
0284 openFileForReadBinary(const Twine &Path) {
0285 return openFileForRead(Path);
0286 }
0287
0288
0289
0290
0291
0292 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
0293 getBufferForFile(const Twine &Name, int64_t FileSize = -1,
0294 bool RequiresNullTerminator = true, bool IsVolatile = false,
0295 bool IsText = true);
0296
0297
0298
0299 virtual directory_iterator dir_begin(const Twine &Dir,
0300 std::error_code &EC) = 0;
0301
0302
0303
0304 virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
0305
0306
0307 virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
0308
0309
0310
0311
0312 virtual std::error_code getRealPath(const Twine &Path,
0313 SmallVectorImpl<char> &Output);
0314
0315
0316
0317 virtual bool exists(const Twine &Path);
0318
0319
0320 virtual std::error_code isLocal(const Twine &Path, bool &Result);
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 virtual std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
0334
0335
0336
0337 llvm::ErrorOr<bool> equivalent(const Twine &A, const Twine &B);
0338
0339 enum class PrintType { Summary, Contents, RecursiveContents };
0340 void print(raw_ostream &OS, PrintType Type = PrintType::Contents,
0341 unsigned IndentLevel = 0) const {
0342 printImpl(OS, Type, IndentLevel);
0343 }
0344
0345 using VisitCallbackTy = llvm::function_ref<void(FileSystem &)>;
0346 virtual void visitChildFileSystems(VisitCallbackTy Callback) {}
0347 void visit(VisitCallbackTy Callback) {
0348 Callback(*this);
0349 visitChildFileSystems(Callback);
0350 }
0351
0352 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0353 LLVM_DUMP_METHOD void dump() const;
0354 #endif
0355
0356 protected:
0357 virtual void printImpl(raw_ostream &OS, PrintType Type,
0358 unsigned IndentLevel) const {
0359 printIndent(OS, IndentLevel);
0360 OS << "FileSystem\n";
0361 }
0362
0363 void printIndent(raw_ostream &OS, unsigned IndentLevel) const {
0364 for (unsigned i = 0; i < IndentLevel; ++i)
0365 OS << " ";
0366 }
0367 };
0368
0369
0370
0371
0372
0373 IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
0374
0375
0376
0377
0378
0379 std::unique_ptr<FileSystem> createPhysicalFileSystem();
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391 class OverlayFileSystem : public RTTIExtends<OverlayFileSystem, FileSystem> {
0392 using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>;
0393
0394
0395
0396 FileSystemList FSList;
0397
0398 public:
0399 static const char ID;
0400 OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base);
0401
0402
0403 void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
0404
0405 llvm::ErrorOr<Status> status(const Twine &Path) override;
0406 bool exists(const Twine &Path) override;
0407 llvm::ErrorOr<std::unique_ptr<File>>
0408 openFileForRead(const Twine &Path) override;
0409 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
0410 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
0411 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
0412 std::error_code isLocal(const Twine &Path, bool &Result) override;
0413 std::error_code getRealPath(const Twine &Path,
0414 SmallVectorImpl<char> &Output) override;
0415
0416 using iterator = FileSystemList::reverse_iterator;
0417 using const_iterator = FileSystemList::const_reverse_iterator;
0418 using reverse_iterator = FileSystemList::iterator;
0419 using const_reverse_iterator = FileSystemList::const_iterator;
0420 using range = iterator_range<iterator>;
0421 using const_range = iterator_range<const_iterator>;
0422
0423
0424 iterator overlays_begin() { return FSList.rbegin(); }
0425 const_iterator overlays_begin() const { return FSList.rbegin(); }
0426
0427
0428 iterator overlays_end() { return FSList.rend(); }
0429 const_iterator overlays_end() const { return FSList.rend(); }
0430
0431
0432 reverse_iterator overlays_rbegin() { return FSList.begin(); }
0433 const_reverse_iterator overlays_rbegin() const { return FSList.begin(); }
0434
0435
0436 reverse_iterator overlays_rend() { return FSList.end(); }
0437 const_reverse_iterator overlays_rend() const { return FSList.end(); }
0438
0439 range overlays_range() { return llvm::reverse(FSList); }
0440 const_range overlays_range() const { return llvm::reverse(FSList); }
0441
0442 protected:
0443 void printImpl(raw_ostream &OS, PrintType Type,
0444 unsigned IndentLevel) const override;
0445 void visitChildFileSystems(VisitCallbackTy Callback) override;
0446 };
0447
0448
0449
0450
0451 class ProxyFileSystem : public RTTIExtends<ProxyFileSystem, FileSystem> {
0452 public:
0453 static const char ID;
0454 explicit ProxyFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
0455 : FS(std::move(FS)) {}
0456
0457 llvm::ErrorOr<Status> status(const Twine &Path) override {
0458 return FS->status(Path);
0459 }
0460 bool exists(const Twine &Path) override { return FS->exists(Path); }
0461 llvm::ErrorOr<std::unique_ptr<File>>
0462 openFileForRead(const Twine &Path) override {
0463 return FS->openFileForRead(Path);
0464 }
0465 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
0466 return FS->dir_begin(Dir, EC);
0467 }
0468 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
0469 return FS->getCurrentWorkingDirectory();
0470 }
0471 std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
0472 return FS->setCurrentWorkingDirectory(Path);
0473 }
0474 std::error_code getRealPath(const Twine &Path,
0475 SmallVectorImpl<char> &Output) override {
0476 return FS->getRealPath(Path, Output);
0477 }
0478 std::error_code isLocal(const Twine &Path, bool &Result) override {
0479 return FS->isLocal(Path, Result);
0480 }
0481
0482 protected:
0483 FileSystem &getUnderlyingFS() const { return *FS; }
0484 void visitChildFileSystems(VisitCallbackTy Callback) override {
0485 if (FS) {
0486 Callback(*FS);
0487 FS->visitChildFileSystems(Callback);
0488 }
0489 }
0490
0491 private:
0492 IntrusiveRefCntPtr<FileSystem> FS;
0493
0494 virtual void anchor() override;
0495 };
0496
0497 namespace detail {
0498
0499 class InMemoryDirectory;
0500 class InMemoryNode;
0501
0502 struct NewInMemoryNodeInfo {
0503 llvm::sys::fs::UniqueID DirUID;
0504 StringRef Path;
0505 StringRef Name;
0506 time_t ModificationTime;
0507 std::unique_ptr<llvm::MemoryBuffer> Buffer;
0508 uint32_t User;
0509 uint32_t Group;
0510 llvm::sys::fs::file_type Type;
0511 llvm::sys::fs::perms Perms;
0512
0513 Status makeStatus() const;
0514 };
0515
0516 class NamedNodeOrError {
0517 ErrorOr<std::pair<llvm::SmallString<128>, const detail::InMemoryNode *>>
0518 Value;
0519
0520 public:
0521 NamedNodeOrError(llvm::SmallString<128> Name,
0522 const detail::InMemoryNode *Node)
0523 : Value(std::make_pair(Name, Node)) {}
0524 NamedNodeOrError(std::error_code EC) : Value(EC) {}
0525 NamedNodeOrError(llvm::errc EC) : Value(EC) {}
0526
0527 StringRef getName() const { return (*Value).first; }
0528 explicit operator bool() const { return static_cast<bool>(Value); }
0529 operator std::error_code() const { return Value.getError(); }
0530 std::error_code getError() const { return Value.getError(); }
0531 const detail::InMemoryNode *operator*() const { return (*Value).second; }
0532 };
0533
0534 }
0535
0536
0537 class InMemoryFileSystem : public RTTIExtends<InMemoryFileSystem, FileSystem> {
0538 std::unique_ptr<detail::InMemoryDirectory> Root;
0539 std::string WorkingDirectory;
0540 bool UseNormalizedPaths = true;
0541
0542 public:
0543 static const char ID;
0544
0545 private:
0546 using MakeNodeFn = llvm::function_ref<std::unique_ptr<detail::InMemoryNode>(
0547 detail::NewInMemoryNodeInfo)>;
0548
0549
0550 bool addFile(const Twine &Path, time_t ModificationTime,
0551 std::unique_ptr<llvm::MemoryBuffer> Buffer,
0552 std::optional<uint32_t> User, std::optional<uint32_t> Group,
0553 std::optional<llvm::sys::fs::file_type> Type,
0554 std::optional<llvm::sys::fs::perms> Perms, MakeNodeFn MakeNode);
0555
0556
0557
0558
0559 detail::NamedNodeOrError lookupNode(const Twine &P, bool FollowFinalSymlink,
0560 size_t SymlinkDepth = 0) const;
0561
0562 class DirIterator;
0563
0564 public:
0565 explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
0566 ~InMemoryFileSystem() override;
0567
0568
0569
0570
0571
0572
0573
0574 bool addFile(const Twine &Path, time_t ModificationTime,
0575 std::unique_ptr<llvm::MemoryBuffer> Buffer,
0576 std::optional<uint32_t> User = std::nullopt,
0577 std::optional<uint32_t> Group = std::nullopt,
0578 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
0579 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595 bool addHardLink(const Twine &NewLink, const Twine &Target);
0596
0597
0598
0599 static constexpr size_t MaxSymlinkDepth = 16;
0600
0601
0602
0603
0604 bool
0605 addSymbolicLink(const Twine &NewLink, const Twine &Target,
0606 time_t ModificationTime,
0607 std::optional<uint32_t> User = std::nullopt,
0608 std::optional<uint32_t> Group = std::nullopt,
0609 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
0610
0611
0612
0613
0614
0615
0616
0617 bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
0618 const llvm::MemoryBufferRef &Buffer,
0619 std::optional<uint32_t> User = std::nullopt,
0620 std::optional<uint32_t> Group = std::nullopt,
0621 std::optional<llvm::sys::fs::file_type> Type = std::nullopt,
0622 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
0623
0624 std::string toString() const;
0625
0626
0627 bool useNormalizedPaths() const { return UseNormalizedPaths; }
0628
0629 llvm::ErrorOr<Status> status(const Twine &Path) override;
0630 llvm::ErrorOr<std::unique_ptr<File>>
0631 openFileForRead(const Twine &Path) override;
0632 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
0633
0634 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
0635 return WorkingDirectory;
0636 }
0637
0638
0639
0640
0641
0642
0643 std::error_code getRealPath(const Twine &Path,
0644 SmallVectorImpl<char> &Output) override;
0645 std::error_code isLocal(const Twine &Path, bool &Result) override;
0646 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
0647
0648 protected:
0649 void printImpl(raw_ostream &OS, PrintType Type,
0650 unsigned IndentLevel) const override;
0651 };
0652
0653
0654 llvm::sys::fs::UniqueID getNextVirtualUniqueID();
0655
0656
0657
0658 std::unique_ptr<FileSystem>
0659 getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
0660 llvm::SourceMgr::DiagHandlerTy DiagHandler,
0661 StringRef YAMLFilePath, void *DiagContext = nullptr,
0662 IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
0663
0664 struct YAMLVFSEntry {
0665 template <typename T1, typename T2>
0666 YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory = false)
0667 : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)),
0668 IsDirectory(IsDirectory) {}
0669 std::string VPath;
0670 std::string RPath;
0671 bool IsDirectory = false;
0672 };
0673
0674 class RedirectingFSDirIterImpl;
0675 class RedirectingFileSystemParser;
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777 class RedirectingFileSystem
0778 : public RTTIExtends<RedirectingFileSystem, vfs::FileSystem> {
0779 public:
0780 static const char ID;
0781 enum EntryKind { EK_Directory, EK_DirectoryRemap, EK_File };
0782 enum NameKind { NK_NotSet, NK_External, NK_Virtual };
0783
0784
0785 enum class RedirectKind {
0786
0787
0788
0789 Fallthrough,
0790
0791
0792 Fallback,
0793
0794
0795 RedirectOnly
0796 };
0797
0798
0799 enum class RootRelativeKind {
0800
0801 CWD,
0802
0803
0804 OverlayDir
0805 };
0806
0807
0808 class Entry {
0809 EntryKind Kind;
0810 std::string Name;
0811
0812 public:
0813 Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
0814 virtual ~Entry() = default;
0815
0816 StringRef getName() const { return Name; }
0817 EntryKind getKind() const { return Kind; }
0818 };
0819
0820
0821 class DirectoryEntry : public Entry {
0822 std::vector<std::unique_ptr<Entry>> Contents;
0823 Status S;
0824
0825 public:
0826
0827 DirectoryEntry(StringRef Name, std::vector<std::unique_ptr<Entry>> Contents,
0828 Status S)
0829 : Entry(EK_Directory, Name), Contents(std::move(Contents)),
0830 S(std::move(S)) {}
0831
0832
0833 DirectoryEntry(StringRef Name, Status S)
0834 : Entry(EK_Directory, Name), S(std::move(S)) {}
0835
0836 Status getStatus() { return S; }
0837
0838 void addContent(std::unique_ptr<Entry> Content) {
0839 Contents.push_back(std::move(Content));
0840 }
0841
0842 Entry *getLastContent() const { return Contents.back().get(); }
0843
0844 using iterator = decltype(Contents)::iterator;
0845
0846 iterator contents_begin() { return Contents.begin(); }
0847 iterator contents_end() { return Contents.end(); }
0848
0849 static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
0850 };
0851
0852
0853
0854 class RemapEntry : public Entry {
0855 std::string ExternalContentsPath;
0856 NameKind UseName;
0857
0858 protected:
0859 RemapEntry(EntryKind K, StringRef Name, StringRef ExternalContentsPath,
0860 NameKind UseName)
0861 : Entry(K, Name), ExternalContentsPath(ExternalContentsPath),
0862 UseName(UseName) {}
0863
0864 public:
0865 StringRef getExternalContentsPath() const { return ExternalContentsPath; }
0866
0867
0868 bool useExternalName(bool GlobalUseExternalName) const {
0869 return UseName == NK_NotSet ? GlobalUseExternalName
0870 : (UseName == NK_External);
0871 }
0872
0873 NameKind getUseName() const { return UseName; }
0874
0875 static bool classof(const Entry *E) {
0876 switch (E->getKind()) {
0877 case EK_DirectoryRemap:
0878 [[fallthrough]];
0879 case EK_File:
0880 return true;
0881 case EK_Directory:
0882 return false;
0883 }
0884 llvm_unreachable("invalid entry kind");
0885 }
0886 };
0887
0888
0889
0890 class DirectoryRemapEntry : public RemapEntry {
0891 public:
0892 DirectoryRemapEntry(StringRef Name, StringRef ExternalContentsPath,
0893 NameKind UseName)
0894 : RemapEntry(EK_DirectoryRemap, Name, ExternalContentsPath, UseName) {}
0895
0896 static bool classof(const Entry *E) {
0897 return E->getKind() == EK_DirectoryRemap;
0898 }
0899 };
0900
0901
0902 class FileEntry : public RemapEntry {
0903 public:
0904 FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
0905 : RemapEntry(EK_File, Name, ExternalContentsPath, UseName) {}
0906
0907 static bool classof(const Entry *E) { return E->getKind() == EK_File; }
0908 };
0909
0910
0911 struct LookupResult {
0912
0913 llvm::SmallVector<Entry *, 32> Parents;
0914
0915
0916 Entry *E;
0917
0918 private:
0919
0920
0921
0922 std::optional<std::string> ExternalRedirect;
0923
0924 public:
0925 LookupResult(Entry *E, sys::path::const_iterator Start,
0926 sys::path::const_iterator End);
0927
0928
0929
0930
0931 std::optional<StringRef> getExternalRedirect() const {
0932 if (isa<DirectoryRemapEntry>(E))
0933 return StringRef(*ExternalRedirect);
0934 if (auto *FE = dyn_cast<FileEntry>(E))
0935 return FE->getExternalContentsPath();
0936 return std::nullopt;
0937 }
0938
0939
0940
0941 void getPath(llvm::SmallVectorImpl<char> &Path) const;
0942 };
0943
0944 private:
0945 friend class RedirectingFSDirIterImpl;
0946 friend class RedirectingFileSystemParser;
0947
0948
0949
0950
0951 std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const;
0952
0953
0954
0955
0956 ErrorOr<Status> getExternalStatus(const Twine &LookupPath,
0957 const Twine &OriginalPath) const;
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971 std::error_code makeAbsolute(StringRef WorkingDir,
0972 SmallVectorImpl<char> &Path) const;
0973
0974
0975
0976
0977
0978
0979 bool pathComponentMatches(llvm::StringRef lhs, llvm::StringRef rhs) const {
0980 if ((CaseSensitive ? lhs == rhs : lhs.equals_insensitive(rhs)))
0981 return true;
0982 return (lhs == "/" && rhs == "\\") || (lhs == "\\" && rhs == "/");
0983 }
0984
0985
0986 std::vector<std::unique_ptr<Entry>> Roots;
0987
0988
0989 std::string WorkingDirectory;
0990
0991
0992 IntrusiveRefCntPtr<FileSystem> ExternalFS;
0993
0994
0995
0996
0997
0998 std::string OverlayFileDir;
0999
1000
1001
1002
1003
1004
1005
1006 bool CaseSensitive = is_style_posix(sys::path::Style::native);
1007
1008
1009
1010 bool IsRelativeOverlay = false;
1011
1012
1013
1014 bool UseExternalNames = true;
1015
1016
1017
1018 mutable bool HasBeenUsed = false;
1019
1020
1021 bool UsageTrackingActive = false;
1022
1023
1024
1025 RedirectKind Redirection = RedirectKind::Fallthrough;
1026
1027
1028
1029 RootRelativeKind RootRelative = RootRelativeKind::CWD;
1030
1031
1032 RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS);
1033
1034
1035
1036
1037
1038 ErrorOr<LookupResult>
1039 lookupPathImpl(llvm::sys::path::const_iterator Start,
1040 llvm::sys::path::const_iterator End, Entry *From,
1041 llvm::SmallVectorImpl<Entry *> &Entries) const;
1042
1043
1044 ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath,
1045 const LookupResult &Result);
1046
1047 public:
1048
1049
1050
1051 ErrorOr<LookupResult> lookupPath(StringRef Path) const;
1052
1053
1054
1055 static std::unique_ptr<RedirectingFileSystem>
1056 create(std::unique_ptr<MemoryBuffer> Buffer,
1057 SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
1058 void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
1059
1060
1061 static std::unique_ptr<RedirectingFileSystem>
1062 create(ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1063 bool UseExternalNames, FileSystem &ExternalFS);
1064
1065 ErrorOr<Status> status(const Twine &Path) override;
1066 bool exists(const Twine &Path) override;
1067 ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
1068
1069 std::error_code getRealPath(const Twine &Path,
1070 SmallVectorImpl<char> &Output) override;
1071
1072 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
1073
1074 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
1075
1076 std::error_code isLocal(const Twine &Path, bool &Result) override;
1077
1078 std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const override;
1079
1080 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
1081
1082 void setOverlayFileDir(StringRef PrefixDir);
1083
1084 StringRef getOverlayFileDir() const;
1085
1086
1087
1088 void setFallthrough(bool Fallthrough);
1089
1090 void setRedirection(RedirectingFileSystem::RedirectKind Kind);
1091
1092 std::vector<llvm::StringRef> getRoots() const;
1093
1094 bool hasBeenUsed() const { return HasBeenUsed; };
1095 void clearHasBeenUsed() { HasBeenUsed = false; }
1096
1097 void setUsageTrackingActive(bool Active) { UsageTrackingActive = Active; }
1098
1099 void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel = 0) const;
1100
1101 protected:
1102 void printImpl(raw_ostream &OS, PrintType Type,
1103 unsigned IndentLevel) const override;
1104 void visitChildFileSystems(VisitCallbackTy Callback) override;
1105 };
1106
1107
1108
1109
1110 void collectVFSFromYAML(
1111 std::unique_ptr<llvm::MemoryBuffer> Buffer,
1112 llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
1113 SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
1114 void *DiagContext = nullptr,
1115 IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
1116
1117 class YAMLVFSWriter {
1118 std::vector<YAMLVFSEntry> Mappings;
1119 std::optional<bool> IsCaseSensitive;
1120 std::optional<bool> IsOverlayRelative;
1121 std::optional<bool> UseExternalNames;
1122 std::string OverlayDir;
1123
1124 void addEntry(StringRef VirtualPath, StringRef RealPath, bool IsDirectory);
1125
1126 public:
1127 YAMLVFSWriter() = default;
1128
1129 void addFileMapping(StringRef VirtualPath, StringRef RealPath);
1130 void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath);
1131
1132 void setCaseSensitivity(bool CaseSensitive) {
1133 IsCaseSensitive = CaseSensitive;
1134 }
1135
1136 void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
1137
1138 void setOverlayDir(StringRef OverlayDirectory) {
1139 IsOverlayRelative = true;
1140 OverlayDir.assign(OverlayDirectory.str());
1141 }
1142
1143 const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
1144
1145 void write(llvm::raw_ostream &OS);
1146 };
1147
1148
1149
1150
1151 class TracingFileSystem
1152 : public llvm::RTTIExtends<TracingFileSystem, ProxyFileSystem> {
1153 public:
1154 static const char ID;
1155
1156 std::size_t NumStatusCalls = 0;
1157 std::size_t NumOpenFileForReadCalls = 0;
1158 std::size_t NumDirBeginCalls = 0;
1159 std::size_t NumGetRealPathCalls = 0;
1160 std::size_t NumExistsCalls = 0;
1161 std::size_t NumIsLocalCalls = 0;
1162
1163 TracingFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
1164 : RTTIExtends(std::move(FS)) {}
1165
1166 ErrorOr<Status> status(const Twine &Path) override {
1167 ++NumStatusCalls;
1168 return ProxyFileSystem::status(Path);
1169 }
1170
1171 ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override {
1172 ++NumOpenFileForReadCalls;
1173 return ProxyFileSystem::openFileForRead(Path);
1174 }
1175
1176 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
1177 ++NumDirBeginCalls;
1178 return ProxyFileSystem::dir_begin(Dir, EC);
1179 }
1180
1181 std::error_code getRealPath(const Twine &Path,
1182 SmallVectorImpl<char> &Output) override {
1183 ++NumGetRealPathCalls;
1184 return ProxyFileSystem::getRealPath(Path, Output);
1185 }
1186
1187 bool exists(const Twine &Path) override {
1188 ++NumExistsCalls;
1189 return ProxyFileSystem::exists(Path);
1190 }
1191
1192 std::error_code isLocal(const Twine &Path, bool &Result) override {
1193 ++NumIsLocalCalls;
1194 return ProxyFileSystem::isLocal(Path, Result);
1195 }
1196
1197 protected:
1198 void printImpl(raw_ostream &OS, PrintType Type,
1199 unsigned IndentLevel) const override;
1200 };
1201
1202 }
1203 }
1204
1205 #endif