LLVM: lib/Support/VirtualFileSystem.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24#include "llvm/Config/llvm-config.h"
40#include
41#include
42#include
43#include
44#include
45#include
46#include
47#include
48#include
49#include <system_error>
50#include
51#include
52
53using namespace llvm;
55
62
67
71 : Name(Name.str()), UID(UID), MTime(MTime), User(User), Group(Group),
72 Size(Size), Type(Type), Perms(Perms) {}
73
75 return Status(In.getName(), In.getUniqueID(), In.getLastModificationTime(),
76 In.getUser(), In.getGroup(), NewSize, In.getType(),
77 In.getPermissions());
78}
79
81 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
82 In.getUser(), In.getGroup(), In.getSize(), In.getType(),
83 In.getPermissions());
84}
85
87 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
88 In.getUser(), In.getGroup(), In.getSize(), In.type(),
89 In.permissions());
90}
91
96
98
100
104
106
108
110 return isStatusKnown() && Type != file_type::file_not_found;
111}
112
114
116
119 bool RequiresNullTerminator, bool IsVolatile,
120 bool IsText) {
122 if ()
123 return F.getError();
124
125 return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
126}
127
130 return {};
131
133 if (!WorkingDir)
134 return WorkingDir.getError();
135
137 return {};
138}
139
144
148
153
156 if (!StatusA)
157 return StatusA.getError();
159 if (!StatusB)
160 return StatusB.getError();
161 return StatusA->equivalent(*StatusB);
162}
163
164#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
166#endif
167
168#ifndef NDEBUG
170 return Component == ".." || Component == ".";
171}
172
175
178 return true;
179 return false;
180}
181#endif
182
183
184
185
186
187namespace {
188
189
190class RealFile : public File {
191 friend class RealFileSystem;
192
194 Status S;
195 std::string RealName;
196
197 RealFile(file_t RawFD, StringRef NewName, StringRef NewRealPathName)
198 : FD(RawFD), S(NewName, {}, {}, {}, {}, {},
200 RealName(NewRealPathName.str()) {
202 }
203
204public:
205 ~RealFile() override;
206
207 ErrorOr status() override;
208 ErrorOrstd::string getName() override;
209 ErrorOr<std::unique_ptr> getBuffer(const Twine &Name,
210 int64_t FileSize,
211 bool RequiresNullTerminator,
212 bool IsVolatile) override;
213 std::error_code close() override;
214 void setPath(const Twine &Path) override;
215};
216
217}
218
219RealFile::~RealFile() { close(); }
220
221ErrorOr RealFile::status() {
223 if (!S.isStatusKnown()) {
224 file_status RealStatus;
225 if (std::error_code EC = sys::fs::status(FD, RealStatus))
226 return EC;
228 }
229 return S;
230}
231
232ErrorOrstd::string RealFile::getName() {
233 return RealName.empty() ? S.getName().str() : RealName;
234}
235
236ErrorOr<std::unique_ptr>
237RealFile::getBuffer(const Twine &Name, int64_t FileSize,
238 bool RequiresNullTerminator, bool IsVolatile) {
241 IsVolatile);
242}
243
244std::error_code RealFile::close() {
247 return EC;
248}
249
250void RealFile::setPath(const Twine &Path) {
251 RealName = Path.str();
254}
255
256namespace {
257
258
259
260
261
262
263
264
265
266class RealFileSystem : public FileSystem {
267public:
268 explicit RealFileSystem(bool LinkCWDToProcess) {
269 if (!LinkCWDToProcess) {
270 SmallString<128> PWD, RealPWD;
272 WD = EC;
274 WD = WorkingDirectory{PWD, PWD};
275 else
276 WD = WorkingDirectory{PWD, RealPWD};
277 }
278 }
279
280 ErrorOr status(const Twine &Path) override;
281 ErrorOr<std::unique_ptr> openFileForRead(const Twine &Path) override;
282 ErrorOr<std::unique_ptr>
283 openFileForReadBinary(const Twine &Path) override;
284 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
285
286 llvm::ErrorOrstd::string getCurrentWorkingDirectory() const override;
287 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
288 std::error_code isLocal(const Twine &Path, bool &Result) override;
289 std::error_code getRealPath(const Twine &Path,
290 SmallVectorImpl &Output) override;
291
292protected:
294 unsigned IndentLevel) const override;
295
296private:
297
298
299 Twine adjustPath(const Twine &Path, SmallVectorImpl &Storage) const {
300 if (!WD || !*WD)
302 Path.toVector(Storage);
304 return Storage;
305 }
306
307 ErrorOr<std::unique_ptr>
308 openFileForReadWithFlags(const Twine &Name, sys::fs::OpenFlags Flags) {
309 SmallString<256> RealName, Storage;
311 adjustPath(Name, Storage), Flags, &RealName);
312 if (!FDOrErr)
314 return std::unique_ptr(
315 new RealFile(*FDOrErr, Name.str(), RealName.str()));
316 }
317
318 struct WorkingDirectory {
319
320 SmallString<128> Specified;
321
323 };
324 std::optional<llvm::ErrorOr> WD;
325};
326
327}
328
329ErrorOr RealFileSystem::status(const Twine &Path) {
330 SmallString<256> Storage;
331 sys::fs::file_status RealStatus;
332 if (std::error_code EC =
334 return EC;
336}
337
338ErrorOr<std::unique_ptr>
339RealFileSystem::openFileForRead(const Twine &Name) {
341}
342
343ErrorOr<std::unique_ptr>
344RealFileSystem::openFileForReadBinary(const Twine &Name) {
346}
347
348llvm::ErrorOrstd::string RealFileSystem::getCurrentWorkingDirectory() const {
349 if (WD && *WD)
350 return std::string(WD->get().Specified);
351 if (WD)
352 return WD->getError();
353
354 SmallString<128> Dir;
356 return EC;
357 return std::string(Dir);
358}
359
360std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
361 if (!WD)
363
365 adjustPath(Path, Storage).toVector(Absolute);
366 bool IsDir;
368 return Err;
369 if (!IsDir)
370 return std::make_error_code(std::errc::not_a_directory);
372 return Err;
374 return std::error_code();
375}
376
377std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
378 SmallString<256> Storage;
380}
381
382std::error_code RealFileSystem::getRealPath(const Twine &Path,
383 SmallVectorImpl &Output) {
384 SmallString<256> Storage;
386}
387
388void RealFileSystem::printImpl(raw_ostream &OS, PrintType Type,
389 unsigned IndentLevel) const {
390 printIndent(OS, IndentLevel);
391 OS << "RealFileSystem using ";
392 if (WD)
393 OS << "own";
394 else
395 OS << "process";
396 OS << " CWD\n";
397}
398
404
406 return std::make_unique(false);
407}
408
409namespace {
410
413
414public:
415 RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
418 }
419
420 std::error_code increment() override {
421 std::error_code EC;
426 return EC;
427 }
428};
429
430}
431
433 std::error_code &EC) {
434 SmallString<128> Storage;
436 std::make_shared(adjustPath(Dir, Storage), EC));
437}
438
439
440
441
442
444 FSList.push_back(std::move(BaseFS));
445}
446
448 FSList.push_back(FS);
449
450
452}
453
463
465
467 if ((*I)->exists(Path))
468 return true;
469 }
470 return false;
471}
472
475
477 auto Result = (*I)->openFileForRead(Path);
479 return Result;
480 }
482}
483
486
487 return FSList.front()->getCurrentWorkingDirectory();
488}
489
490std::error_code
492 for (auto &FS : FSList)
493 if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
494 return EC;
495 return {};
496}
497
499 for (auto &FS : FSList)
500 if (FS->exists(Path))
501 return FS->isLocal(Path, Result);
503}
504
507 for (const auto &FS : FSList)
508 if (FS->exists(Path))
509 return FS->getRealPath(Path, Output);
511}
512
515 Callback(*FS);
516 FS->visitChildFileSystems(Callback);
517 }
518}
519
521 unsigned IndentLevel) const {
522 printIndent(OS, IndentLevel);
523 OS << "OverlayFileSystem\n";
524 if (Type == PrintType::Summary)
525 return;
526
527 if (Type == PrintType::Contents)
528 Type = PrintType::Summary;
530 FS->print(OS, Type, IndentLevel + 1);
531}
532
534
535namespace {
536
537
540
541
543
545
547
548
549
550 std::error_code incrementIter(bool IsFirstTime) {
551 while (!IterList.empty()) {
552 CurrentDirIter = IterList.back();
555 break;
556 }
557
560 return {};
561 }
562
563 std::error_code incrementDirIter(bool IsFirstTime) {
564 assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
565 "incrementing past end");
566 std::error_code EC;
567 if (!IsFirstTime)
569 if (!EC && CurrentDirIter == directory_iterator())
570 EC = incrementIter(IsFirstTime);
571 return EC;
572 }
573
574 std::error_code incrementImpl(bool IsFirstTime) {
575 while (true) {
576 std::error_code EC = incrementDirIter(IsFirstTime);
577 if (EC || CurrentDirIter == directory_iterator()) {
578 CurrentEntry = directory_entry();
579 return EC;
580 }
581 CurrentEntry = *CurrentDirIter;
583 if (SeenNames.insert(Name).second)
584 return EC;
585 }
587 }
588
589public:
591 std::error_code &EC) {
592 for (const auto &FS : FileSystems) {
593 std::error_code FEC;
594 directory_iterator Iter = FS->dir_begin(Dir, FEC);
595 if (FEC && FEC != errc::no_such_file_or_directory) {
596 EC = FEC;
597 return;
598 }
599 if (!FEC)
601 }
602 EC = incrementImpl(true);
603 }
604
606 std::error_code &EC)
607 : IterList(DirIters) {
608 EC = incrementImpl(true);
609 }
610
611 std::error_code increment() override { return incrementImpl(false); }
612};
613
614}
615
617 std::error_code &EC) {
619 std::make_shared(FSList, Dir.str(), EC));
620 if (EC)
621 return {};
622 return Combined;
623}
624
625void ProxyFileSystem::anchor() {}
626
627namespace llvm {
628namespace vfs {
629
631
638
639
640
643 std::string FileName;
644
645public:
647 : Kind(Kind), FileName(std::string(llvm::sys::path::filename(FileName))) {
648 }
650
651
652
653
655
656
659 virtual std::string toString(unsigned Indent) const = 0;
660};
661
664 std::unique_ptrllvm::MemoryBuffer Buffer;
665
666public:
670
675
676 std::string toString(unsigned Indent) const override {
677 return (std::string(Indent, ' ') + Stat.getName() + "\n").str();
678 }
679
683};
684
685namespace {
686
687class InMemoryHardLink : public InMemoryNode {
688 const InMemoryFile &ResolvedFile;
689
690public:
691 InMemoryHardLink(StringRef Path, const InMemoryFile &ResolvedFile)
692 : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
693 const InMemoryFile &getResolvedFile() const { return ResolvedFile; }
694
695 Status getStatus(const Twine &RequestedName) const override {
696 return ResolvedFile.getStatus(RequestedName);
697 }
698
699 std::string toString(unsigned Indent) const override {
700 return std::string(Indent, ' ') + "HardLink to -> " +
701 ResolvedFile.toString(0);
702 }
703
704 static bool classof(const InMemoryNode *N) {
706 }
707};
708
709class InMemorySymbolicLink : public InMemoryNode {
710 std::string TargetPath;
711 Status Stat;
712
713public:
714 InMemorySymbolicLink(StringRef Path, StringRef TargetPath, Status Stat)
716 Stat(Stat) {}
717
718 std::string toString(unsigned Indent) const override {
719 return std::string(Indent, ' ') + "SymbolicLink to -> " + TargetPath;
720 }
721
722 Status getStatus(const Twine &RequestedName) const override {
724 }
725
726 StringRef getTargetPath() const { return TargetPath; }
727
728 static bool classof(const InMemoryNode *N) {
730 }
731};
732
733
734
735
736class InMemoryFileAdaptor : public File {
737 const InMemoryFile &Node;
738
739 std::string RequestedName;
740
741public:
742 explicit InMemoryFileAdaptor(const InMemoryFile &Node,
743 std::string RequestedName)
744 : Node(Node), RequestedName(std::move(RequestedName)) {}
745
746 llvm::ErrorOr status() override {
747 return Node.getStatus(RequestedName);
748 }
749
750 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer>
751 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
752 bool IsVolatile) override {
753 llvm::MemoryBuffer *Buf = Node.getBuffer();
756 }
757
758 std::error_code close() override { return {}; }
759
760 void setPath(const Twine &Path) override { RequestedName = Path.str(); }
761};
762}
763
766 std::map<std::string, std::unique_ptr, std::less<>> Entries;
767
768public:
771
772
773
774
778
780
782 auto I = Entries.find(Name);
783 if (I != Entries.end())
784 return I->second.get();
785 return nullptr;
786 }
787
789 return Entries.emplace(Name, std::move(Child)).first->second.get();
790 }
791
793
796
797 std::string toString(unsigned Indent) const override {
798 std::string Result =
799 (std::string(Indent, ' ') + Stat.getName() + "\n").str();
800 for (const auto &Entry : Entries)
801 Result += Entry.second->toString(Indent + 2);
802 return Result;
803 }
804
808};
809
810}
811
812
813
814
828
838
840 : Root(new detail::InMemoryDirectory(
845 UseNormalizedPaths(UseNormalizedPaths) {}
846
848
850 return Root->toString(0);
851}
852
853bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
854 std::unique_ptrllvm::MemoryBuffer Buffer,
855 std::optional<uint32_t> User,
856 std::optional<uint32_t> Group,
857 std::optionalllvm::sys::fs::file\_type Type,
858 std::optionalllvm::sys::fs::perms Perms,
859 MakeNodeFn MakeNode) {
861 P.toVector(Path);
862
863
866 (void)EC;
867
870
871 if (Path.empty())
872 return false;
873
876 const auto ResolvedUser = User.value_or(0);
877 const auto ResolvedGroup = Group.value_or(0);
880
881
883
885 while (true) {
886 Name = *I;
887 ++I;
888 if (I == E)
889 break;
892
894 StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
899 Name, std::make_uniquedetail::InMemoryDirectory(std::move(Stat))));
900 continue;
901 }
902
904 return false;
906 }
910 MakeNode({Dir->getUniqueID(), Path, Name, ModificationTime,
911 std::move(Buffer), ResolvedUser, ResolvedGroup,
912 ResolvedType, ResolvedPerms}));
913 return true;
914 }
917
920 "Must be either file, hardlink or directory!");
921
922
924 return Link->getResolvedFile().getBuffer()->getBuffer() ==
925 Buffer->getBuffer();
926 }
928 Buffer->getBuffer();
929}
930
931bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
932 std::unique_ptrllvm::MemoryBuffer Buffer,
933 std::optional<uint32_t> User,
934 std::optional<uint32_t> Group,
935 std::optionalllvm::sys::fs::file\_type Type,
936 std::optionalllvm::sys::fs::perms Perms) {
937 return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type,
938 Perms,
940 -> std::unique_ptrdetail::InMemoryNode {
943 return std::make_uniquedetail::InMemoryDirectory(Stat);
944 return std::make_uniquedetail::InMemoryFile(
945 Stat, std::move(NNI.Buffer));
946 });
947}
948
950 const Twine &P, time_t ModificationTime,
952 std::optional<uint32_t> Group, std::optionalllvm::sys::fs::file\_type Type,
953 std::optionalllvm::sys::fs::perms Perms) {
955 std::move(User), std::move(Group), std::move(Type),
956 std::move(Perms),
958 -> std::unique_ptrdetail::InMemoryNode {
961 return std::make_uniquedetail::InMemoryDirectory(Stat);
962 return std::make_uniquedetail::InMemoryFile(
963 Stat, std::move(NNI.Buffer));
964 });
965}
966
968InMemoryFileSystem::lookupNode(const Twine &P, bool FollowFinalSymlink,
969 size_t SymlinkDepth) const {
971 P.toVector(Path);
972
973
976 (void)EC;
977
980
982 if (Path.empty())
984
986 while (true) {
988 ++I;
991
993
994
995 if (I == E && !FollowFinalSymlink)
997
1000
1002 if (std::error_code EC = makeAbsolute(TargetPath))
1003 return EC;
1004
1005
1006
1007
1008
1010 lookupNode(TargetPath, true, SymlinkDepth + 1);
1013
1016
1017
1019 continue;
1020 }
1021
1022
1024 if (I == E)
1027 }
1028
1029
1034 }
1035
1038 return detail::NamedNodeOrError(Path, Dir);
1039 }
1040}
1041
1044 auto NewLinkNode = lookupNode(NewLink, false);
1045
1046
1047
1048 auto TargetNode = lookupNode(Target, true);
1049
1050
1052 return false;
1053 return addFile(NewLink, 0, nullptr, std::nullopt, std::nullopt, std::nullopt,
1055 return std::make_uniquedetail::InMemoryHardLink(
1058 });
1059}
1060
1062 const Twine &NewLink, const Twine &Target, time_t ModificationTime,
1063 std::optional<uint32_t> User, std::optional<uint32_t> Group,
1064 std::optionalllvm::sys::fs::perms Perms) {
1065 auto NewLinkNode = lookupNode(NewLink, false);
1066 if (NewLinkNode)
1067 return false;
1068
1070 NewLink.toVector(NewLinkStr);
1071 Target.toVector(TargetStr);
1072
1073 return addFile(NewLinkStr, ModificationTime, nullptr, User, Group,
1076 return std::make_uniquedetail::InMemorySymbolicLink(
1077 NewLinkStr, TargetStr, NNI.makeStatus());
1078 });
1079}
1080
1082 auto Node = lookupNode(Path, true);
1084 return (*Node)->getStatus(Path);
1085 return Node.getError();
1086}
1087
1090 auto Node = lookupNode(Path,true);
1092 return Node.getError();
1093
1094
1095
1097 return std::unique_ptr(
1098 new detail::InMemoryFileAdaptor(*F, Path.str()));
1099
1100
1102}
1103
1104
1109 std::string RequestedDirName;
1110
1111 void setCurrentEntry() {
1112 if (I != E) {
1116 switch (I->second->getKind()) {
1120 break;
1123 break;
1125 if (auto SymlinkTarget =
1126 FS->lookupNode(Path, true)) {
1127 Path = SymlinkTarget.getName();
1128 Type = (*SymlinkTarget)->getStatus(Path).getType();
1129 }
1130 break;
1131 }
1133 } else {
1134
1135
1137 }
1138 }
1139
1140public:
1142
1145 std::string RequestedDirName)
1146 : FS(FS), I(Dir.begin()), E(Dir.end()),
1147 RequestedDirName(std::move(RequestedDirName)) {
1148 setCurrentEntry();
1149 }
1150
1152 ++I;
1153 setCurrentEntry();
1154 return {};
1155 }
1156};
1157
1159 std::error_code &EC) {
1160 auto Node = lookupNode(Dir, true);
1161 if () {
1162 EC = Node.getError();
1164 }
1165
1168 std::make_shared(this, *DirNode, Dir.str()));
1169
1172}
1173
1176 P.toVector(Path);
1177
1178
1181 (void)EC;
1182
1185
1186 if (!Path.empty())
1187 WorkingDirectory = std::string(Path);
1188 return {};
1189}
1190
1194 if (!CWD || CWD->empty())
1196 Path.toVector(Output);
1198 return EC;
1200 return {};
1201}
1202
1204 Result = false;
1205 return {};
1206}
1207
1209 unsigned IndentLevel) const {
1210 printIndent(OS, IndentLevel);
1211 OS << "InMemoryFileSystem\n";
1212}
1213
1214}
1215}
1216
1217
1218
1219
1220
1221namespace {
1222
1224
1226 const size_t n = Path.find_first_of("/\\");
1227
1228 if (n != static_cast<size_t>(-1))
1230 : llvm::sys::path::Style::windows_backslash;
1231 return style;
1232}
1233
1234
1236
1238
1239
1240
1244 return result;
1245}
1246
1247
1248static bool isFileNotFound(std::error_code EC,
1251 return false;
1253}
1254
1255}
1256
1257
1260 if (ExternalFS)
1261 if (auto ExternalWorkingDirectory =
1262 ExternalFS->getCurrentWorkingDirectory()) {
1263 WorkingDirectory = *ExternalWorkingDirectory;
1264 }
1265}
1266
1267
1268
1271 std::string Dir;
1273
1274 std::error_code incrementImpl(bool IsFirstTime) {
1275 assert((IsFirstTime || Current != End) && "cannot iterate past end");
1276 if (!IsFirstTime)
1277 ++Current;
1278 if (Current != End) {
1282 switch ((*Current)->getKind()) {
1284 [[fallthrough]];
1287 break;
1290 break;
1291 }
1293 } else {
1295 }
1296 return {};
1297 };
1298
1299public:
1303 : Dir(Path.str()), Current(Begin), End(End) {
1304 EC = incrementImpl(true);
1305 }
1306
1308 return incrementImpl(false);
1309 }
1310};
1311
1312namespace {
1313
1314
1315
1317 std::string Dir;
1320
1321public:
1322 RedirectingFSDirRemapIterImpl(std::string DirPath,
1324 : Dir(std::move(DirPath)), DirStyle(getExistingStyle(Dir)),
1325 ExternalIter(ExtIter) {
1327 setCurrentEntry();
1328 }
1329
1330 void setCurrentEntry() {
1334
1337
1338 CurrentEntry = directory_entry(std::string(NewPath), ExternalIter->type());
1339 }
1340
1341 std::error_code increment() override {
1342 std::error_code EC;
1344 if (!EC && ExternalIter != llvm::vfs::directory_iterator())
1345 setCurrentEntry();
1346 else
1347 CurrentEntry = directory_entry();
1348 return EC;
1349 }
1350};
1351}
1352
1353llvm::ErrorOrstd::string
1355 return WorkingDirectory;
1356}
1357
1358std::error_code
1360
1363
1365 Path.toVector(AbsolutePath);
1366 if (std::error_code EC = makeAbsolute(AbsolutePath))
1367 return EC;
1368 WorkingDirectory = std::string(AbsolutePath);
1369 return {};
1370}
1371
1373 bool &Result) {
1376
1377 if (makeAbsolute(Path))
1378 return {};
1379
1380 return ExternalFS->isLocal(Path, Result);
1381}
1382
1384
1388
1389
1390
1391 return {};
1392
1394 if (!WorkingDir)
1395 return WorkingDir.getError();
1396
1397 return makeAbsolute(WorkingDir.get(), Path);
1398}
1399
1400std::error_code
1401RedirectingFileSystem::makeAbsolute(StringRef WorkingDir,
1403
1404
1405
1406
1407 if (!WorkingDir.empty() &&
1411 return std::error_code();
1412 }
1416 } else {
1417
1418
1421 }
1422
1423 std::string Result = std::string(WorkingDir);
1424 StringRef Dir(Result);
1427 }
1428
1429
1430
1431
1432
1435
1436 return {};
1437}
1438
1440 std::error_code &EC) {
1443
1444 EC = makeAbsolute(Path);
1445 if (EC)
1446 return {};
1447
1449 if (!Result) {
1451 isFileNotFound(Result.getError()))
1452 return ExternalFS->dir_begin(Path, EC);
1453
1454 EC = Result.getError();
1455 return {};
1456 }
1457
1458
1460 if (!S) {
1462 isFileNotFound(S.getError(), Result->E))
1463 return ExternalFS->dir_begin(Dir, EC);
1464
1466 return {};
1467 }
1468
1469 if (!S->isDirectory()) {
1471 return {};
1472 }
1473
1474
1475
1477 std::error_code RedirectEC;
1478 if (auto ExtRedirect = Result->getExternalRedirect()) {
1480 RedirectIter = ExternalFS->dir_begin(*ExtRedirect, RedirectEC);
1481
1482 if (!RE->useExternalName(UseExternalNames)) {
1483
1484 RedirectIter =
1486 std::string(Path), RedirectIter));
1487 }
1488 } else {
1490 RedirectIter =
1492 Path, DE->contents_begin(), DE->contents_end(), RedirectEC));
1493 }
1494
1495 if (RedirectEC) {
1497 EC = RedirectEC;
1498 return {};
1499 }
1500 RedirectIter = {};
1501 }
1502
1504 EC = RedirectEC;
1505 return RedirectIter;
1506 }
1507
1508 std::error_code ExternalEC;
1509 directory_iterator ExternalIter = ExternalFS->dir_begin(Path, ExternalEC);
1510 if (ExternalEC) {
1512 EC = ExternalEC;
1513 return {};
1514 }
1515 ExternalIter = {};
1516 }
1517
1519 switch (Redirection) {
1523 break;
1527 break;
1528 default:
1530 }
1531
1533 std::make_shared(Iters, EC)};
1534 if (EC)
1535 return {};
1536 return Combined;
1537}
1538
1540 OverlayFileDir = Dir.str();
1541}
1542
1544 return OverlayFileDir;
1545}
1546
1550 } else {
1552 }
1553}
1554
1557 Redirection = Kind;
1558}
1559
1561 std::vector R;
1562 R.reserve(Roots.size());
1563 for (const auto &Root : Roots)
1564 R.push_back(Root->getName());
1565 return R;
1566}
1567
1569 unsigned IndentLevel) const {
1571 OS << "RedirectingFileSystem (UseExternalNames: "
1572 << (UseExternalNames ? "true" : "false") << ")\n";
1574 return;
1575
1576 for (const auto &Root : Roots)
1577 printEntry(OS, Root.get(), IndentLevel);
1578
1580 OS << "ExternalFS:\n";
1582 IndentLevel + 1);
1583}
1584
1587 unsigned IndentLevel) const {
1589 OS << "'" << E->getName() << "'";
1590
1591 switch (E->getKind()) {
1594
1595 OS << "\n";
1596 for (std::unique_ptr &SubEntry :
1598 printEntry(OS, SubEntry.get(), IndentLevel + 1);
1599 break;
1600 }
1604 OS << " -> '" << RE->getExternalContentsPath() << "'";
1605 switch (RE->getUseName()) {
1607 break;
1609 OS << " (UseExternalName: true)";
1610 break;
1612 OS << " (UseExternalName: false)";
1613 break;
1614 }
1615 OS << "\n";
1616 break;
1617 }
1618 }
1619}
1620
1622 if (ExternalFS) {
1623 Callback(*ExternalFS);
1624 ExternalFS->visitChildFileSystems(Callback);
1625 }
1626}
1627
1628
1631
1633
1634
1638
1639 if (!S) {
1640 error(N, "expected string");
1641 return false;
1642 }
1643 Result = S->getValue(Storage);
1644 return true;
1645 }
1646
1647
1648 bool parseScalarBool(yaml::Node *N, bool &Result) {
1651 if (!parseScalarString(N, Value, Storage))
1652 return false;
1653
1654 if (Value.equals_insensitive("true") || Value.equals_insensitive("on") ||
1655 Value.equals_insensitive("yes") || Value == "1") {
1656 Result = true;
1657 return true;
1658 } else if (Value.equals_insensitive("false") ||
1659 Value.equals_insensitive("off") ||
1660 Value.equals_insensitive("no") || Value == "0") {
1661 Result = false;
1662 return true;
1663 }
1664
1665 error(N, "expected boolean value");
1666 return false;
1667 }
1668
1669 std::optionalRedirectingFileSystem::RedirectKind
1673 if (!parseScalarString(N, Value, Storage))
1674 return std::nullopt;
1675
1676 if (Value.equals_insensitive("fallthrough")) {
1678 } else if (Value.equals_insensitive("fallback")) {
1680 } else if (Value.equals_insensitive("redirect-only")) {
1682 }
1683 return std::nullopt;
1684 }
1685
1686 std::optionalRedirectingFileSystem::RootRelativeKind
1690 if (!parseScalarString(N, Value, Storage))
1691 return std::nullopt;
1692 if (Value.equals_insensitive("cwd")) {
1694 } else if (Value.equals_insensitive("overlay-dir")) {
1696 }
1697 return std::nullopt;
1698 }
1699
1700 struct KeyStatus {
1702 bool Seen = false;
1703
1705 };
1706
1707 using KeyStatusPair = std::pair<StringRef, KeyStatus>;
1708
1709
1712 auto It = Keys.find(Key);
1713 if (It == Keys.end()) {
1714 error(KeyNode, "unknown key");
1715 return false;
1716 }
1717 KeyStatus &S = It->second;
1718 if (S.Seen) {
1719 error(KeyNode, Twine("duplicate key '") + Key + "'");
1720 return false;
1721 }
1722 S.Seen = true;
1723 return true;
1724 }
1725
1726
1728 for (const auto &I : Keys) {
1729 if (I.second.Required && .second.Seen) {
1730 error(Obj, Twine("missing key '") + I.first + "'");
1731 return false;
1732 }
1733 }
1734 return true;
1735 }
1736
1737public:
1741 if (!ParentEntry) {
1742 for (const auto &Root : FS->Roots) {
1743 if (Name == Root->getName()) {
1744 ParentEntry = Root.get();
1745 return ParentEntry;
1746 }
1747 }
1748 } else {
1750 for (std::unique_ptrRedirectingFileSystem::Entry &Content :
1751 llvm::make_range(DE->contents_begin(), DE->contents_end())) {
1752 auto *DirContent =
1754 if (DirContent && Name == Content->getName())
1755 return DirContent;
1756 }
1757 }
1758
1759
1760 std::unique_ptrRedirectingFileSystem::Entry E =
1761 std::make_uniqueRedirectingFileSystem::DirectoryEntry(
1763 std::chrono::system_clock::now(), 0, 0, 0,
1765
1766 if (!ParentEntry) {
1767 FS->Roots.push_back(std::move(E));
1768 ParentEntry = FS->Roots.back().get();
1769 return ParentEntry;
1770 }
1771
1773 DE->addContent(std::move(E));
1774 return DE->getLastContent();
1775 }
1776
1777private:
1782 switch (SrcE->getKind()) {
1785
1786
1787
1788 if (!Name.empty())
1789 NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
1790 for (std::unique_ptrRedirectingFileSystem::Entry &SubEntry :
1792 uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
1793 break;
1794 }
1796 assert(NewParentE && "Parent entry must exist");
1799 DE->addContent(
1800 std::make_uniqueRedirectingFileSystem::DirectoryRemapEntry(
1801 Name, DR->getExternalContentsPath(), DR->getUseName()));
1802 break;
1803 }
1805 assert(NewParentE && "Parent entry must exist");
1808 DE->addContent(std::make_uniqueRedirectingFileSystem::FileEntry(
1809 Name, FE->getExternalContentsPath(), FE->getUseName()));
1810 break;
1811 }
1812 }
1813 }
1814
1815 std::unique_ptrRedirectingFileSystem::Entry
1816 parseEntry(yaml::Node *N, RedirectingFileSystem *FS, bool IsRootEntry) {
1818 if (!M) {
1819 error(N, "expected mapping node for file or directory entry");
1820 return nullptr;
1821 }
1822
1823 KeyStatusPair Fields[] = {
1824 KeyStatusPair("name", true),
1825 KeyStatusPair("type", true),
1826 KeyStatusPair("contents", false),
1827 KeyStatusPair("external-contents", false),
1828 KeyStatusPair("use-external-name", false),
1829 };
1830
1831 DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
1832
1833 enum { CF_NotSet, CF_List, CF_External } ContentsField = CF_NotSet;
1834 std::vector<std::unique_ptrRedirectingFileSystem::Entry>
1835 EntryArrayContents;
1836 SmallString<256> ExternalContentsPath;
1837 SmallString<256> Name;
1838 yaml::Node *NameValueNode = nullptr;
1841
1842 for (auto &I : *M) {
1843 StringRef Key;
1844
1845
1846 SmallString<256> Buffer;
1847 if (!parseScalarString(I.getKey(), Key, Buffer))
1848 return nullptr;
1849
1850 if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
1851 return nullptr;
1852
1853 StringRef Value;
1854 if (Key == "name") {
1855 if (!parseScalarString(I.getValue(), Value, Buffer))
1856 return nullptr;
1857
1858 NameValueNode = I.getValue();
1859
1860
1861 Name = canonicalize(Value).str();
1862 } else if (Key == "type") {
1863 if (!parseScalarString(I.getValue(), Value, Buffer))
1864 return nullptr;
1865 if (Value == "file")
1867 else if (Value == "directory")
1869 else if (Value == "directory-remap")
1871 else {
1872 error(I.getValue(), "unknown value for 'type'");
1873 return nullptr;
1874 }
1875 } else if (Key == "contents") {
1876 if (ContentsField != CF_NotSet) {
1878 "entry already has 'contents' or 'external-contents'");
1879 return nullptr;
1880 }
1881 ContentsField = CF_List;
1883 if (!Contents) {
1884
1885 error(I.getValue(), "expected array");
1886 return nullptr;
1887 }
1888
1889 for (auto &I : *Contents) {
1890 if (std::unique_ptrRedirectingFileSystem::Entry E =
1891 parseEntry(&I, FS, false))
1892 EntryArrayContents.push_back(std::move(E));
1893 else
1894 return nullptr;
1895 }
1896 } else if (Key == "external-contents") {
1897 if (ContentsField != CF_NotSet) {
1899 "entry already has 'contents' or 'external-contents'");
1900 return nullptr;
1901 }
1902 ContentsField = CF_External;
1903 if (!parseScalarString(I.getValue(), Value, Buffer))
1904 return nullptr;
1905
1906 SmallString<256> FullPath;
1907 if (FS->IsRelativeOverlay) {
1908 FullPath = FS->getOverlayFileDir();
1910 "External contents prefix directory must exist");
1911 SmallString<256> AbsFullPath = Value;
1912 if (FS->makeAbsolute(FullPath, AbsFullPath)) {
1913 error(N, "failed to make 'external-contents' absolute");
1914 return nullptr;
1915 }
1916 FullPath = AbsFullPath;
1917 } else {
1918 FullPath = Value;
1919 }
1920
1921
1922
1923 FullPath = canonicalize(FullPath);
1924 ExternalContentsPath = FullPath.str();
1925 } else if (Key == "use-external-name") {
1926 bool Val;
1927 if (!parseScalarBool(I.getValue(), Val))
1928 return nullptr;
1931 } else {
1933 }
1934 }
1935
1936 if (Stream.failed())
1937 return nullptr;
1938
1939
1940 if (ContentsField == CF_NotSet) {
1941 error(N, "missing key 'contents' or 'external-contents'");
1942 return nullptr;
1943 }
1944 if (!checkMissingKeys(N, Keys))
1945 return nullptr;
1946
1947
1950 error(N, "'use-external-name' is not supported for 'directory' entries");
1951 return nullptr;
1952 }
1953
1955 ContentsField == CF_List) {
1956 error(N, "'contents' is not supported for 'directory-remap' entries");
1957 return nullptr;
1958 }
1959
1961 if (IsRootEntry) {
1962
1963
1965 path_style = sys::path::Style::posix;
1967 sys::path::Style::windows_backslash)) {
1968 path_style = sys::path::Style::windows_backslash;
1969 } else {
1970
1971
1972
1973 std::error_code EC;
1974 if (FS->RootRelative ==
1975 RedirectingFileSystem::RootRelativeKind::OverlayDir) {
1976 StringRef FullPath = FS->getOverlayFileDir();
1977 assert(!FullPath.empty() && "Overlay file directory must exist");
1978 EC = FS->makeAbsolute(FullPath, Name);
1979 Name = canonicalize(Name);
1980 } else {
1981 EC = FS->makeAbsolute(Name);
1982 }
1983 if (EC) {
1984 assert(NameValueNode && "Name presence should be checked earlier");
1986 NameValueNode,
1987 "entry with relative path at the root level is not discoverable");
1988 return nullptr;
1989 }
1991 ? sys::path::Style::posix
1992 : sys::path::Style::windows_backslash;
1993 }
1994
1995
1996
1997 if (path_style == sys::path::Style::windows_backslash &&
1998 getExistingStyle(Name) != sys::path::Style::windows_backslash)
1999 path_style = sys::path::Style::windows_slash;
2000 }
2001
2002
2003 StringRef Trimmed = Name;
2005 while (Trimmed.size() > RootPathLen &&
2007 Trimmed = Trimmed.slice(0, Trimmed.size() - 1);
2008
2009
2011
2012 std::unique_ptrRedirectingFileSystem::Entry Result;
2013 switch (Kind) {
2015 Result = std::make_uniqueRedirectingFileSystem::FileEntry(
2016 LastComponent, std::move(ExternalContentsPath), UseExternalName);
2017 break;
2019 Result = std::make_uniqueRedirectingFileSystem::DirectoryRemapEntry(
2020 LastComponent, std::move(ExternalContentsPath), UseExternalName);
2021 break;
2023 Result = std::make_uniqueRedirectingFileSystem::DirectoryEntry(
2024 LastComponent, std::move(EntryArrayContents),
2027 break;
2028 }
2029
2031 if (Parent.empty())
2033
2034
2035 for (sys::path::reverse_iterator I = sys::path::rbegin(Parent, path_style),
2038 std::vector<std::unique_ptrRedirectingFileSystem::Entry> Entries;
2039 Entries.push_back(std::move(Result));
2040 Result = std::make_uniqueRedirectingFileSystem::DirectoryEntry(
2041 *I, std::move(Entries),
2044 }
2046 }
2047
2048public:
2050
2051
2054 if (!Top) {
2055 error(Root, "expected mapping node");
2056 return false;
2057 }
2058
2059 KeyStatusPair Fields[] = {
2060 KeyStatusPair("version", true),
2061 KeyStatusPair("case-sensitive", false),
2062 KeyStatusPair("use-external-names", false),
2063 KeyStatusPair("root-relative", false),
2064 KeyStatusPair("overlay-relative", false),
2065 KeyStatusPair("fallthrough", false),
2066 KeyStatusPair("redirecting-with", false),
2067 KeyStatusPair("roots", true),
2068 };
2069
2071 std::vector<std::unique_ptrRedirectingFileSystem::Entry> RootEntries;
2072
2073
2074 for (auto &I : *Top) {
2077 if (!parseScalarString(I.getKey(), Key, KeyBuffer))
2078 return false;
2079
2080 if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
2081 return false;
2082
2083 if (Key == "roots") {
2085 if (!Roots) {
2086 error(I.getValue(), "expected array");
2087 return false;
2088 }
2089
2090 for (auto &I : *Roots) {
2091 if (std::unique_ptrRedirectingFileSystem::Entry E =
2092 parseEntry(&I, FS, true))
2093 RootEntries.push_back(std::move(E));
2094 else
2095 return false;
2096 }
2097 } else if (Key == "version") {
2100 if (!parseScalarString(I.getValue(), VersionString, Storage))
2101 return false;
2104 error(I.getValue(), "expected integer");
2105 return false;
2106 }
2108 error(I.getValue(), "invalid version number");
2109 return false;
2110 }
2112 error(I.getValue(), "version mismatch, expected 0");
2113 return false;
2114 }
2115 } else if (Key == "case-sensitive") {
2116 if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
2117 return false;
2118 } else if (Key == "overlay-relative") {
2119 if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
2120 return false;
2121 } else if (Key == "use-external-names") {
2122 if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
2123 return false;
2124 } else if (Key == "fallthrough") {
2125 if (Keys["redirecting-with"].Seen) {
2127 "'fallthrough' and 'redirecting-with' are mutually exclusive");
2128 return false;
2129 }
2130
2131 bool ShouldFallthrough = false;
2132 if (!parseScalarBool(I.getValue(), ShouldFallthrough))
2133 return false;
2134
2135 if (ShouldFallthrough) {
2137 } else {
2139 }
2140 } else if (Key == "redirecting-with") {
2141 if (Keys["fallthrough"].Seen) {
2143 "'fallthrough' and 'redirecting-with' are mutually exclusive");
2144 return false;
2145 }
2146
2147 if (auto Kind = parseRedirectKind(I.getValue())) {
2148 FS->Redirection = *Kind;
2149 } else {
2150 error(I.getValue(), "expected valid redirect kind");
2151 return false;
2152 }
2153 } else if (Key == "root-relative") {
2154 if (auto Kind = parseRootRelativeKind(I.getValue())) {
2155 FS->RootRelative = *Kind;
2156 } else {
2157 error(I.getValue(), "expected valid root-relative kind");
2158 return false;
2159 }
2160 } else {
2162 }
2163 }
2164
2165 if (Stream.failed())
2166 return false;
2167
2168 if (!checkMissingKeys(Top, Keys))
2169 return false;
2170
2171
2172
2173
2174 for (auto &E : RootEntries)
2175 uniqueOverlayTree(FS, E.get());
2176
2177 return true;
2178 }
2179};
2180
2181std::unique_ptr
2184 StringRef YAMLFilePath, void *DiagContext,
2187 yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
2188
2192 if (DI == Stream.end() || !Root) {
2194 return nullptr;
2195 }
2196
2198
2199 std::unique_ptr FS(
2200 new RedirectingFileSystem(ExternalFS));
2201
2202 if (!YAMLFilePath.empty()) {
2203
2204
2205
2206
2207
2208
2209
2210
2212 std::error_code EC = FS->makeAbsolute(OverlayAbsDir);
2213 assert(!EC && "Overlay dir final path must be absolute");
2214 (void)EC;
2215 FS->setOverlayFileDir(OverlayAbsDir);
2216 }
2217
2218 if (.parse(Root, FS.get()))
2219 return nullptr;
2220
2221 return FS;
2222}
2223
2225 ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
2227 std::unique_ptr FS(
2228 new RedirectingFileSystem(ExternalFS));
2229 FS->UseExternalNames = UseExternalNames;
2230
2232
2233 for (auto &Mapping : llvm::reverse(RemappedFiles)) {
2236 {
2237 auto EC = ExternalFS->makeAbsolute(From);
2238 (void)EC;
2239 assert(!EC && "Could not make absolute path");
2240 }
2241
2242
2243
2245 if (ToEntry)
2246 continue;
2247
2248
2255 Parent);
2256 }
2257 assert(Parent && "File without a directory?");
2258 {
2259 auto EC = ExternalFS->makeAbsolute(To);
2260 (void)EC;
2261 assert(!EC && "Could not make absolute path");
2262 }
2263
2264
2265 auto NewFile = std::make_uniqueRedirectingFileSystem::FileEntry(
2269 ToEntry = NewFile.get();
2271 std::move(NewFile));
2272 }
2273
2274 return FS;
2275}
2276
2281
2282
2283
2287 getExistingStyle(DRE->getExternalContentsPath()));
2288 ExternalRedirect = std::string(Redirect);
2289 }
2290}
2291
2294 Result.clear();
2298}
2299
2300std::error_code RedirectingFileSystem::makeCanonicalForLookup(
2302 if (std::error_code EC = makeAbsolute(Path))
2303 return EC;
2304
2306 canonicalize(StringRef(Path.data(), Path.size()));
2307 if (CanonicalPath.empty())
2309
2310 Path.assign(CanonicalPath.begin(), CanonicalPath.end());
2311 return {};
2312}
2313
2317 if (std::error_code EC = makeCanonicalForLookup(CanonicalPath))
2318 return EC;
2319
2320
2322 HasBeenUsed = true;
2323
2327 for (const auto &Root : Roots) {
2329 lookupPathImpl(Start, End, Root.get(), Entries);
2330 if (UsageTrackingActive && Result && isa(Result->E))
2331 HasBeenUsed = true;
2333 Result->Parents = std::move(Entries);
2334 return Result;
2335 }
2336 }
2338}
2339
2341RedirectingFileSystem::lookupPathImpl(
2347 "Paths should not contain traversal components");
2348
2350
2351
2352 if (!FromName.empty()) {
2353 if (!pathComponentMatches(*Start, FromName))
2355
2356 ++Start;
2357
2358 if (Start == End) {
2359
2360 return LookupResult(From, Start, End);
2361 }
2362 }
2363
2366
2368 return LookupResult(From, Start, End);
2369
2371 for (const std::unique_ptrRedirectingFileSystem::Entry &DirEntry :
2372 llvm::make_range(DE->contents_begin(), DE->contents_end())) {
2375 lookupPathImpl(Start, End, DirEntry.get(), Entries);
2377 return Result;
2379 }
2380
2382}
2383
2385 bool UseExternalNames,
2386 Status ExternalStatus) {
2387
2388
2390 return ExternalStatus;
2391
2392 Status S = ExternalStatus;
2393 if (!UseExternalNames)
2395 else
2397 return S;
2398}
2399
2400ErrorOr RedirectingFileSystem::status(
2401 const Twine &LookupPath, const Twine &OriginalPath,
2402 const RedirectingFileSystem::LookupResult &Result) {
2403 if (std::optional ExtRedirect = Result.getExternalRedirect()) {
2404 SmallString<256> RemappedPath((*ExtRedirect).str());
2405 if (std::error_code EC = makeAbsolute(RemappedPath))
2406 return EC;
2407
2408 ErrorOr S = ExternalFS->status(RemappedPath);
2409 if (!S)
2410 return S;
2414 RE->useExternalName(UseExternalNames), *S);
2415 }
2416
2419}
2420
2421ErrorOr
2422RedirectingFileSystem::getExternalStatus(const Twine &LookupPath,
2423 const Twine &OriginalPath) const {
2424 auto Result = ExternalFS->status(LookupPath);
2425
2426
2427
2428 if (!Result || Result->ExposesExternalVFSPath)
2431}
2432
2435 OriginalPath.toVector(Path);
2436
2437 if (std::error_code EC = makeAbsolute(Path))
2438 return EC;
2439
2441
2442
2443 ErrorOr S = getExternalStatus(Path, OriginalPath);
2444 if (S)
2445 return S;
2446 }
2447
2449 if (!Result) {
2450
2451
2453 isFileNotFound(Result.getError()))
2454 return getExternalStatus(Path, OriginalPath);
2455 return Result.getError();
2456 }
2457
2458 ErrorOr S = status(Path, OriginalPath, *Result);
2460 isFileNotFound(S.getError(), Result->E)) {
2461
2462
2463
2464 return getExternalStatus(Path, OriginalPath);
2465 }
2466
2467 return S;
2468}
2469
2472 OriginalPath.toVector(Path);
2473
2474 if (makeAbsolute(Path))
2475 return false;
2476
2478
2479
2480 if (ExternalFS->exists(Path))
2481 return true;
2482 }
2483
2485 if (!Result) {
2486
2487
2489 isFileNotFound(Result.getError()))
2490 return ExternalFS->exists(Path);
2491 return false;
2492 }
2493
2494 std::optional ExtRedirect = Result->getExternalRedirect();
2495 if (!ExtRedirect) {
2497 return true;
2498 }
2499
2501 if (makeAbsolute(RemappedPath))
2502 return false;
2503
2504 if (ExternalFS->exists(RemappedPath))
2505 return true;
2506
2508
2509
2510
2511 return ExternalFS->exists(Path);
2512 }
2513
2514 return false;
2515}
2516
2517namespace {
2518
2519
2520class FileWithFixedStatus : public File {
2521 std::unique_ptr InnerFile;
2523
2524public:
2525 FileWithFixedStatus(std::unique_ptr InnerFile, Status S)
2526 : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
2527
2530
2531 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
2532 bool IsVolatile) override {
2533 return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
2534 IsVolatile);
2535 }
2536
2537 std::error_code close() override { return InnerFile->close(); }
2538
2539 void setPath(const Twine &Path) override { S = S.copyWithNewName(S, Path); }
2540};
2541
2542}
2543
2544ErrorOr<std::unique_ptr>
2546
2547
2548 if (!Result || (*Result)->status()->ExposesExternalVFSPath)
2549 return Result;
2550
2552 auto Name = F->get()->getName();
2553 if (Name && Name.get() != P.str())
2555 return F;
2556}
2557
2561 OriginalPath.toVector(Path);
2562
2563 if (std::error_code EC = makeAbsolute(Path))
2564 return EC;
2565
2567
2568
2569 auto F = File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
2570 if (F)
2571 return F;
2572 }
2573
2575 if (!Result) {
2576
2577
2579 isFileNotFound(Result.getError()))
2580 return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
2581 return Result.getError();
2582 }
2583
2584 if (!Result->getExternalRedirect())
2586
2587 StringRef ExtRedirect = *Result->getExternalRedirect();
2589 if (std::error_code EC = makeAbsolute(RemappedPath))
2590 return EC;
2591
2593
2594 auto ExternalFile =
2595 File::getWithPath(ExternalFS->openFileForRead(RemappedPath), ExtRedirect);
2596 if (!ExternalFile) {
2598 isFileNotFound(ExternalFile.getError(), Result->E)) {
2599
2600
2601
2602 return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
2603 }
2604 return ExternalFile;
2605 }
2606
2607 auto ExternalStatus = (*ExternalFile)->status();
2608 if (!ExternalStatus)
2609 return ExternalStatus.getError();
2610
2611
2612
2614 OriginalPath, RE->useExternalName(UseExternalNames), *ExternalStatus);
2615 return std::unique_ptr(
2616 std::make_unique(std::move(*ExternalFile), S));
2617}
2618
2619std::error_code
2623 OriginalPath.toVector(Path);
2624
2625 if (std::error_code EC = makeAbsolute(Path))
2626 return EC;
2627
2629
2630
2631 std::error_code EC = ExternalFS->getRealPath(Path, Output);
2632 if (!EC)
2633 return EC;
2634 }
2635
2637 if (!Result) {
2638
2639
2641 isFileNotFound(Result.getError()))
2642 return ExternalFS->getRealPath(Path, Output);
2643 return Result.getError();
2644 }
2645
2646
2647
2648 if (auto ExtRedirect = Result->getExternalRedirect()) {
2649 auto P = ExternalFS->getRealPath(*ExtRedirect, Output);
2651 isFileNotFound(P, Result->E)) {
2652
2653
2654
2655 return ExternalFS->getRealPath(Path, Output);
2656 }
2657 return P;
2658 }
2659
2660
2661
2663 Result->getPath(Output);
2664 return {};
2665 }
2667}
2668
2669std::unique_ptr
2672 StringRef YAMLFilePath, void *DiagContext,
2675 YAMLFilePath, DiagContext,
2676 std::move(ExternalFS));
2677}
2678
2682 auto Kind = SrcE->getKind();
2685 assert(DE && "Must be a directory");
2686 for (std::unique_ptrRedirectingFileSystem::Entry &SubEntry :
2687 llvm::make_range(DE->contents_begin(), DE->contents_end())) {
2688 Path.push_back(SubEntry->getName());
2690 Path.pop_back();
2691 }
2692 return;
2693 }
2694
2697 assert(DR && "Must be a directory remap");
2699 for (auto &Comp : Path)
2703 return;
2704 }
2705
2708 assert(FE && "Must be a file");
2710 for (auto &Comp : Path)
2713}
2714
2718 if (!RootResult)
2719 return;
2722 getVFSEntries(RootResult->E, Components, CollectedEntries);
2723}
2724
2726 static std::atomic UID;
2727 unsigned ID = ++UID;
2728
2729
2730 return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
2731}
2732
2733void YAMLVFSWriter::addEntry(StringRef VirtualPath, StringRef RealPath,
2734 bool IsDirectory) {
2738 Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
2739}
2740
2742 addEntry(VirtualPath, RealPath, false);
2743}
2744
2747 addEntry(VirtualPath, RealPath, true);
2748}
2749
2750namespace {
2751
2752class JSONWriter {
2755
2756 unsigned getDirIndent() { return 4 * DirStack.size(); }
2757 unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
2760 void startDirectory(StringRef Path);
2761 void endDirectory();
2763
2764public:
2766
2768 std::optional UseExternalNames,
2769 std::optional IsCaseSensitive,
2770 std::optional IsOverlayRelative, StringRef OverlayDir);
2771};
2772
2773}
2774
2775bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
2776 using namespace llvm::sys;
2777
2778
2781 IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
2782 if (*IParent != *IChild)
2783 return false;
2784 }
2785
2786 return IParent == EParent;
2787}
2788
2789StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
2791 assert(containedIn(Parent, Path));
2792 return Path.substr(Parent.size() + 1);
2793}
2794
2795void JSONWriter::startDirectory(StringRef Path) {
2796 StringRef Name =
2797 DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
2799 unsigned Indent = getDirIndent();
2800 OS.indent(Indent) << "{\n";
2801 OS.indent(Indent + 2) << "'type': 'directory',\n";
2803 OS.indent(Indent + 2) << "'contents': [\n";
2804}
2805
2806void JSONWriter::endDirectory() {
2807 unsigned Indent = getDirIndent();
2808 OS.indent(Indent + 2) << "]\n";
2809 OS.indent(Indent) << "}";
2810
2812}
2813
2814void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
2815 unsigned Indent = getFileIndent();
2816 OS.indent(Indent) << "{\n";
2817 OS.indent(Indent + 2) << "'type': 'file',\n";
2819 OS.indent(Indent + 2) << "'external-contents': \""
2821 OS.indent(Indent) << "}";
2822}
2823
2825 std::optional UseExternalNames,
2826 std::optional IsCaseSensitive,
2827 std::optional IsOverlayRelative,
2829 using namespace llvm::sys;
2830
2831 OS << "{\n"
2832 " 'version': 0,\n";
2833 if (IsCaseSensitive)
2834 OS << " 'case-sensitive': '" << (*IsCaseSensitive ? "true" : "false")
2835 << "',\n";
2836 if (UseExternalNames)
2837 OS << " 'use-external-names': '" << (*UseExternalNames ? "true" : "false")
2838 << "',\n";
2839 bool UseOverlayRelative = false;
2840 if (IsOverlayRelative) {
2841 UseOverlayRelative = *IsOverlayRelative;
2842 OS << " 'overlay-relative': '" << (UseOverlayRelative ? "true" : "false")
2843 << "',\n";
2844 }
2845 OS << " 'roots': [\n";
2846
2847 if (!Entries.empty()) {
2848 const YAMLVFSEntry &Entry = Entries.front();
2849
2850 startDirectory(
2852 );
2853
2855 if (UseOverlayRelative) {
2857 "Overlay dir must be contained in RPath");
2859 }
2860
2861 bool IsCurrentDirEmpty = true;
2862 if (.IsDirectory) {
2864 IsCurrentDirEmpty = false;
2865 }
2866
2867 for (const auto &Entry : Entries.slice(1)) {
2868 StringRef Dir =
2870 if (Dir == DirStack.back()) {
2871 if (!IsCurrentDirEmpty) {
2872 OS << ",\n";
2873 }
2874 } else {
2875 bool IsDirPoppedFromStack = false;
2876 while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
2877 OS << "\n";
2878 endDirectory();
2879 IsDirPoppedFromStack = true;
2880 }
2881 if (IsDirPoppedFromStack || !IsCurrentDirEmpty) {
2882 OS << ",\n";
2883 }
2884 startDirectory(Dir);
2885 IsCurrentDirEmpty = true;
2886 }
2888 if (UseOverlayRelative) {
2890 "Overlay dir must be contained in RPath");
2892 }
2893 if (.IsDirectory) {
2895 IsCurrentDirEmpty = false;
2896 }
2897 }
2898
2899 while (!DirStack.empty()) {
2900 OS << "\n";
2901 endDirectory();
2902 }
2903 OS << "\n";
2904 }
2905
2906 OS << " ]\n"
2907 << "}\n";
2908}
2909
2912 return LHS.VPath < RHS.VPath;
2913 });
2914
2915 JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
2916 IsOverlayRelative, OverlayDir);
2917}
2918
2920 FileSystem &FS_, const Twine &Path, std::error_code &EC)
2921 : FS(&FS_) {
2924 State = std::make_shareddetail::RecDirIterState();
2925 State->Stack.push_back(I);
2926 }
2927}
2928
2931 assert(FS && State && !State->Stack.empty() && "incrementing past end");
2932 assert(!State->Stack.back()->path().empty() && "non-canonical end iterator");
2934
2935 if (State->HasNoPushRequest)
2936 State->HasNoPushRequest = false;
2937 else {
2940 FS->dir_begin(State->Stack.back()->path(), EC);
2941 if (I != End) {
2942 State->Stack.push_back(I);
2943 return *this;
2944 }
2945 }
2946 }
2947
2948 while (!State->Stack.empty() && State->Stack.back().increment(EC) == End)
2949 State->Stack.pop_back();
2950
2951 if (State->Stack.empty())
2952 State.reset();
2953
2954 return *this;
2955}
2956
2958 unsigned IndentLevel) const {
2959 printIndent(OS, IndentLevel);
2960 OS << "TracingFileSystem\n";
2961 if (Type == PrintType::Summary)
2962 return;
2963
2964 printIndent(OS, IndentLevel);
2966 printIndent(OS, IndentLevel);
2968 printIndent(OS, IndentLevel);
2970 printIndent(OS, IndentLevel);
2972 printIndent(OS, IndentLevel);
2974 printIndent(OS, IndentLevel);
2976
2977 if (Type == PrintType::Contents)
2978 Type = PrintType::Summary;
2979 getUnderlyingFS().print(OS, Type, IndentLevel + 1);
2980}
2981
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
Provides ErrorOr smart pointer.
static void makeAbsolute(vfs::FileSystem &VFS, SmallVectorImpl< char > &Path)
Make Path absolute.
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)
static StringRef getName(Value *V)
This file defines the SmallString class.
This file defines the SmallVector class.
StringSet - A set-like wrapper for the StringMap.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
LLVM_ABI const file_t kInvalidFile
static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, SmallVectorImpl< StringRef > &Path, SmallVectorImpl< YAMLVFSEntry > &Entries)
Definition VirtualFileSystem.cpp:2679
static Status getRedirectedFileStatus(const Twine &OriginalPath, bool UseExternalNames, Status ExternalStatus)
Definition VirtualFileSystem.cpp:2384
static bool pathHasTraversal(StringRef Path)
Definition VirtualFileSystem.cpp:173
static bool isTraversalComponent(StringRef Component)
Definition VirtualFileSystem.cpp:169
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
iterator find(const_arg_type_t< KeyT > Val)
Represents either an error or a value T.
std::error_code getError() const
Error takeError()
Take ownership of the stored error.
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...
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
StringRef getBuffer() const
Represents a location in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
StringRef - Represent a constant reference to a string, i.e.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
LLVM_ABI void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
LLVM Value Representation.
An opaque object representing a hash code.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
const std::string & path() const
directory_iterator - Iterates through the entries in path.
directory_iterator & increment(std::error_code &ec)
Represents the result of a call to sys::fs::status().
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.
Definition VirtualFileSystem.cpp:149
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 makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
Definition VirtualFileSystem.cpp:128
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.
Definition VirtualFileSystem.cpp:140
void printIndent(raw_ostream &OS, unsigned IndentLevel) const
LLVM_DUMP_METHOD void dump() const
Definition VirtualFileSystem.cpp:165
void print(raw_ostream &OS, PrintType Type=PrintType::Contents, unsigned IndentLevel=0) const
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)
This is a convenience method that opens a file, gets its content and then closes the file.
Definition VirtualFileSystem.cpp:118
llvm::ErrorOr< bool > equivalent(const Twine &A, const Twine &B)
Definition VirtualFileSystem.cpp:154
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
Definition VirtualFileSystem.cpp:145
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
static ErrorOr< std::unique_ptr< File > > getWithPath(ErrorOr< std::unique_ptr< File > > Result, const Twine &P)
Definition VirtualFileSystem.cpp:2545
virtual ~File()
Destroy the file after closing it (if open).
Adaptor from InMemoryDir::iterator to directory_iterator.
Definition VirtualFileSystem.cpp:1105
DirIterator(const InMemoryFileSystem *FS, const detail::InMemoryDirectory &Dir, std::string RequestedDirName)
Definition VirtualFileSystem.cpp:1143
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
Definition VirtualFileSystem.cpp:1151
std::error_code isLocal(const Twine &Path, bool &Result) override
Definition VirtualFileSystem.cpp:1203
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Definition VirtualFileSystem.cpp:1158
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....
Definition VirtualFileSystem.cpp:1191
~InMemoryFileSystem() override
static constexpr size_t MaxSymlinkDepth
Arbitrary max depth to search through symlinks.
InMemoryFileSystem(bool UseNormalizedPaths=true)
Definition VirtualFileSystem.cpp:839
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition VirtualFileSystem.cpp:1208
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
bool addHardLink(const Twine &NewLink, const Twine &Target)
Add a hard link to a file.
Definition VirtualFileSystem.cpp:1042
std::string toString() const
Definition VirtualFileSystem.cpp:849
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.
Definition VirtualFileSystem.cpp:949
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.
Definition VirtualFileSystem.cpp:1061
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Definition VirtualFileSystem.cpp:1174
llvm::ErrorOr< Status > status(const Twine &Path) override
Definition VirtualFileSystem.cpp:1081
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Definition VirtualFileSystem.cpp:1089
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Definition VirtualFileSystem.cpp:616
void visitChildFileSystems(VisitCallbackTy Callback) override
Definition VirtualFileSystem.cpp:513
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Definition VirtualFileSystem.cpp:474
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Definition VirtualFileSystem.cpp:505
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Definition VirtualFileSystem.cpp:491
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
Definition VirtualFileSystem.cpp:447
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
Definition VirtualFileSystem.cpp:443
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Definition VirtualFileSystem.cpp:485
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
Definition VirtualFileSystem.cpp:498
bool exists(const Twine &Path) override
Definition VirtualFileSystem.cpp:464
llvm::ErrorOr< Status > status(const Twine &Path) override
Definition VirtualFileSystem.cpp:454
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
FileSystemList::reverse_iterator iterator
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition VirtualFileSystem.cpp:520
Directory iterator implementation for RedirectingFileSystem's directory entries.
Definition VirtualFileSystem.cpp:1270
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
Definition VirtualFileSystem.cpp:1307
RedirectingFSDirIterImpl(const Twine &Path, RedirectingFileSystem::DirectoryEntry::iterator Begin, RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)
Definition VirtualFileSystem.cpp:1300
A helper class to hold the common YAML parsing state.
Definition VirtualFileSystem.cpp:1629
RedirectingFileSystemParser(yaml::Stream &S)
Definition VirtualFileSystem.cpp:2049
static RedirectingFileSystem::Entry * lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name, RedirectingFileSystem::Entry *ParentEntry=nullptr)
Definition VirtualFileSystem.cpp:1739
bool parse(yaml::Node *Root, RedirectingFileSystem *FS)
Definition VirtualFileSystem.cpp:2052
decltype(Contents)::iterator iterator
A single file or directory in the VFS.
StringRef getName() const
EntryKind getKind() const
A virtual file system parsed from a YAML file.
@ 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.
Definition VirtualFileSystem.cpp:2470
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition VirtualFileSystem.cpp:1568
friend class RedirectingFileSystemParser
std::vector< llvm::StringRef > getRoots() const
Definition VirtualFileSystem.cpp:1560
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Definition VirtualFileSystem.cpp:1439
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...
Definition VirtualFileSystem.cpp:2315
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.
Definition VirtualFileSystem.cpp:1547
void visitChildFileSystems(VisitCallbackTy Callback) override
Definition VirtualFileSystem.cpp:1621
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Gets real path of Path e.g.
Definition VirtualFileSystem.cpp:2620
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the text file at Path, if one exists.
Definition VirtualFileSystem.cpp:2559
void setOverlayFileDir(StringRef PrefixDir)
Definition VirtualFileSystem.cpp:1539
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition VirtualFileSystem.cpp:1354
void setRedirection(RedirectingFileSystem::RedirectKind Kind)
Definition VirtualFileSystem.cpp:1555
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
Definition VirtualFileSystem.cpp:1372
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 ...
Definition VirtualFileSystem.cpp:2182
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition VirtualFileSystem.cpp:1359
StringRef getOverlayFileDir() const
Definition VirtualFileSystem.cpp:1543
void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel=0) const
Definition VirtualFileSystem.cpp:1585
The result of a status operation.
llvm::sys::fs::UniqueID getUniqueID() const
LLVM_ABI bool equivalent(const Status &Other) const
Definition VirtualFileSystem.cpp:92
static LLVM_ABI Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
Definition VirtualFileSystem.cpp:80
LLVM_ABI bool isStatusKnown() const
Definition VirtualFileSystem.cpp:107
LLVM_ABI bool exists() const
Definition VirtualFileSystem.cpp:109
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.
Definition VirtualFileSystem.cpp:74
LLVM_ABI bool isOther() const
Definition VirtualFileSystem.cpp:101
LLVM_ABI bool isSymlink() const
Definition VirtualFileSystem.cpp:105
llvm::sys::TimePoint getLastModificationTime() const
llvm::sys::fs::file_type getType() const
LLVM_ABI bool isRegularFile() const
Definition VirtualFileSystem.cpp:99
LLVM_ABI bool isDirectory() const
Definition VirtualFileSystem.cpp:97
std::size_t NumOpenFileForReadCalls
std::size_t NumIsLocalCalls
std::size_t NumExistsCalls
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition VirtualFileSystem.cpp:2957
std::size_t NumDirBeginCalls
std::size_t NumGetRealPathCalls
std::size_t NumStatusCalls
LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath)
Definition VirtualFileSystem.cpp:2741
LLVM_ABI void write(llvm::raw_ostream &OS)
Definition VirtualFileSystem.cpp:2910
LLVM_ABI void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)
Definition VirtualFileSystem.cpp:2745
InMemoryDirectory(Status Stat)
Definition VirtualFileSystem.cpp:769
InMemoryNode * addChild(StringRef Name, std::unique_ptr< InMemoryNode > Child)
Definition VirtualFileSystem.cpp:788
Status getStatus(const Twine &RequestedName) const override
Return the Status for this node.
Definition VirtualFileSystem.cpp:775
const_iterator end() const
Definition VirtualFileSystem.cpp:795
static bool classof(const InMemoryNode *N)
Definition VirtualFileSystem.cpp:805
InMemoryNode * getChild(StringRef Name) const
Definition VirtualFileSystem.cpp:781
const_iterator begin() const
Definition VirtualFileSystem.cpp:794
UniqueID getUniqueID() const
Definition VirtualFileSystem.cpp:779
decltype(Entries)::const_iterator const_iterator
Definition VirtualFileSystem.cpp:792
std::string toString(unsigned Indent) const override
Definition VirtualFileSystem.cpp:797
Status getStatus(const Twine &RequestedName) const override
Return the Status for this node.
Definition VirtualFileSystem.cpp:671
std::string toString(unsigned Indent) const override
Definition VirtualFileSystem.cpp:676
InMemoryFile(Status Stat, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Definition VirtualFileSystem.cpp:667
static bool classof(const InMemoryNode *N)
Definition VirtualFileSystem.cpp:680
llvm::MemoryBuffer * getBuffer() const
Definition VirtualFileSystem.cpp:674
The in memory file system is a tree of Nodes.
Definition VirtualFileSystem.cpp:641
StringRef getFileName() const
Get the filename of this node (the name without the directory part).
Definition VirtualFileSystem.cpp:657
InMemoryNodeKind getKind() const
Definition VirtualFileSystem.cpp:658
virtual ~InMemoryNode()=default
InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
Definition VirtualFileSystem.cpp:646
virtual std::string toString(unsigned Indent) const =0
virtual Status getStatus(const Twine &RequestedName) const =0
Return the Status for this node.
A member of a directory, yielded by a directory_iterator.
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 & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
recursive_directory_iterator()=default
Construct an 'end' iterator.
LLVM_ABI recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
Definition VirtualFileSystem.cpp:2930
Abstract base class for all Nodes.
This class represents a YAML stream potentially containing multiple documents.
LLVM_ABI document_iterator end()
LLVM_ABI document_iterator begin()
LLVM_ABI void printError(Node *N, const Twine &Msg, SourceMgr::DiagKind Kind=SourceMgr::DK_Error)
Iterator abstraction for Documents over a Stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Resolved
Queried, materialization begun.
LLVM_ABI std::error_code closeFile(file_t &F)
Close the file object.
LLVM_ABI const file_t kInvalidFile
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
file_type
An enumeration for the file system's view of the type.
LLVM_ABI std::error_code set_current_path(const Twine &path)
Set the current path.
LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
LLVM_ABI Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
LLVM_ABI std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
LLVM_ABI std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
LLVM_ABI std::error_code is_local(const Twine &path, bool &result)
Is the file mounted on a local filesystem?
LLVM_ABI std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
LLVM_ABI bool is_directory(const basic_file_status &status)
Does status represent a directory?
LLVM_ABI StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
LLVM_ABI StringRef root_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get root path.
LLVM_ABI const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get begin iterator over path.
LLVM_ABI bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
LLVM_ABI void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
LLVM_ABI StringRef remove_leading_dotslash(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
LLVM_ABI reverse_iterator rend(StringRef path LLVM_LIFETIME_BOUND)
Get reverse end iterator over path.
LLVM_ABI reverse_iterator rbegin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get reverse begin iterator over path.
LLVM_ABI const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
LLVM_ABI bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
InMemoryNodeKind
Definition VirtualFileSystem.cpp:632
@ IME_File
Definition VirtualFileSystem.cpp:633
@ IME_HardLink
Definition VirtualFileSystem.cpp:635
@ IME_Directory
Definition VirtualFileSystem.cpp:634
@ IME_SymbolicLink
Definition VirtualFileSystem.cpp:636
std::error_code make_error_code(OutputErrorCode EV)
LLVM_ABI void collectVFSEntries(RedirectingFileSystem &VFS, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries)
Collect all pairs of <virtual path, real path> entries from the VFS.
Definition VirtualFileSystem.cpp:2715
LLVM_ABI std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition VirtualFileSystem.cpp:405
static sys::fs::UniqueID getFileID(sys::fs::UniqueID Parent, llvm::StringRef Name, llvm::StringRef Contents)
Definition VirtualFileSystem.cpp:819
LLVM_ABI llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
Definition VirtualFileSystem.cpp:2725
static sys::fs::UniqueID getUniqueID(hash_code Hash)
Definition VirtualFileSystem.cpp:815
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition VirtualFileSystem.cpp:399
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.
static sys::fs::UniqueID getDirectoryID(sys::fs::UniqueID Parent, llvm::StringRef Name)
Definition VirtualFileSystem.cpp:824
LLVM_ABI std::string escape(StringRef Input, bool EscapePrintable=true)
Escape Input for a double quoted scalar; if EscapePrintable is true, all UTF8 sequences will be escap...
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
IntrusiveRefCntPtr< T > makeIntrusiveRefCnt(Args &&...A)
Factory function for creating intrusive ref counted pointers.
@ no_such_file_or_directory
@ operation_not_permitted
FunctionAddr VTableAddr uintptr_t uintptr_t Version
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
LLVM_ABI std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
Implement std::hash so that hash_code can be used in STL containers.
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)
Definition VirtualFileSystem.cpp:2277
LLVM_ABI void getPath(llvm::SmallVectorImpl< char > &Path) const
Get the (canonical) path of the found entry.
Definition VirtualFileSystem.cpp:2292
llvm::SmallVector< Entry *, 32 > Parents
Chain of parent directory entries for E.
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
directory_entry CurrentEntry
LLVM_ABI Status makeStatus() const
Definition VirtualFileSystem.cpp:829
llvm::sys::fs::file_type Type
std::unique_ptr< llvm::MemoryBuffer > Buffer
llvm::sys::fs::perms Perms
llvm::sys::fs::UniqueID DirUID