24#include "llvm/Config/llvm-config.h"
50#include <system_error>
76 return Status(In.getName(), In.getUniqueID(), In.getLastModificationTime(),
77 In.getUser(), In.getGroup(), NewSize, In.getType(),
82 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
83 In.getUser(), In.getGroup(), In.getSize(), In.getType(),
88 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
89 In.getUser(), In.getGroup(), In.getSize(), In.type(),
120 bool RequiresNullTerminator,
bool IsVolatile) {
125 return (*F)->getBuffer(
Name, FileSize, RequiresNullTerminator, IsVolatile);
134 return WorkingDir.getError();
154#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
160 return Component.equals(
"..") || Component.equals(
".");
180class RealFile :
public File {
181 friend class RealFileSystem;
185 std::string RealName;
188 : FD(RawFD), S(NewName, {}, {}, {}, {}, {},
190 RealName(NewRealPathName.str()) {
191 assert(FD != kInvalidFile &&
"Invalid or inactive file descriptor");
195 ~RealFile()
override;
201 bool RequiresNullTerminator,
202 bool IsVolatile)
override;
203 std::error_code close()
override;
204 void setPath(
const Twine &Path)
override;
209RealFile::~RealFile() { close(); }
212 assert(FD != kInvalidFile &&
"cannot stat closed file");
213 if (!S.isStatusKnown()) {
223 return RealName.empty() ? S.getName().str() : RealName;
227RealFile::getBuffer(
const Twine &
Name, int64_t FileSize,
228 bool RequiresNullTerminator,
bool IsVolatile) {
229 assert(FD != kInvalidFile &&
"cannot get buffer for closed file");
234std::error_code RealFile::close() {
240void RealFile::setPath(
const Twine &Path) {
241 RealName =
Path.str();
258 explicit RealFileSystem(
bool LinkCWDToProcess) {
259 if (!LinkCWDToProcess) {
264 WD = WorkingDirectory{PWD, PWD};
266 WD = WorkingDirectory{PWD, RealPWD};
275 std::error_code setCurrentWorkingDirectory(
const Twine &Path)
override;
276 std::error_code isLocal(
const Twine &Path,
bool &Result)
override;
277 std::error_code getRealPath(
const Twine &Path,
282 unsigned IndentLevel)
const override;
290 Path.toVector(Storage);
295 struct WorkingDirectory {
301 std::optional<llvm::ErrorOr<WorkingDirectory>> WD;
309 if (std::error_code EC =
316RealFileSystem::openFileForRead(
const Twine &
Name) {
322 return std::unique_ptr<File>(
323 new RealFile(*FDOrErr,
Name.str(), RealName.
str()));
328 return std::string(WD->get().Specified.str());
330 return WD->getError();
335 return std::string(Dir.
str());
338std::error_code RealFileSystem::setCurrentWorkingDirectory(
const Twine &Path) {
343 adjustPath(Path, Storage).toVector(Absolute);
348 return std::make_error_code(std::errc::not_a_directory);
352 return std::error_code();
355std::error_code RealFileSystem::isLocal(
const Twine &Path,
bool &Result) {
361RealFileSystem::getRealPath(
const Twine &Path,
368 unsigned IndentLevel)
const {
369 printIndent(
OS, IndentLevel);
370 OS <<
"RealFileSystem using ";
384 return std::make_unique<RealFileSystem>(
false);
393 RealFSDirIter(
const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
398 std::error_code increment()
override {
411 std::error_code &EC) {
414 std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC));
446 auto Result = (*I)->openFileForRead(Path);
456 return FSList.
front()->getCurrentWorkingDirectory();
461 for (
auto &FS : FSList)
462 if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
468 for (
auto &FS : FSList)
469 if (FS->exists(Path))
470 return FS->isLocal(Path, Result);
477 for (
const auto &FS : FSList)
478 if (FS->exists(Path))
479 return FS->getRealPath(Path, Output);
484 unsigned IndentLevel)
const {
486 OS <<
"OverlayFileSystem\n";
493 FS->print(
OS,
Type, IndentLevel + 1);
513 std::error_code incrementIter(
bool IsFirstTime) {
514 while (!IterList.
empty()) {
515 CurrentDirIter = IterList.
back();
522 return errc::no_such_file_or_directory;
526 std::error_code incrementDirIter(
bool IsFirstTime) {
528 "incrementing past end");
533 EC = incrementIter(IsFirstTime);
537 std::error_code incrementImpl(
bool IsFirstTime) {
539 std::error_code
EC = incrementDirIter(IsFirstTime);
544 CurrentEntry = *CurrentDirIter;
554 std::error_code &EC) {
555 for (
auto FS : FileSystems) {
558 if (FEC && FEC != errc::no_such_file_or_directory) {
565 EC = incrementImpl(
true);
570 : IterList(DirIters.
begin(), DirIters.
end()) {
571 EC = incrementImpl(
true);
574 std::error_code increment()
override {
return incrementImpl(
false); }
580 std::error_code &EC) {
582 std::make_shared<CombiningDirIterImpl>(FSList, Dir.
str(), EC));
588void ProxyFileSystem::anchor() {}
606 std::string FileName;
610 : Kind(Kind), FileName(
std::
string(
llvm::sys::path::filename(FileName))) {
622 virtual std::string
toString(
unsigned Indent)
const = 0;
627 std::unique_ptr<llvm::MemoryBuffer> Buffer;
635 return Status::copyWithNewName(Stat, RequestedName);
639 std::string
toString(
unsigned Indent)
const override {
640 return (std::string(Indent,
' ') + Stat.
getName() +
"\n").str();
650class InMemoryHardLink :
public InMemoryNode {
651 const InMemoryFile &ResolvedFile;
654 InMemoryHardLink(
StringRef Path,
const InMemoryFile &ResolvedFile)
655 : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
656 const InMemoryFile &getResolvedFile()
const {
return ResolvedFile; }
658 Status getStatus(
const Twine &RequestedName)
const override {
659 return ResolvedFile.getStatus(RequestedName);
662 std::string
toString(
unsigned Indent)
const override {
663 return std::string(Indent,
' ') +
"HardLink to -> " +
664 ResolvedFile.toString(0);
667 static bool classof(
const InMemoryNode *
N) {
672class InMemorySymbolicLink :
public InMemoryNode {
673 std::string TargetPath;
681 std::string
toString(
unsigned Indent)
const override {
682 return std::string(Indent,
' ') +
"SymbolicLink to -> " + TargetPath;
685 Status getStatus(
const Twine &RequestedName)
const override {
686 return Status::copyWithNewName(Stat, RequestedName);
689 StringRef getTargetPath()
const {
return TargetPath; }
691 static bool classof(
const InMemoryNode *
N) {
699class InMemoryFileAdaptor :
public File {
700 const InMemoryFile &
Node;
702 std::string RequestedName;
705 explicit InMemoryFileAdaptor(
const InMemoryFile &
Node,
706 std::string RequestedName)
710 return Node.getStatus(RequestedName);
714 getBuffer(
const Twine &
Name, int64_t FileSize,
bool RequiresNullTerminator,
715 bool IsVolatile)
override {
721 std::error_code close()
override {
return {}; }
723 void setPath(
const Twine &Path)
override { RequestedName =
Path.str(); }
729 std::map<std::string, std::unique_ptr<InMemoryNode>> Entries;
739 return Status::copyWithNewName(Stat, RequestedName);
745 auto I = Entries.find(
Name.str());
746 if (
I != Entries.end())
747 return I->second.get();
752 return Entries.emplace(
Name, std::move(Child)).first->second.get();
760 std::string
toString(
unsigned Indent)
const override {
762 (std::string(Indent,
' ') + Stat.
getName() +
"\n").str();
763 for (
const auto &Entry : Entries)
764 Result += Entry.second->toString(Indent + 2);
794 (
Type == sys::fs::file_type::directory_file)
796 :
getFileID(DirUID,
Name, Buffer ? Buffer->getBuffer() :
"");
799 Group, Buffer ? Buffer->getBufferSize() : 0,
Type, Perms);
803 : Root(new detail::InMemoryDirectory(
806 llvm::sys::fs::file_type::directory_file,
807 llvm::sys::fs::perms::all_all))),
808 UseNormalizedPaths(UseNormalizedPaths) {}
813 return Root->toString(0);
816bool InMemoryFileSystem::addFile(
const Twine &
P, time_t ModificationTime,
817 std::unique_ptr<llvm::MemoryBuffer> Buffer,
818 std::optional<uint32_t>
User,
819 std::optional<uint32_t> Group,
820 std::optional<llvm::sys::fs::file_type>
Type,
821 std::optional<llvm::sys::fs::perms> Perms,
822 MakeNodeFn MakeNode) {
839 const auto ResolvedUser =
User.value_or(0);
840 const auto ResolvedGroup = Group.value_or(0);
855 std::move(Buffer), ResolvedUser, ResolvedGroup,
856 ResolvedType, ResolvedPerms}));
862 StringRef(Path.str().begin(),
Name.end() - Path.str().begin()),
866 Dir = cast<detail::InMemoryDirectory>(Dir->
addChild(
867 Name, std::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
871 if (
auto *NewDir = dyn_cast<detail::InMemoryDirectory>(
Node)) {
875 isa<detail::InMemoryHardLink>(
Node)) &&
876 "Must be either file, hardlink or directory!");
883 if (
auto Link = dyn_cast<detail::InMemoryHardLink>(
Node)) {
884 return Link->getResolvedFile().getBuffer()->getBuffer() ==
887 return cast<detail::InMemoryFile>(
Node)->getBuffer()->getBuffer() ==
893bool InMemoryFileSystem::addFile(
const Twine &
P, time_t ModificationTime,
894 std::unique_ptr<llvm::MemoryBuffer> Buffer,
895 std::optional<uint32_t>
User,
896 std::optional<uint32_t> Group,
897 std::optional<llvm::sys::fs::file_type>
Type,
898 std::optional<llvm::sys::fs::perms> Perms) {
899 return addFile(
P, ModificationTime, std::move(Buffer),
User, Group,
Type,
902 -> std::unique_ptr<detail::InMemoryNode> {
905 return std::make_unique<detail::InMemoryDirectory>(Stat);
906 return std::make_unique<detail::InMemoryFile>(
907 Stat, std::move(NNI.
Buffer));
912 const Twine &
P, time_t ModificationTime,
914 std::optional<uint32_t> Group, std::optional<llvm::sys::fs::file_type>
Type,
915 std::optional<llvm::sys::fs::perms> Perms) {
917 std::move(
User), std::move(Group), std::move(
Type),
920 -> std::unique_ptr<detail::InMemoryNode> {
923 return std::make_unique<detail::InMemoryDirectory>(Stat);
924 return std::make_unique<detail::InMemoryFile>(
925 Stat, std::move(NNI.
Buffer));
930InMemoryFileSystem::lookupNode(
const Twine &
P,
bool FollowFinalSymlink,
931 size_t SymlinkDepth)
const {
954 if (
auto Symlink = dyn_cast<detail::InMemorySymbolicLink>(Node)) {
957 if (
I ==
E && !FollowFinalSymlink)
972 lookupNode(TargetPath,
true, SymlinkDepth + 1);
976 if (!isa<detail::InMemoryDirectory>(*
Target))
980 Dir = cast<detail::InMemoryDirectory>(*
Target);
985 if (
auto File = dyn_cast<detail::InMemoryFile>(Node)) {
992 if (
auto File = dyn_cast<detail::InMemoryHardLink>(
Node)) {
998 Dir = cast<detail::InMemoryDirectory>(
Node);
1006 auto NewLinkNode = lookupNode(NewLink,
false);
1010 auto TargetNode = lookupNode(
Target,
true);
1013 if (!TargetNode || NewLinkNode || !isa<detail::InMemoryFile>(*TargetNode))
1015 return addFile(NewLink, 0,
nullptr, std::nullopt, std::nullopt, std::nullopt,
1017 return std::make_unique<detail::InMemoryHardLink>(
1019 *cast<detail::InMemoryFile>(*TargetNode));
1025 std::optional<uint32_t>
User, std::optional<uint32_t> Group,
1026 std::optional<llvm::sys::fs::perms> Perms) {
1027 auto NewLinkNode = lookupNode(NewLink,
false);
1033 Target.toVector(TargetStr);
1035 return addFile(NewLinkStr, ModificationTime,
nullptr,
User, Group,
1038 return std::make_unique<detail::InMemorySymbolicLink>(
1044 auto Node = lookupNode(Path,
true);
1046 return (*Node)->getStatus(Path);
1047 return Node.getError();
1052 auto Node = lookupNode(Path,
true);
1054 return Node.getError();
1058 if (
auto *
F = dyn_cast<detail::InMemoryFile>(*Node))
1059 return std::unique_ptr<File>(
1060 new detail::InMemoryFileAdaptor(*
F, Path.str()));
1071 std::string RequestedDirName;
1073 void setCurrentEntry() {
1078 switch (
I->second->getKind()) {
1087 if (
auto SymlinkTarget =
1088 FS->lookupNode(Path,
true)) {
1089 Path = SymlinkTarget.getName();
1090 Type = (*SymlinkTarget)->getStatus(Path).getType();
1107 std::string RequestedDirName)
1108 : FS(FS),
I(Dir.begin()), E(Dir.end()),
1109 RequestedDirName(
std::
move(RequestedDirName)) {
1121 std::error_code &EC) {
1122 auto Node = lookupNode(Dir,
true);
1124 EC = Node.getError();
1128 if (
auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
1130 std::make_shared<DirIterator>(
this, *DirNode, Dir.
str()));
1149 WorkingDirectory = std::string(Path.str());
1157 if (!CWD || CWD->empty())
1159 Path.toVector(Output);
1172 unsigned IndentLevel)
const {
1174 OS <<
"InMemoryFileSystem\n";
1189 const size_t n = Path.find_first_of(
"/\\");
1191 if (n !=
static_cast<size_t>(-1))
1211static bool isFileNotFound(std::error_code EC,
1213 if (
E && !isa<RedirectingFileSystem::DirectoryRemapEntry>(
E))
1224 if (
auto ExternalWorkingDirectory =
1225 ExternalFS->getCurrentWorkingDirectory()) {
1226 WorkingDirectory = *ExternalWorkingDirectory;
1237 std::error_code incrementImpl(
bool IsFirstTime) {
1238 assert((IsFirstTime || Current !=
End) &&
"cannot iterate past end");
1241 if (Current !=
End) {
1245 switch ((*Current)->getKind()) {
1266 : Dir(Path.str()), Current(Begin),
End(
End) {
1267 EC = incrementImpl(
true);
1271 return incrementImpl(
false);
1285 RedirectingFSDirRemapIterImpl(std::string DirPath,
1287 : Dir(
std::
move(DirPath)), DirStyle(getExistingStyle(Dir)),
1288 ExternalIter(ExtIter) {
1293 void setCurrentEntry() {
1304 std::error_code increment()
override {
1318 return WorkingDirectory;
1328 Path.toVector(AbsolutePath);
1329 if (std::error_code EC = makeAbsolute(AbsolutePath))
1331 WorkingDirectory = std::string(AbsolutePath.
str());
1340 if (makeCanonical(Path))
1343 return ExternalFS->isLocal(Path, Result);
1358 return WorkingDir.getError();
1360 return makeAbsolute(WorkingDir.get(), Path);
1364RedirectingFileSystem::makeAbsolute(
StringRef WorkingDir,
1370 if (!WorkingDir.
empty() &&
1374 return std::error_code();
1386 std::string
Result = std::string(WorkingDir);
1403 std::error_code &EC) {
1407 EC = makeCanonical(Path);
1414 isFileNotFound(Result.getError()))
1415 return ExternalFS->dir_begin(Path, EC);
1417 EC = Result.getError();
1425 isFileNotFound(S.
getError(), Result->E))
1426 return ExternalFS->dir_begin(Dir, EC);
1432 if (!S->isDirectory()) {
1440 std::error_code RedirectEC;
1441 if (
auto ExtRedirect = Result->getExternalRedirect()) {
1442 auto RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
1443 RedirectIter = ExternalFS->dir_begin(*ExtRedirect, RedirectEC);
1445 if (!RE->useExternalName(UseExternalNames)) {
1449 std::string(Path), RedirectIter));
1452 auto DE = cast<DirectoryEntry>(Result->E);
1455 Path, DE->contents_begin(), DE->contents_end(), RedirectEC));
1468 return RedirectIter;
1471 std::error_code ExternalEC;
1482 switch (Redirection) {
1496 std::make_shared<CombiningDirIterImpl>(Iters, EC)};
1503 OverlayFileDir = Dir.
str();
1507 return OverlayFileDir;
1524 std::vector<StringRef> R;
1525 R.reserve(Roots.size());
1526 for (
const auto &Root : Roots)
1527 R.push_back(Root->getName());
1532 unsigned IndentLevel)
const {
1534 OS <<
"RedirectingFileSystem (UseExternalNames: "
1535 << (UseExternalNames ?
"true" :
"false") <<
")\n";
1539 for (
const auto &Root : Roots)
1543 OS <<
"ExternalFS:\n";
1550 unsigned IndentLevel)
const {
1552 OS <<
"'" <<
E->getName() <<
"'";
1554 switch (
E->getKind()) {
1556 auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(
E);
1559 for (std::unique_ptr<Entry> &SubEntry :
1566 auto *RE = cast<RedirectingFileSystem::RemapEntry>(
E);
1567 OS <<
" -> '" << RE->getExternalContentsPath() <<
"'";
1568 switch (RE->getUseName()) {
1572 OS <<
" (UseExternalName: true)";
1575 OS <<
" (UseExternalName: false)";
1593 const auto *S = dyn_cast<yaml::ScalarNode>(
N);
1596 error(
N,
"expected string");
1599 Result = S->getValue(Storage);
1604 bool parseScalarBool(
yaml::Node *
N,
bool &Result) {
1607 if (!parseScalarString(
N,
Value, Storage))
1610 if (
Value.equals_insensitive(
"true") ||
Value.equals_insensitive(
"on") ||
1611 Value.equals_insensitive(
"yes") ||
Value ==
"1") {
1614 }
else if (
Value.equals_insensitive(
"false") ||
1615 Value.equals_insensitive(
"off") ||
1616 Value.equals_insensitive(
"no") ||
Value ==
"0") {
1621 error(
N,
"expected boolean value");
1625 std::optional<RedirectingFileSystem::RedirectKind>
1629 if (!parseScalarString(
N,
Value, Storage))
1630 return std::nullopt;
1632 if (
Value.equals_insensitive(
"fallthrough")) {
1634 }
else if (
Value.equals_insensitive(
"fallback")) {
1636 }
else if (
Value.equals_insensitive(
"redirect-only")) {
1639 return std::nullopt;
1642 std::optional<RedirectingFileSystem::RootRelativeKind>
1646 if (!parseScalarString(
N,
Value, Storage))
1647 return std::nullopt;
1648 if (
Value.equals_insensitive(
"cwd")) {
1650 }
else if (
Value.equals_insensitive(
"overlay-dir")) {
1653 return std::nullopt;
1660 KeyStatus(
bool Required =
false) : Required(Required) {}
1663 using KeyStatusPair = std::pair<StringRef, KeyStatus>;
1668 if (!Keys.
count(Key)) {
1669 error(KeyNode,
"unknown key");
1672 KeyStatus &S = Keys[Key];
1674 error(KeyNode,
Twine(
"duplicate key '") + Key +
"'");
1683 for (
const auto &
I : Keys) {
1684 if (
I.second.Required && !
I.second.Seen) {
1685 error(Obj,
Twine(
"missing key '") +
I.first +
"'");
1697 for (
const auto &Root : FS->Roots) {
1698 if (
Name.equals(Root->getName())) {
1699 ParentEntry = Root.get();
1704 auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1705 for (std::unique_ptr<RedirectingFileSystem::Entry> &
Content :
1708 dyn_cast<RedirectingFileSystem::DirectoryEntry>(
Content.get());
1709 if (DirContent &&
Name.equals(
Content->getName()))
1715 std::unique_ptr<RedirectingFileSystem::Entry>
E =
1716 std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1718 std::chrono::system_clock::now(), 0, 0, 0,
1722 FS->Roots.push_back(std::move(
E));
1723 ParentEntry = FS->Roots.back().get();
1727 auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1728 DE->addContent(std::move(
E));
1729 return DE->getLastContent();
1739 auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
1745 for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
1747 uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
1751 assert(NewParentE &&
"Parent entry must exist");
1752 auto *DR = cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
1753 auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1755 std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1756 Name, DR->getExternalContentsPath(), DR->getUseName()));
1760 assert(NewParentE &&
"Parent entry must exist");
1761 auto *FE = cast<RedirectingFileSystem::FileEntry>(SrcE);
1762 auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1763 DE->addContent(std::make_unique<RedirectingFileSystem::FileEntry>(
1764 Name, FE->getExternalContentsPath(), FE->getUseName()));
1770 std::unique_ptr<RedirectingFileSystem::Entry>
1772 auto *
M = dyn_cast<yaml::MappingNode>(
N);
1774 error(
N,
"expected mapping node for file or directory entry");
1778 KeyStatusPair Fields[] = {
1779 KeyStatusPair(
"name",
true),
1780 KeyStatusPair(
"type",
true),
1781 KeyStatusPair(
"contents",
false),
1782 KeyStatusPair(
"external-contents",
false),
1783 KeyStatusPair(
"use-external-name",
false),
1788 enum { CF_NotSet, CF_List, CF_External } ContentsField = CF_NotSet;
1789 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>>
1797 for (
auto &
I : *M) {
1802 if (!parseScalarString(
I.getKey(), Key, Buffer))
1805 if (!checkDuplicateOrUnknownKey(
I.getKey(), Key, Keys))
1809 if (Key ==
"name") {
1810 if (!parseScalarString(
I.getValue(),
Value, Buffer))
1813 NameValueNode =
I.getValue();
1817 }
else if (Key ==
"type") {
1818 if (!parseScalarString(
I.getValue(),
Value, Buffer))
1820 if (
Value ==
"file")
1822 else if (
Value ==
"directory")
1824 else if (
Value ==
"directory-remap")
1827 error(
I.getValue(),
"unknown value for 'type'");
1830 }
else if (Key ==
"contents") {
1831 if (ContentsField != CF_NotSet) {
1833 "entry already has 'contents' or 'external-contents'");
1836 ContentsField = CF_List;
1837 auto *Contents = dyn_cast<yaml::SequenceNode>(
I.getValue());
1840 error(
I.getValue(),
"expected array");
1844 for (
auto &
I : *Contents) {
1845 if (std::unique_ptr<RedirectingFileSystem::Entry>
E =
1846 parseEntry(&
I, FS,
false))
1847 EntryArrayContents.push_back(std::move(
E));
1851 }
else if (Key ==
"external-contents") {
1852 if (ContentsField != CF_NotSet) {
1854 "entry already has 'contents' or 'external-contents'");
1857 ContentsField = CF_External;
1858 if (!parseScalarString(
I.getValue(),
Value, Buffer))
1862 if (
FS->IsRelativeOverlay) {
1863 FullPath =
FS->getOverlayFileDir();
1865 "External contents prefix directory must exist");
1873 FullPath = canonicalize(FullPath);
1874 ExternalContentsPath = FullPath.
str();
1875 }
else if (Key ==
"use-external-name") {
1877 if (!parseScalarBool(
I.getValue(), Val))
1890 if (ContentsField == CF_NotSet) {
1891 error(
N,
"missing key 'contents' or 'external-contents'");
1894 if (!checkMissingKeys(
N, Keys))
1900 error(
N,
"'use-external-name' is not supported for 'directory' entries");
1905 ContentsField == CF_List) {
1906 error(
N,
"'contents' is not supported for 'directory-remap' entries");
1924 if (
FS->RootRelative ==
1927 assert(!FullPath.
empty() &&
"Overlay file directory must exist");
1928 EC =
FS->makeAbsolute(FullPath,
Name);
1934 assert(NameValueNode &&
"Name presence should be checked earlier");
1937 "entry with relative path at the root level is not discoverable");
1955 while (Trimmed.
size() > RootPathLen &&
1957 Trimmed = Trimmed.
slice(0, Trimmed.
size() - 1);
1962 std::unique_ptr<RedirectingFileSystem::Entry>
Result;
1965 Result = std::make_unique<RedirectingFileSystem::FileEntry>(
1966 LastComponent, std::move(ExternalContentsPath), UseExternalName);
1969 Result = std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1970 LastComponent, std::move(ExternalContentsPath), UseExternalName);
1973 Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1974 LastComponent, std::move(EntryArrayContents),
1988 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
1989 Entries.push_back(std::move(Result));
1990 Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1991 *
I, std::move(Entries),
2003 auto *Top = dyn_cast<yaml::MappingNode>(Root);
2005 error(Root,
"expected mapping node");
2009 KeyStatusPair Fields[] = {
2010 KeyStatusPair(
"version",
true),
2011 KeyStatusPair(
"case-sensitive",
false),
2012 KeyStatusPair(
"use-external-names",
false),
2013 KeyStatusPair(
"root-relative",
false),
2014 KeyStatusPair(
"overlay-relative",
false),
2015 KeyStatusPair(
"fallthrough",
false),
2016 KeyStatusPair(
"redirecting-with",
false),
2017 KeyStatusPair(
"roots",
true),
2021 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> RootEntries;
2024 for (
auto &
I : *Top) {
2027 if (!parseScalarString(
I.getKey(), Key, KeyBuffer))
2030 if (!checkDuplicateOrUnknownKey(
I.getKey(), Key, Keys))
2033 if (Key ==
"roots") {
2034 auto *Roots = dyn_cast<yaml::SequenceNode>(
I.getValue());
2036 error(
I.getValue(),
"expected array");
2040 for (
auto &
I : *Roots) {
2041 if (std::unique_ptr<RedirectingFileSystem::Entry>
E =
2042 parseEntry(&
I, FS,
true))
2043 RootEntries.push_back(std::move(
E));
2047 }
else if (Key ==
"version") {
2050 if (!parseScalarString(
I.getValue(), VersionString, Storage))
2054 error(
I.getValue(),
"expected integer");
2058 error(
I.getValue(),
"invalid version number");
2062 error(
I.getValue(),
"version mismatch, expected 0");
2065 }
else if (Key ==
"case-sensitive") {
2066 if (!parseScalarBool(
I.getValue(), FS->CaseSensitive))
2068 }
else if (Key ==
"overlay-relative") {
2069 if (!parseScalarBool(
I.getValue(), FS->IsRelativeOverlay))
2071 }
else if (Key ==
"use-external-names") {
2072 if (!parseScalarBool(
I.getValue(), FS->UseExternalNames))
2074 }
else if (Key ==
"fallthrough") {
2075 if (Keys[
"redirecting-with"].Seen) {
2077 "'fallthrough' and 'redirecting-with' are mutually exclusive");
2081 bool ShouldFallthrough =
false;
2082 if (!parseScalarBool(
I.getValue(), ShouldFallthrough))
2085 if (ShouldFallthrough) {
2090 }
else if (Key ==
"redirecting-with") {
2091 if (Keys[
"fallthrough"].Seen) {
2093 "'fallthrough' and 'redirecting-with' are mutually exclusive");
2097 if (
auto Kind = parseRedirectKind(
I.getValue())) {
2098 FS->Redirection = *Kind;
2100 error(
I.getValue(),
"expected valid redirect kind");
2103 }
else if (Key ==
"root-relative") {
2104 if (
auto Kind = parseRootRelativeKind(
I.getValue())) {
2105 FS->RootRelative = *Kind;
2107 error(
I.getValue(),
"expected valid root-relative kind");
2118 if (!checkMissingKeys(Top, Keys))
2124 for (
auto &
E : RootEntries)
2125 uniqueOverlayTree(FS,
E.get());
2131std::unique_ptr<RedirectingFileSystem>
2134 StringRef YAMLFilePath,
void *DiagContext,
2142 if (DI == Stream.
end() || !Root) {
2149 std::unique_ptr<RedirectingFileSystem> FS(
2152 if (!YAMLFilePath.
empty()) {
2163 assert(!EC &&
"Overlay dir final path must be absolute");
2165 FS->setOverlayFileDir(OverlayAbsDir);
2168 if (!
P.parse(Root, FS.get()))
2175 ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
2176 bool UseExternalNames,
FileSystem &ExternalFS) {
2177 std::unique_ptr<RedirectingFileSystem> FS(
2179 FS->UseExternalNames = UseExternalNames;
2189 assert(!EC &&
"Could not make absolute path");
2207 assert(Parent &&
"File without a directory?");
2211 assert(!EC &&
"Could not make absolute path");
2215 auto NewFile = std::make_unique<RedirectingFileSystem::FileEntry>(
2219 ToEntry = NewFile.get();
2220 cast<RedirectingFileSystem::DirectoryEntry>(Parent)->addContent(
2221 std::move(NewFile));
2234 if (
auto *DRE = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(
E)) {
2237 getExistingStyle(DRE->getExternalContentsPath()));
2238 ExternalRedirect = std::string(Redirect);
2245 for (
Entry *Parent : Parents)
2252 if (std::error_code EC = makeAbsolute(Path))
2256 canonicalize(
StringRef(Path.data(), Path.size()));
2257 if (CanonicalPath.
empty())
2260 Path.assign(CanonicalPath.
begin(), CanonicalPath.
end());
2269 for (
const auto &Root : Roots) {
2271 lookupPathImpl(Start,
End, Root.get(), Entries);
2273 Result->Parents = std::move(Entries);
2281RedirectingFileSystem::lookupPathImpl(
2287 "Paths should not contain traversal components");
2292 if (!FromName.
empty()) {
2293 if (!pathComponentMatches(*Start, FromName))
2300 return LookupResult(
From, Start,
End);
2304 if (isa<RedirectingFileSystem::FileEntry>(
From))
2307 if (isa<RedirectingFileSystem::DirectoryRemapEntry>(
From))
2308 return LookupResult(
From, Start,
End);
2310 auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(
From);
2311 for (
const std::unique_ptr<RedirectingFileSystem::Entry> &DirEntry :
2313 Entries.push_back(
From);
2315 lookupPathImpl(Start,
End, DirEntry.get(), Entries);
2325 bool UseExternalNames,
2330 return ExternalStatus;
2332 Status S = ExternalStatus;
2333 if (!UseExternalNames)
2342 const Twine &CanonicalPath,
const Twine &OriginalPath,
2344 if (std::optional<StringRef> ExtRedirect =
Result.getExternalRedirect()) {
2346 if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
2353 auto *RE = cast<RedirectingFileSystem::RemapEntry>(
Result.E);
2355 RE->useExternalName(UseExternalNames), *S);
2358 auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(
Result.E);
2363RedirectingFileSystem::getExternalStatus(
const Twine &CanonicalPath,
2364 const Twine &OriginalPath)
const {
2365 auto Result = ExternalFS->status(CanonicalPath);
2369 if (!Result ||
Result->ExposesExternalVFSPath)
2376 OriginalPath.
toVector(CanonicalPath);
2378 if (std::error_code EC = makeCanonical(CanonicalPath))
2395 isFileNotFound(Result.getError()))
2396 return getExternalStatus(CanonicalPath, OriginalPath);
2397 return Result.getError();
2402 isFileNotFound(S.
getError(), Result->E)) {
2406 return getExternalStatus(CanonicalPath, OriginalPath);
2415class FileWithFixedStatus :
public File {
2416 std::unique_ptr<File> InnerFile;
2420 FileWithFixedStatus(std::unique_ptr<File> InnerFile,
Status S)
2426 getBuffer(
const Twine &
Name, int64_t FileSize,
bool RequiresNullTerminator,
2427 bool IsVolatile)
override {
2428 return InnerFile->getBuffer(
Name, FileSize, RequiresNullTerminator,
2432 std::error_code close()
override {
return InnerFile->close(); }
2443 if (!Result || (*Result)->status()->ExposesExternalVFSPath)
2447 auto Name =
F->get()->getName();
2449 F->get()->setPath(
P);
2456 OriginalPath.
toVector(CanonicalPath);
2458 if (std::error_code EC = makeCanonical(CanonicalPath))
2476 isFileNotFound(Result.getError()))
2479 return Result.getError();
2482 if (!Result->getExternalRedirect())
2485 StringRef ExtRedirect = *Result->getExternalRedirect();
2487 if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
2490 auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
2493 ExternalFS->openFileForRead(CanonicalRemappedPath), ExtRedirect);
2494 if (!ExternalFile) {
2496 isFileNotFound(ExternalFile.getError(), Result->E)) {
2503 return ExternalFile;
2506 auto ExternalStatus = (*ExternalFile)->status();
2507 if (!ExternalStatus)
2508 return ExternalStatus.getError();
2513 OriginalPath, RE->useExternalName(UseExternalNames), *ExternalStatus);
2514 return std::unique_ptr<File>(
2515 std::make_unique<FileWithFixedStatus>(std::move(*ExternalFile), S));
2522 OriginalPath.
toVector(CanonicalPath);
2524 if (std::error_code EC = makeCanonical(CanonicalPath))
2530 std::error_code EC = ExternalFS->getRealPath(CanonicalPath, Output);
2541 isFileNotFound(Result.getError()))
2542 return ExternalFS->getRealPath(CanonicalPath, Output);
2543 return Result.getError();
2548 if (
auto ExtRedirect = Result->getExternalRedirect()) {
2549 auto P = ExternalFS->getRealPath(*ExtRedirect, Output);
2551 isFileNotFound(
P, Result->E)) {
2555 return ExternalFS->getRealPath(CanonicalPath, Output);
2563 Result->getPath(Output);
2569std::unique_ptr<FileSystem>
2572 StringRef YAMLFilePath,
void *DiagContext,
2575 YAMLFilePath, DiagContext,
2576 std::move(ExternalFS));
2584 auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
2585 assert(DE &&
"Must be a directory");
2586 for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
2588 Path.push_back(SubEntry->getName());
2596 auto *DR = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
2597 assert(DR &&
"Must be a directory remap");
2599 for (
auto &Comp : Path)
2607 auto *FE = dyn_cast<RedirectingFileSystem::FileEntry>(SrcE);
2608 assert(FE &&
"Must be a file");
2610 for (
auto &Comp : Path)
2622 std::move(Buffer),
DiagHandler, YAMLFilePath, DiagContext,
2623 std::move(ExternalFS));
2627 VFS->lookupPath(
"/");
2636 static std::atomic<unsigned> UID;
2637 unsigned ID = ++UID;
2640 return UniqueID(std::numeric_limits<uint64_t>::max(),
ID);
2648 Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
2652 addEntry(VirtualPath, RealPath,
false);
2657 addEntry(VirtualPath, RealPath,
true);
2666 unsigned getDirIndent() {
return 4 * DirStack.
size(); }
2667 unsigned getFileIndent() {
return 4 * (DirStack.
size() + 1); }
2671 void endDirectory();
2678 std::optional<bool> UseExternalNames,
2679 std::optional<bool> IsCaseSensitive,
2680 std::optional<bool> IsOverlayRelative,
StringRef OverlayDir);
2691 IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
2692 if (*IParent != *IChild)
2696 return IParent == EParent;
2701 assert(containedIn(Parent, Path));
2705void JSONWriter::startDirectory(
StringRef Path) {
2707 DirStack.
empty() ?
Path : containedPart(DirStack.
back(), Path);
2709 unsigned Indent = getDirIndent();
2711 OS.
indent(Indent + 2) <<
"'type': 'directory',\n";
2713 OS.
indent(Indent + 2) <<
"'contents': [\n";
2716void JSONWriter::endDirectory() {
2717 unsigned Indent = getDirIndent();
2725 unsigned Indent = getFileIndent();
2727 OS.
indent(Indent + 2) <<
"'type': 'file',\n";
2729 OS.
indent(Indent + 2) <<
"'external-contents': \""
2735 std::optional<bool> UseExternalNames,
2736 std::optional<bool> IsCaseSensitive,
2737 std::optional<bool> IsOverlayRelative,
2743 if (IsCaseSensitive)
2744 OS <<
" 'case-sensitive': '" << (*IsCaseSensitive ?
"true" :
"false")
2746 if (UseExternalNames)
2747 OS <<
" 'use-external-names': '" << (*UseExternalNames ?
"true" :
"false")
2749 bool UseOverlayRelative =
false;
2750 if (IsOverlayRelative) {
2751 UseOverlayRelative = *IsOverlayRelative;
2752 OS <<
" 'overlay-relative': '" << (UseOverlayRelative ?
"true" :
"false")
2755 OS <<
" 'roots': [\n";
2757 if (!Entries.empty()) {
2765 if (UseOverlayRelative) {
2768 "Overlay dir must be contained in RPath");
2769 RPath = RPath.
slice(OverlayDirLen, RPath.
size());
2772 bool IsCurrentDirEmpty =
true;
2773 if (!Entry.IsDirectory) {
2775 IsCurrentDirEmpty =
false;
2778 for (
const auto &Entry : Entries.slice(1)) {
2781 if (Dir == DirStack.
back()) {
2782 if (!IsCurrentDirEmpty) {
2786 bool IsDirPoppedFromStack =
false;
2787 while (!DirStack.
empty() && !containedIn(DirStack.
back(), Dir)) {
2790 IsDirPoppedFromStack =
true;
2792 if (IsDirPoppedFromStack || !IsCurrentDirEmpty) {
2795 startDirectory(Dir);
2796 IsCurrentDirEmpty =
true;
2799 if (UseOverlayRelative) {
2802 "Overlay dir must be contained in RPath");
2803 RPath = RPath.
slice(OverlayDirLen, RPath.
size());
2805 if (!Entry.IsDirectory) {
2807 IsCurrentDirEmpty =
false;
2811 while (!DirStack.
empty()) {
2824 return LHS.VPath <
RHS.VPath;
2827 JSONWriter(
OS).write(Mappings, UseExternalNames, IsCaseSensitive,
2836 State = std::make_shared<detail::RecDirIterState>();
2837 State->Stack.push(
I);
2843 assert(FS && State && !State->Stack.empty() &&
"incrementing past end");
2844 assert(!State->Stack.top()->path().empty() &&
"non-canonical end iterator");
2847 if (State->HasNoPushRequest)
2848 State->HasNoPushRequest =
false;
2853 State->Stack.push(
I);
2859 while (!State->Stack.empty() && State->Stack.top().increment(EC) ==
End)
2862 if (State->Stack.empty())
BlockVerifier::State From
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Provides ErrorOr<T> smart pointer.
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, SmallVectorImpl< StringRef > &Path, SmallVectorImpl< YAMLVFSEntry > &Entries)
static Status getRedirectedFileStatus(const Twine &OriginalPath, bool UseExternalNames, Status ExternalStatus)
static bool pathHasTraversal(StringRef Path)
static bool isTraversalComponent(StringRef Component)
Defines the virtual file system interface vfs::FileSystem.
static unsigned getSize(unsigned Kind)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Represents either an error or a value T.
std::error_code getError() const
Tagged union holding either a T or a Error.
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.
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 StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
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.
static constexpr size_t npos
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...
std::string str() const
Return the twine contents as a std::string.
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 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 & 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.
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
bool exists(const Twine &Path)
Check whether a file exists. Provided for convenience.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
This is a convenience method that opens a file, gets its content and then closes the file.
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0
Get a File object for the file at Path, if one exists.
void printIndent(raw_ostream &OS, unsigned IndentLevel) const
LLVM_DUMP_METHOD void dump() const
void print(raw_ostream &OS, PrintType Type=PrintType::Contents, unsigned IndentLevel=0) const
virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const
Gets real path of Path e.g.
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
static ErrorOr< std::unique_ptr< File > > getWithPath(ErrorOr< std::unique_ptr< File > > Result, const Twine &P)
virtual ~File()
Destroy the file after closing it (if open).
Adaptor from InMemoryDir::iterator to directory_iterator.
DirIterator(const InMemoryFileSystem *FS, const detail::InMemoryDirectory &Dir, std::string RequestedDirName)
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
An in-memory file system.
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
~InMemoryFileSystem() override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Canonicalizes Path by combining with the current working directory and normalizing the path (e....
static constexpr size_t MaxSymlinkDepth
Arbitrary max depth to search through symlinks.
InMemoryFileSystem(bool UseNormalizedPaths=true)
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
bool addHardLink(const Twine &NewLink, const Twine &Target)
Add a hard link to a file.
std::string toString() const
bool addFileNoOwn(const Twine &Path, time_t ModificationTime, const llvm::MemoryBufferRef &Buffer, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::file_type > Type=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)
Add a buffer to the VFS with a path.
bool addSymbolicLink(const Twine &NewLink, const Twine &Target, time_t ModificationTime, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)
Add a symbolic link.
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
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
Is the file mounted on a local filesystem?
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
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
Directory iterator implementation for RedirectingFileSystem's directory entries.
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
RedirectingFSDirIterImpl(const Twine &Path, RedirectingFileSystem::DirectoryEntry::iterator Begin, RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)
A helper class to hold the common YAML parsing state.
RedirectingFileSystemParser(yaml::Stream &S)
static RedirectingFileSystem::Entry * lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name, RedirectingFileSystem::Entry *ParentEntry=nullptr)
bool parse(yaml::Node *Root, RedirectingFileSystem *FS)
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.
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
std::vector< llvm::StringRef > getRoots() const
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
ErrorOr< LookupResult > lookupPath(StringRef Path) const
Looks up Path in Roots and returns a LookupResult giving the matched entry and, if the entry was a Fi...
RedirectKind
The type of redirection to perform.
@ Fallthrough
Lookup the redirected path first (ie.
@ Fallback
Lookup the provided path first and if that fails, "fallback" to a lookup of the redirected path.
@ RedirectOnly
Only lookup the redirected path, do not lookup the originally provided path.
void setFallthrough(bool Fallthrough)
Sets the redirection kind to Fallthrough if true or RedirectOnly otherwise.
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
void setOverlayFileDir(StringRef PrefixDir)
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
void setRedirection(RedirectingFileSystem::RedirectKind Kind)
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
static std::unique_ptr< RedirectingFileSystem > create(std::unique_ptr< MemoryBuffer > Buffer, SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext, IntrusiveRefCntPtr< FileSystem > ExternalFS)
Parses Buffer, which is expected to be in YAML format and returns a virtual file system representing ...
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
StringRef getOverlayFileDir() const
void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel=0) const
The result of a status operation.
llvm::sys::fs::UniqueID getUniqueID() const
bool equivalent(const Status &Other) const
static Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
bool isStatusKnown() const
bool ExposesExternalVFSPath
Whether this entity has an external path different from the virtual path, and the external path is ex...
static Status copyWithNewSize(const Status &In, uint64_t NewSize)
Get a copy of a Status with a different size.
llvm::sys::fs::file_type getType() const
bool isRegularFile() const
StringRef getName() const
Returns the name that should be used for this file or directory.
void addFileMapping(StringRef VirtualPath, StringRef RealPath)
void write(llvm::raw_ostream &OS)
void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)
InMemoryDirectory(Status Stat)
InMemoryNode * addChild(StringRef Name, std::unique_ptr< InMemoryNode > Child)
Status getStatus(const Twine &RequestedName) const override
Return the Status for this node.
const_iterator end() const
static bool classof(const InMemoryNode *N)
InMemoryNode * getChild(StringRef Name) const
const_iterator begin() const
UniqueID getUniqueID() const
decltype(Entries)::const_iterator const_iterator
std::string toString(unsigned Indent) const override
Status getStatus(const Twine &RequestedName) const override
Return the Status for this node.
std::string toString(unsigned Indent) const override
InMemoryFile(Status Stat, std::unique_ptr< llvm::MemoryBuffer > Buffer)
static bool classof(const InMemoryNode *N)
llvm::MemoryBuffer * getBuffer() const
The in memory file system is a tree of Nodes.
StringRef getFileName() const
Get the filename of this node (the name without the directory part).
InMemoryNodeKind getKind() const
virtual ~InMemoryNode()=default
InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
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.
recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
Abstract base class for all Nodes.
This class represents a YAML stream potentially containing multiple documents.
document_iterator begin()
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.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
@ Resolved
Queried, materialization begun.
void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
const file_t kInvalidFile
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
std::error_code closeFile(file_t &F)
Close the file object.
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.
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
file_type
An enumeration for the file system's view of the type.
std::error_code set_current_path(const Twine &path)
Set the current path.
std::error_code is_local(const Twine &path, bool &result)
Is the file mounted on a local filesystem?
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.
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
bool is_directory(const basic_file_status &status)
Does status represent a directory?
StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
reverse_iterator rend(StringRef path)
Get reverse end iterator over path.
const_iterator end(StringRef path)
Get end iterator over path.
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
reverse_iterator rbegin(StringRef path, Style style=Style::native)
Get reverse begin iterator over path.
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
StringRef root_path(StringRef path, Style style=Style::native)
Get root path.
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
StringRef remove_leading_dotslash(StringRef path, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
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.
void collectVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Collect all pairs of <virtual path, real path> entries from the YAMLFilePath.
std::unique_ptr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.
static sys::fs::UniqueID getFileID(sys::fs::UniqueID Parent, llvm::StringRef Name, llvm::StringRef Contents)
llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
static sys::fs::UniqueID getUniqueID(hash_code Hash)
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
static sys::fs::UniqueID getDirectoryID(sys::fs::UniqueID Parent, llvm::StringRef Name)
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.
std::error_code make_error_code(BitcodeError E)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, bool ContinueOnCuIndexOverflow)
@ no_such_file_or_directory
@ operation_not_permitted
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
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.
Represents the result of a path lookup into the RedirectingFileSystem.
Entry * E
The entry the looked-up path corresponds to.
LookupResult(Entry *E, sys::path::const_iterator Start, sys::path::const_iterator End)
void getPath(llvm::SmallVectorImpl< char > &Path) const
Get the (canonical) path of the found entry.
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
directory_entry CurrentEntry
Status makeStatus() const
std::unique_ptr< llvm::MemoryBuffer > Buffer