24#include "llvm/Config/llvm-config.h"
50#include <system_error>
71 : Name(Name.str()), UID(UID), MTime(MTime), User(User), Group(Group),
72 Size(Size), Type(Type), Perms(Perms) {}
75 return Status(In.getName(), In.getUniqueID(), In.getLastModificationTime(),
76 In.getUser(), In.getGroup(), NewSize, In.getType(),
81 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
82 In.getUser(), In.getGroup(), In.getSize(), In.getType(),
87 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
88 In.getUser(), In.getGroup(), In.getSize(), In.type(),
119 bool RequiresNullTerminator,
bool IsVolatile,
125 return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
134 return WorkingDir.getError();
157 return StatusA.getError();
160 return StatusB.getError();
161 return StatusA->equivalent(*StatusB);
164#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
170 return Component ==
".." || Component ==
".";
190class RealFile :
public File {
191 friend class RealFileSystem;
195 std::string OriginalName;
198 std::optional<std::string> RealName;
200 RealFile(file_t RawFD, StringRef NewName, StringRef NewOriginalName)
201 : FD(RawFD), S(NewName, {}, {}, {}, {}, {},
203 OriginalName(NewOriginalName.str()) {
204 assert(FD.
isValid() &&
"Invalid or inactive file descriptor");
208 ~RealFile()
override;
210 ErrorOr<Status>
status()
override;
211 ErrorOr<std::string>
getName()
override;
212 ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(
const Twine &Name,
214 bool RequiresNullTerminator,
215 bool IsVolatile)
override;
216 std::error_code close()
override;
217 void setPath(
const Twine &Path)
override;
222RealFile::~RealFile() { close(); }
224ErrorOr<Status> RealFile::status() {
227 assert(FD.isValid() &&
"cannot stat closed file");
228 if (!S.isStatusKnown()) {
229 file_status RealStatus;
237ErrorOr<std::string> RealFile::getName() {
240 SmallString<256>
Path;
248 return RealName->empty() ? S.getName().str() : *RealName;
251ErrorOr<std::unique_ptr<MemoryBuffer>>
252RealFile::getBuffer(
const Twine &Name, int64_t FileSize,
253 bool RequiresNullTerminator,
bool IsVolatile) {
256 assert(FD.isValid() &&
"cannot get buffer for closed file");
261std::error_code RealFile::close() {
269void RealFile::setPath(
const Twine &Path) {
272 RealName =
Path.str();
287class RealFileSystem :
public FileSystem {
289 explicit RealFileSystem(
bool LinkCWDToProcess) {
290 if (!LinkCWDToProcess) {
291 SmallString<128> PWD, RealPWD;
295 WD = WorkingDirectory{PWD, PWD};
297 WD = WorkingDirectory{PWD, RealPWD};
301 ErrorOr<Status>
status(
const Twine &Path)
override;
302 ErrorOr<std::unique_ptr<File>>
openFileForRead(
const Twine &Path)
override;
303 ErrorOr<std::unique_ptr<File>>
304 openFileForReadBinary(
const Twine &Path)
override;
305 directory_iterator dir_begin(
const Twine &Dir, std::error_code &EC)
override;
307 llvm::ErrorOr<std::string> getCurrentWorkingDirectory()
const override;
308 std::error_code setCurrentWorkingDirectory(
const Twine &Path)
override;
309 std::error_code isLocal(
const Twine &Path,
bool &Result)
override;
311 getDirectoryContentRealSources(
const Twine &Dir,
312 SmallVectorImpl<std::string> &Out)
override {
315 std::error_code getRealPath(
const Twine &Path,
316 SmallVectorImpl<char> &Output)
override;
320 unsigned IndentLevel)
const override;
325 Twine adjustPath(
const Twine &Path, SmallVectorImpl<char> &Storage)
const {
328 Path.toVector(Storage);
333 ErrorOr<std::unique_ptr<File>>
335 SmallString<256>
Path, Storage;
336 adjustPath(Name, Storage).toVector(Path);
340 return std::unique_ptr<File>(
new RealFile(*FDOrErr,
Name.str(), Path));
343 struct WorkingDirectory {
345 SmallString<128> Specified;
349 std::optional<llvm::ErrorOr<WorkingDirectory>> WD;
354ErrorOr<Status> RealFileSystem::status(
const Twine &Path) {
357 SmallString<256> Storage;
358 sys::fs::file_status RealStatus;
359 if (std::error_code EC =
365ErrorOr<std::unique_ptr<File>>
366RealFileSystem::openFileForRead(
const Twine &Name) {
372ErrorOr<std::unique_ptr<File>>
373RealFileSystem::openFileForReadBinary(
const Twine &Name) {
379llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory()
const {
383 return std::string(WD->get().Specified);
385 return WD->getError();
387 SmallString<128> Dir;
390 return std::string(Dir);
393std::error_code RealFileSystem::setCurrentWorkingDirectory(
const Twine &Path) {
400 adjustPath(Path, Storage).toVector(Absolute);
405 return std::make_error_code(std::errc::not_a_directory);
409 return std::error_code();
412std::error_code RealFileSystem::isLocal(
const Twine &Path,
bool &Result) {
415 SmallString<256> Storage;
419std::error_code RealFileSystem::getRealPath(
const Twine &Path,
420 SmallVectorImpl<char> &Output) {
423 SmallString<256> Storage;
427void RealFileSystem::printImpl(raw_ostream &OS, PrintType
Type,
428 unsigned IndentLevel)
const {
429 printIndent(OS, IndentLevel);
430 OS <<
"RealFileSystem using ";
449 return std::make_unique<RealFileSystem>(
false);
458 RealFSDirIter(
const Twine &Path, std::error_code &EC) {
466 std::error_code increment()
override {
481 std::error_code &EC) {
484 SmallString<128> Storage;
486 std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC));
494 FSList.push_back(std::move(BaseFS));
498 FSList.push_back(FS);
517 if ((*I)->exists(Path))
527 auto Result = (*I)->openFileForRead(Path);
537 return FSList.front()->getCurrentWorkingDirectory();
542 for (
auto &FS : FSList)
543 if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
549 for (
auto &FS : FSList)
550 if (FS->exists(Path))
551 return FS->isLocal(Path, Result);
557 for (
const auto &FS : FSList)
558 if (FS->exists(Path))
559 return FS->getRealPath(Path, Output);
567 (*I)->getDirectoryContentRealSources(Dir, Out);
573 FS->visitChildFileSystems(Callback);
578 unsigned IndentLevel)
const {
579 printIndent(OS, IndentLevel);
580 OS <<
"OverlayFileSystem\n";
581 if (
Type == PrintType::Summary)
584 if (
Type == PrintType::Contents)
585 Type = PrintType::Summary;
587 FS->print(OS,
Type, IndentLevel + 1);
607 std::error_code incrementIter(
bool IsFirstTime) {
608 while (!IterList.
empty()) {
609 CurrentDirIter = IterList.
back();
620 std::error_code incrementDirIter(
bool IsFirstTime) {
621 assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
622 "incrementing past end");
626 if (!EC && CurrentDirIter == directory_iterator())
627 EC = incrementIter(IsFirstTime);
631 std::error_code incrementImpl(
bool IsFirstTime) {
633 std::error_code
EC = incrementDirIter(IsFirstTime);
634 if (EC || CurrentDirIter == directory_iterator()) {
635 CurrentEntry = directory_entry();
638 CurrentEntry = *CurrentDirIter;
640 if (SeenNames.
insert(Name).second)
648 std::error_code &EC) {
649 for (
const auto &FS : FileSystems) {
651 directory_iterator Iter =
FS->dir_begin(Dir, FEC);
652 if (FEC && FEC != errc::no_such_file_or_directory) {
659 EC = incrementImpl(
true);
664 : IterList(DirIters) {
665 EC = incrementImpl(
true);
668 std::error_code increment()
override {
return incrementImpl(
false); }
674 std::error_code &EC) {
676 std::make_shared<CombiningDirIterImpl>(FSList, Dir.
str(), EC));
682void ProxyFileSystem::anchor() {}
700 std::string FileName;
704 : Kind(Kind), FileName(
std::string(
llvm::
sys::
path::filename(FileName))) {
716 virtual std::string
toString(
unsigned Indent)
const = 0;
721 std::unique_ptr<llvm::MemoryBuffer> Buffer;
733 std::string
toString(
unsigned Indent)
const override {
734 return (std::string(Indent,
' ') + Stat.getName() +
"\n").str();
744class InMemoryHardLink :
public InMemoryNode {
745 const InMemoryFile &ResolvedFile;
748 InMemoryHardLink(
StringRef Path,
const InMemoryFile &ResolvedFile)
749 : InMemoryNode(Path,
IME_HardLink), ResolvedFile(ResolvedFile) {}
750 const InMemoryFile &getResolvedFile()
const {
return ResolvedFile; }
752 Status getStatus(
const Twine &RequestedName)
const override {
753 return ResolvedFile.getStatus(RequestedName);
756 std::string
toString(
unsigned Indent)
const override {
757 return std::string(Indent,
' ') +
"HardLink to -> " +
758 ResolvedFile.toString(0);
761 static bool classof(
const InMemoryNode *
N) {
767 std::string TargetPath;
771 InMemorySymbolicLink(StringRef Path, StringRef TargetPath, Status Stat)
775 std::string
toString(
unsigned Indent)
const override {
776 return std::string(Indent,
' ') +
"SymbolicLink to -> " + TargetPath;
779 Status getStatus(
const Twine &RequestedName)
const override {
783 StringRef getTargetPath()
const {
return TargetPath; }
785 static bool classof(
const InMemoryNode *
N) {
793class InMemoryFileAdaptor :
public File {
794 const InMemoryFile &Node;
796 std::string RequestedName;
799 explicit InMemoryFileAdaptor(
const InMemoryFile &Node,
800 std::string RequestedName)
801 : Node(Node), RequestedName(std::
move(RequestedName)) {}
803 llvm::ErrorOr<Status>
status()
override {
804 return Node.getStatus(RequestedName);
807 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
808 getBuffer(
const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator,
809 bool IsVolatile)
override {
810 llvm::MemoryBuffer *Buf = Node.getBuffer();
815 std::error_code close()
override {
return {}; }
817 void setPath(
const Twine &Path)
override { RequestedName =
Path.str(); }
823 std::map<std::string, std::unique_ptr<InMemoryNode>, std::less<>> Entries;
839 auto I = Entries.find(Name);
840 if (
I != Entries.end())
841 return I->second.get();
846 return Entries.emplace(Name, std::move(Child)).first->second.get();
854 std::string
toString(
unsigned Indent)
const override {
856 (std::string(Indent,
' ') + Stat.getName() +
"\n").str();
857 for (
const auto &Entry : Entries)
858 Result += Entry.second->toString(Indent + 2);
897 : Root(new
detail::InMemoryDirectory(
902 UseNormalizedPaths(UseNormalizedPaths) {}
907 return Root->toString(0);
910bool InMemoryFileSystem::addFile(
const Twine &
P, time_t ModificationTime,
911 std::unique_ptr<llvm::MemoryBuffer> Buffer,
912 std::optional<uint32_t>
User,
913 std::optional<uint32_t> Group,
914 std::optional<llvm::sys::fs::file_type>
Type,
915 std::optional<llvm::sys::fs::perms> Perms,
916 MakeNodeFn MakeNode) {
933 const auto ResolvedUser =
User.value_or(0);
934 const auto ResolvedGroup = Group.value_or(0);
951 StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
956 Name, std::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
967 MakeNode({Dir->
getUniqueID(), Path, Name, ModificationTime,
968 std::move(Buffer), ResolvedUser, ResolvedGroup,
969 ResolvedType, ResolvedPerms}));
977 "Must be either file, hardlink or directory!");
981 return Link->getResolvedFile().getBuffer()->getBuffer() ==
988bool InMemoryFileSystem::addFile(
const Twine &
P, time_t ModificationTime,
989 std::unique_ptr<llvm::MemoryBuffer> Buffer,
990 std::optional<uint32_t>
User,
991 std::optional<uint32_t> Group,
992 std::optional<llvm::sys::fs::file_type>
Type,
993 std::optional<llvm::sys::fs::perms> Perms) {
994 return addFile(
P, ModificationTime, std::move(Buffer),
User, Group,
Type,
997 -> std::unique_ptr<detail::InMemoryNode> {
1000 return std::make_unique<detail::InMemoryDirectory>(Stat);
1001 return std::make_unique<detail::InMemoryFile>(
1002 Stat, std::move(NNI.
Buffer));
1007 const Twine &
P, time_t ModificationTime,
1009 std::optional<uint32_t> Group, std::optional<llvm::sys::fs::file_type>
Type,
1010 std::optional<llvm::sys::fs::perms> Perms) {
1012 std::move(
User), std::move(Group), std::move(
Type),
1015 -> std::unique_ptr<detail::InMemoryNode> {
1018 return std::make_unique<detail::InMemoryDirectory>(Stat);
1019 return std::make_unique<detail::InMemoryFile>(
1020 Stat, std::move(NNI.
Buffer));
1025InMemoryFileSystem::lookupNode(
const Twine &
P,
bool FollowFinalSymlink,
1026 size_t SymlinkDepth)
const {
1052 if (
I == E && !FollowFinalSymlink)
1067 lookupNode(TargetPath,
true, SymlinkDepth + 1);
1095 return detail::NamedNodeOrError(Path, Dir);
1101 auto NewLinkNode = lookupNode(NewLink,
false);
1105 auto TargetNode = lookupNode(
Target,
true);
1110 return addFile(NewLink, 0,
nullptr, std::nullopt, std::nullopt, std::nullopt,
1112 return std::make_unique<detail::InMemoryHardLink>(
1120 std::optional<uint32_t>
User, std::optional<uint32_t> Group,
1121 std::optional<llvm::sys::fs::perms> Perms) {
1122 auto NewLinkNode = lookupNode(NewLink,
false);
1128 Target.toVector(TargetStr);
1130 return addFile(NewLinkStr, ModificationTime,
nullptr,
User, Group,
1133 return std::make_unique<detail::InMemorySymbolicLink>(
1139 auto Node = lookupNode(Path,
true);
1141 return (*Node)->getStatus(Path);
1142 return Node.getError();
1147 auto Node = lookupNode(Path,
true);
1149 return Node.getError();
1154 return std::unique_ptr<File>(
1155 new detail::InMemoryFileAdaptor(*
F, Path.str()));
1166 std::string RequestedDirName;
1168 void setCurrentEntry() {
1173 switch (I->second->getKind()) {
1182 if (
auto SymlinkTarget =
1183 FS->lookupNode(Path,
true)) {
1184 Path = SymlinkTarget.getName();
1185 Type = (*SymlinkTarget)->getStatus(Path).getType();
1202 std::string RequestedDirName)
1203 : FS(FS), I(Dir.begin()), E(Dir.end()),
1204 RequestedDirName(
std::
move(RequestedDirName)) {
1216 std::error_code &EC) {
1217 auto Node = lookupNode(Dir,
true);
1219 EC =
Node.getError();
1225 std::make_shared<DirIterator>(
this, *DirNode, Dir.
str()));
1244 WorkingDirectory = std::string(Path);
1251 if (!CWD || CWD->empty())
1253 Path.toVector(Output);
1266 unsigned IndentLevel)
const {
1267 printIndent(OS, IndentLevel);
1268 OS <<
"InMemoryFileSystem\n";
1283 const size_t n = Path.find_first_of(
"/\\");
1285 if (n !=
static_cast<size_t>(-1))
1305static bool isFileNotFound(std::error_code EC,
1317 assert(ExternalFS &&
"RedirectingFileSystem requires an external FS");
1318 if (
auto ExternalWorkingDirectory = ExternalFS->getCurrentWorkingDirectory())
1319 WorkingDirectory = *ExternalWorkingDirectory;
1329 std::error_code incrementImpl(
bool IsFirstTime) {
1330 assert((IsFirstTime || Current != End) &&
"cannot iterate past end");
1333 if (Current != End) {
1337 switch ((*Current)->getKind()) {
1358 : Dir(Path.str()), Current(Begin), End(End) {
1359 EC = incrementImpl(
true);
1363 return incrementImpl(
false);
1377 RedirectingFSDirRemapIterImpl(std::string DirPath,
1379 : Dir(
std::
move(DirPath)), DirStyle(getExistingStyle(Dir)),
1380 ExternalIter(ExtIter) {
1385 void setCurrentEntry() {
1396 std::error_code increment()
override {
1399 if (!EC && ExternalIter != llvm::vfs::directory_iterator())
1402 CurrentEntry = directory_entry();
1408llvm::ErrorOr<std::string>
1410 return WorkingDirectory;
1420 Path.toVector(AbsolutePath);
1421 if (std::error_code EC = makeAbsolute(AbsolutePath))
1423 WorkingDirectory = std::string(AbsolutePath);
1432 if (makeAbsolute(Path))
1435 return ExternalFS->isLocal(Path, Result);
1450 return WorkingDir.getError();
1452 return makeAbsolute(WorkingDir.get(), Path);
1456RedirectingFileSystem::makeAbsolute(
StringRef WorkingDir,
1462 if (!WorkingDir.
empty() &&
1466 return std::error_code();
1478 std::string
Result = std::string(WorkingDir);
1479 StringRef Dir(Result);
1495 std::error_code &EC) {
1499 EC = makeAbsolute(Path);
1506 isFileNotFound(Result.getError()))
1507 return ExternalFS->dir_begin(Path, EC);
1509 EC = Result.getError();
1517 isFileNotFound(S.
getError(), Result->E))
1518 return ExternalFS->dir_begin(Dir, EC);
1524 if (!S->isDirectory()) {
1532 std::error_code RedirectEC;
1533 if (
auto ExtRedirect = Result->getExternalRedirect()) {
1535 RedirectIter = ExternalFS->dir_begin(*ExtRedirect, RedirectEC);
1537 if (!RE->useExternalName(UseExternalNames)) {
1541 std::string(Path), RedirectIter));
1547 Path, DE->contents_begin(), DE->contents_end(), RedirectEC));
1560 return RedirectIter;
1563 std::error_code ExternalEC;
1574 switch (Redirection) {
1588 std::make_shared<CombiningDirIterImpl>(Iters, EC)};
1595 OverlayFileDir = Dir.
str();
1599 return OverlayFileDir;
1616 std::vector<StringRef> R;
1617 R.reserve(Roots.size());
1618 for (
const auto &Root : Roots)
1619 R.push_back(Root->getName());
1624 unsigned IndentLevel)
const {
1626 OS <<
"RedirectingFileSystem (UseExternalNames: "
1627 << (UseExternalNames ?
"true" :
"false") <<
")\n";
1631 for (
const auto &Root : Roots)
1635 OS <<
"ExternalFS:\n";
1642 unsigned IndentLevel)
const {
1644 OS <<
"'" << E->getName() <<
"'";
1646 switch (E->getKind()) {
1651 for (std::unique_ptr<Entry> &SubEntry :
1653 printEntry(OS, SubEntry.get(), IndentLevel + 1);
1659 OS <<
" -> '" << RE->getExternalContentsPath() <<
"'";
1660 switch (RE->getUseName()) {
1664 OS <<
" (UseExternalName: true)";
1667 OS <<
" (UseExternalName: false)";
1678 Callback(*ExternalFS);
1679 ExternalFS->visitChildFileSystems(Callback);
1695 error(
N,
"expected string");
1698 Result = S->getValue(Storage);
1703 bool parseScalarBool(
yaml::Node *
N,
bool &Result) {
1706 if (!parseScalarString(
N,
Value, Storage))
1709 if (
Value.equals_insensitive(
"true") ||
Value.equals_insensitive(
"on") ||
1710 Value.equals_insensitive(
"yes") ||
Value ==
"1") {
1713 }
else if (
Value.equals_insensitive(
"false") ||
1714 Value.equals_insensitive(
"off") ||
1715 Value.equals_insensitive(
"no") ||
Value ==
"0") {
1720 error(
N,
"expected boolean value");
1724 std::optional<RedirectingFileSystem::RedirectKind>
1728 if (!parseScalarString(
N,
Value, Storage))
1729 return std::nullopt;
1731 if (
Value.equals_insensitive(
"fallthrough")) {
1733 }
else if (
Value.equals_insensitive(
"fallback")) {
1735 }
else if (
Value.equals_insensitive(
"redirect-only")) {
1738 return std::nullopt;
1741 std::optional<RedirectingFileSystem::RootRelativeKind>
1745 if (!parseScalarString(
N,
Value, Storage))
1746 return std::nullopt;
1747 if (
Value.equals_insensitive(
"cwd")) {
1749 }
else if (
Value.equals_insensitive(
"overlay-dir")) {
1752 return std::nullopt;
1759 KeyStatus(
bool Required =
false) : Required(Required) {}
1762 using KeyStatusPair = std::pair<StringRef, KeyStatus>;
1768 if (It == Keys.
end()) {
1769 error(KeyNode,
"unknown key");
1772 KeyStatus &S = It->second;
1783 for (
const auto &
I : Keys) {
1784 if (
I.second.Required && !
I.second.Seen) {
1785 error(Obj,
Twine(
"missing key '") +
I.first +
"'");
1797 for (
const auto &Root : FS->Roots) {
1798 if (Name == Root->getName()) {
1799 ParentEntry = Root.get();
1805 for (std::unique_ptr<RedirectingFileSystem::Entry> &Content :
1809 if (DirContent && Name == Content->getName())
1815 std::unique_ptr<RedirectingFileSystem::Entry> E =
1816 std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1818 std::chrono::system_clock::now(), 0, 0, 0,
1822 FS->Roots.push_back(std::move(E));
1823 ParentEntry = FS->Roots.back().get();
1828 DE->addContent(std::move(E));
1829 return DE->getLastContent();
1844 NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
1845 for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
1847 uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
1851 assert(NewParentE &&
"Parent entry must exist");
1855 std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1856 Name, DR->getExternalContentsPath(), DR->getUseName()));
1860 assert(NewParentE &&
"Parent entry must exist");
1863 DE->addContent(std::make_unique<RedirectingFileSystem::FileEntry>(
1864 Name, FE->getExternalContentsPath(), FE->getUseName()));
1870 std::unique_ptr<RedirectingFileSystem::Entry>
1871 parseEntry(yaml::Node *
N, RedirectingFileSystem *FS,
bool IsRootEntry) {
1874 error(
N,
"expected mapping node for file or directory entry");
1878 KeyStatusPair Fields[] = {
1879 KeyStatusPair(
"name",
true),
1880 KeyStatusPair(
"type",
true),
1881 KeyStatusPair(
"contents",
false),
1882 KeyStatusPair(
"external-contents",
false),
1883 KeyStatusPair(
"use-external-name",
false),
1886 DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
1888 enum { CF_NotSet, CF_List, CF_External } ContentsField = CF_NotSet;
1889 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>>
1891 SmallString<256> ExternalContentsPath;
1892 SmallString<256>
Name;
1893 yaml::Node *NameValueNode =
nullptr;
1897 for (
auto &
I : *M) {
1901 SmallString<256> Buffer;
1902 if (!parseScalarString(
I.getKey(),
Key, Buffer))
1905 if (!checkDuplicateOrUnknownKey(
I.getKey(),
Key, Keys))
1909 if (
Key ==
"name") {
1910 if (!parseScalarString(
I.getValue(),
Value, Buffer))
1913 NameValueNode =
I.getValue();
1917 }
else if (
Key ==
"type") {
1918 if (!parseScalarString(
I.getValue(),
Value, Buffer))
1920 if (
Value ==
"file")
1922 else if (
Value ==
"directory")
1924 else if (
Value ==
"directory-remap")
1927 error(
I.getValue(),
"unknown value for 'type'");
1930 }
else if (
Key ==
"contents") {
1931 if (ContentsField != CF_NotSet) {
1933 "entry already has 'contents' or 'external-contents'");
1936 ContentsField = CF_List;
1940 error(
I.getValue(),
"expected array");
1944 for (
auto &
I : *Contents) {
1945 if (std::unique_ptr<RedirectingFileSystem::Entry>
E =
1946 parseEntry(&
I, FS,
false))
1947 EntryArrayContents.push_back(std::move(
E));
1951 }
else if (
Key ==
"external-contents") {
1952 if (ContentsField != CF_NotSet) {
1954 "entry already has 'contents' or 'external-contents'");
1957 ContentsField = CF_External;
1958 if (!parseScalarString(
I.getValue(),
Value, Buffer))
1961 SmallString<256> FullPath;
1962 if (
FS->IsRelativeOverlay) {
1963 FullPath =
FS->getOverlayFileDir();
1965 "External contents prefix directory must exist");
1966 SmallString<256> AbsFullPath =
Value;
1967 if (
FS->makeAbsolute(FullPath, AbsFullPath)) {
1968 error(
N,
"failed to make 'external-contents' absolute");
1971 FullPath = AbsFullPath;
1978 FullPath = canonicalize(FullPath);
1979 ExternalContentsPath = FullPath.
str();
1980 }
else if (
Key ==
"use-external-name") {
1982 if (!parseScalarBool(
I.getValue(), Val))
1995 if (ContentsField == CF_NotSet) {
1996 error(
N,
"missing key 'contents' or 'external-contents'");
1999 if (!checkMissingKeys(
N, Keys))
2005 error(
N,
"'use-external-name' is not supported for 'directory' entries");
2010 ContentsField == CF_List) {
2011 error(
N,
"'contents' is not supported for 'directory-remap' entries");
2020 path_style = sys::path::Style::posix;
2022 sys::path::Style::windows_backslash)) {
2023 path_style = sys::path::Style::windows_backslash;
2029 if (
FS->RootRelative ==
2030 RedirectingFileSystem::RootRelativeKind::OverlayDir) {
2031 StringRef FullPath =
FS->getOverlayFileDir();
2032 assert(!FullPath.
empty() &&
"Overlay file directory must exist");
2033 EC =
FS->makeAbsolute(FullPath, Name);
2034 Name = canonicalize(Name);
2036 EC =
FS->makeAbsolute(Name);
2039 assert(NameValueNode &&
"Name presence should be checked earlier");
2042 "entry with relative path at the root level is not discoverable");
2046 ? sys::path::Style::posix
2047 : sys::path::Style::windows_backslash;
2052 if (path_style == sys::path::Style::windows_backslash &&
2053 getExistingStyle(Name) != sys::path::Style::windows_backslash)
2054 path_style = sys::path::Style::windows_slash;
2058 StringRef Trimmed =
Name;
2060 while (Trimmed.
size() > RootPathLen &&
2062 Trimmed = Trimmed.
slice(0, Trimmed.
size() - 1);
2067 std::unique_ptr<RedirectingFileSystem::Entry>
Result;
2070 Result = std::make_unique<RedirectingFileSystem::FileEntry>(
2071 LastComponent, std::move(ExternalContentsPath), UseExternalName);
2074 Result = std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
2075 LastComponent, std::move(ExternalContentsPath), UseExternalName);
2078 Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
2079 LastComponent, std::move(EntryArrayContents),
2093 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
2094 Entries.push_back(std::move(Result));
2095 Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
2096 *
I, std::move(Entries),
2110 error(Root,
"expected mapping node");
2114 KeyStatusPair Fields[] = {
2115 KeyStatusPair(
"version",
true),
2116 KeyStatusPair(
"case-sensitive",
false),
2117 KeyStatusPair(
"use-external-names",
false),
2118 KeyStatusPair(
"root-relative",
false),
2119 KeyStatusPair(
"overlay-relative",
false),
2120 KeyStatusPair(
"fallthrough",
false),
2121 KeyStatusPair(
"redirecting-with",
false),
2122 KeyStatusPair(
"roots",
true),
2126 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> RootEntries;
2129 for (
auto &
I : *Top) {
2132 if (!parseScalarString(
I.getKey(),
Key, KeyBuffer))
2135 if (!checkDuplicateOrUnknownKey(
I.getKey(),
Key, Keys))
2138 if (
Key ==
"roots") {
2141 error(
I.getValue(),
"expected array");
2145 for (
auto &
I : *Roots) {
2146 if (std::unique_ptr<RedirectingFileSystem::Entry> E =
2147 parseEntry(&
I, FS,
true))
2148 RootEntries.push_back(std::move(E));
2152 }
else if (
Key ==
"version") {
2155 if (!parseScalarString(
I.getValue(), VersionString, Storage))
2159 error(
I.getValue(),
"expected integer");
2163 error(
I.getValue(),
"invalid version number");
2167 error(
I.getValue(),
"version mismatch, expected 0");
2170 }
else if (
Key ==
"case-sensitive") {
2171 if (!parseScalarBool(
I.getValue(), FS->CaseSensitive))
2173 }
else if (
Key ==
"overlay-relative") {
2174 if (!parseScalarBool(
I.getValue(), FS->IsRelativeOverlay))
2176 }
else if (
Key ==
"use-external-names") {
2177 if (!parseScalarBool(
I.getValue(), FS->UseExternalNames))
2179 }
else if (
Key ==
"fallthrough") {
2180 if (Keys[
"redirecting-with"].Seen) {
2182 "'fallthrough' and 'redirecting-with' are mutually exclusive");
2186 bool ShouldFallthrough =
false;
2187 if (!parseScalarBool(
I.getValue(), ShouldFallthrough))
2190 if (ShouldFallthrough) {
2195 }
else if (
Key ==
"redirecting-with") {
2196 if (Keys[
"fallthrough"].Seen) {
2198 "'fallthrough' and 'redirecting-with' are mutually exclusive");
2202 if (
auto Kind = parseRedirectKind(
I.getValue())) {
2203 FS->Redirection = *Kind;
2205 error(
I.getValue(),
"expected valid redirect kind");
2208 }
else if (
Key ==
"root-relative") {
2209 if (
auto Kind = parseRootRelativeKind(
I.getValue())) {
2210 FS->RootRelative = *Kind;
2212 error(
I.getValue(),
"expected valid root-relative kind");
2220 if (Stream.failed())
2223 if (!checkMissingKeys(Top, Keys))
2229 for (
auto &E : RootEntries)
2230 uniqueOverlayTree(FS, E.get());
2236std::unique_ptr<RedirectingFileSystem>
2239 StringRef YAMLFilePath,
void *DiagContext,
2247 if (DI == Stream.
end() || !Root) {
2254 std::unique_ptr<RedirectingFileSystem> FS(
2255 new RedirectingFileSystem(ExternalFS));
2257 if (!YAMLFilePath.
empty()) {
2267 std::error_code EC = FS->makeAbsolute(OverlayAbsDir);
2268 assert(!EC &&
"Overlay dir final path must be absolute");
2270 FS->setOverlayFileDir(OverlayAbsDir);
2273 if (!
P.parse(Root, FS.get()))
2280 ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
2282 std::unique_ptr<RedirectingFileSystem> FS(
2283 new RedirectingFileSystem(ExternalFS));
2284 FS->UseExternalNames = UseExternalNames;
2292 auto EC = ExternalFS->makeAbsolute(From);
2294 assert(!EC &&
"Could not make absolute path");
2312 assert(Parent &&
"File without a directory?");
2314 auto EC = ExternalFS->makeAbsolute(To);
2316 assert(!EC &&
"Could not make absolute path");
2320 auto NewFile = std::make_unique<RedirectingFileSystem::FileEntry>(
2324 ToEntry = NewFile.get();
2326 std::move(NewFile));
2342 getExistingStyle(DRE->getExternalContentsPath()));
2343 ExternalRedirect = std::string(Redirect);
2355std::error_code RedirectingFileSystem::makeCanonicalForLookup(
2357 if (std::error_code EC = makeAbsolute(Path))
2361 canonicalize(
StringRef(Path.data(), Path.size()));
2362 if (CanonicalPath.
empty())
2365 Path.assign(CanonicalPath.
begin(), CanonicalPath.
end());
2372 if (std::error_code EC = makeCanonicalForLookup(CanonicalPath))
2382 for (
const auto &Root : Roots) {
2384 lookupPathImpl(Start,
End, Root.get(), Entries);
2388 Result->Parents = std::move(Entries);
2399RedirectingFileSystem::lookupPathImpl(
2405 "Paths should not contain traversal components");
2410 if (!FromName.
empty()) {
2411 if (!pathComponentMatches(*Start, FromName))
2418 return LookupResult(From, Start,
End);
2426 return LookupResult(From, Start,
End);
2429 for (
const std::unique_ptr<RedirectingFileSystem::Entry> &DirEntry :
2433 lookupPathImpl(Start,
End, DirEntry.get(), Entries);
2443 bool UseExternalNames,
2448 return ExternalStatus;
2450 Status S = ExternalStatus;
2451 if (!UseExternalNames)
2458ErrorOr<Status> RedirectingFileSystem::status(
2459 const Twine &LookupPath,
const Twine &OriginalPath,
2460 const RedirectingFileSystem::LookupResult &Result) {
2461 if (std::optional<StringRef> ExtRedirect =
Result.getExternalRedirect()) {
2462 SmallString<256> RemappedPath((*ExtRedirect).str());
2463 if (std::error_code EC = makeAbsolute(RemappedPath))
2466 ErrorOr<Status> S = ExternalFS->status(RemappedPath);
2472 RE->useExternalName(UseExternalNames), *S);
2480RedirectingFileSystem::getExternalStatus(
const Twine &LookupPath,
2481 const Twine &OriginalPath)
const {
2482 auto Result = ExternalFS->status(LookupPath);
2486 if (!Result ||
Result->ExposesExternalVFSPath)
2495 if (std::error_code EC = makeAbsolute(Path))
2511 isFileNotFound(Result.getError()))
2512 return getExternalStatus(Path, OriginalPath);
2513 return Result.getError();
2518 isFileNotFound(S.
getError(), Result->E)) {
2522 return getExternalStatus(Path, OriginalPath);
2532 if (makeAbsolute(Path))
2538 if (ExternalFS->exists(Path))
2547 isFileNotFound(Result.getError()))
2548 return ExternalFS->exists(Path);
2552 std::optional<StringRef> ExtRedirect = Result->getExternalRedirect();
2559 if (makeAbsolute(RemappedPath))
2562 if (ExternalFS->exists(RemappedPath))
2569 return ExternalFS->exists(Path);
2578class FileWithFixedStatus :
public File {
2579 std::unique_ptr<File> InnerFile;
2583 FileWithFixedStatus(std::unique_ptr<File> InnerFile,
Status S)
2589 getBuffer(
const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator,
2590 bool IsVolatile)
override {
2591 return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
2595 std::error_code close()
override {
return InnerFile->close(); }
2597 void setPath(
const Twine &Path)
override { S = S.
copyWithNewName(S, Path); }
2602ErrorOr<std::unique_ptr<File>>
2606 if (!Result || (*Result)->status()->ExposesExternalVFSPath)
2610 auto Name =
F->get()->getName();
2611 if (Name && Name.get() !=
P.str())
2612 F->get()->setPath(
P);
2621 if (std::error_code EC = makeAbsolute(Path))
2637 isFileNotFound(Result.getError()))
2639 return Result.getError();
2642 if (!Result->getExternalRedirect())
2645 StringRef ExtRedirect = *Result->getExternalRedirect();
2647 if (std::error_code EC = makeAbsolute(RemappedPath))
2654 if (!ExternalFile) {
2656 isFileNotFound(ExternalFile.getError(), Result->E)) {
2662 return ExternalFile;
2665 auto ExternalStatus = (*ExternalFile)->status();
2666 if (!ExternalStatus)
2667 return ExternalStatus.getError();
2672 OriginalPath, RE->useExternalName(UseExternalNames), *ExternalStatus);
2673 return std::unique_ptr<File>(
2674 std::make_unique<FileWithFixedStatus>(std::move(*ExternalFile), S));
2683 if (std::error_code EC = makeAbsolute(Path))
2689 std::error_code EC = ExternalFS->getRealPath(Path, Output);
2699 isFileNotFound(Result.getError()))
2700 return ExternalFS->getRealPath(Path, Output);
2701 return Result.getError();
2706 if (
auto ExtRedirect = Result->getExternalRedirect()) {
2707 auto P = ExternalFS->getRealPath(*ExtRedirect, Output);
2709 isFileNotFound(
P, Result->E)) {
2713 return ExternalFS->getRealPath(Path, Output);
2721 Result->getPath(Output);
2732 if (makeAbsolute(Path))
2741 if (ConsultsExternalFS)
2742 ExternalFS->getDirectoryContentRealSources(Path, Out);
2746 switch (Result->E->getKind()) {
2756 if (!makeAbsolute(RemappedPath))
2757 ExternalFS->getDirectoryContentRealSources(RemappedPath, Out);
2763 if (ConsultsExternalFS)
2764 ExternalFS->getDirectoryContentRealSources(Path, Out);
2767std::unique_ptr<FileSystem>
2770 StringRef YAMLFilePath,
void *DiagContext,
2773 YAMLFilePath, DiagContext,
2774 std::move(ExternalFS));
2783 assert(DE &&
"Must be a directory");
2784 for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
2786 Path.push_back(SubEntry->getName());
2795 assert(DR &&
"Must be a directory remap");
2797 for (
auto &Comp : Path)
2806 assert(FE &&
"Must be a file");
2808 for (
auto &Comp : Path)
2824 static std::atomic<unsigned> UID;
2825 unsigned ID = ++UID;
2828 return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
2836 Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
2840 addEntry(VirtualPath, RealPath,
false);
2845 addEntry(VirtualPath, RealPath,
true);
2854 unsigned getDirIndent() {
return 4 * DirStack.
size(); }
2855 unsigned getFileIndent() {
return 4 * (DirStack.
size() + 1); }
2859 void endDirectory();
2866 std::optional<bool> UseExternalNames,
2867 std::optional<bool> IsCaseSensitive,
2868 std::optional<bool> IsOverlayRelative, StringRef OverlayDir);
2873bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
2874 using namespace llvm::sys;
2879 IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
2880 if (*IParent != *IChild)
2884 return IParent == EParent;
2887StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
2889 assert(containedIn(Parent, Path));
2890 return Path.substr(Parent.
size() + 1);
2893void JSONWriter::startDirectory(StringRef Path) {
2895 DirStack.
empty() ?
Path : containedPart(DirStack.
back(), Path);
2897 unsigned Indent = getDirIndent();
2898 OS.
indent(Indent) <<
"{\n";
2899 OS.
indent(Indent + 2) <<
"'type': 'directory',\n";
2901 OS.
indent(Indent + 2) <<
"'contents': [\n";
2904void JSONWriter::endDirectory() {
2905 unsigned Indent = getDirIndent();
2906 OS.
indent(Indent + 2) <<
"]\n";
2907 OS.
indent(Indent) <<
"}";
2912void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
2913 unsigned Indent = getFileIndent();
2914 OS.
indent(Indent) <<
"{\n";
2915 OS.
indent(Indent + 2) <<
"'type': 'file',\n";
2917 OS.
indent(Indent + 2) <<
"'external-contents': \""
2919 OS.
indent(Indent) <<
"}";
2923 std::optional<bool> UseExternalNames,
2924 std::optional<bool> IsCaseSensitive,
2925 std::optional<bool> IsOverlayRelative,
2927 using namespace llvm::sys;
2931 if (IsCaseSensitive)
2932 OS <<
" 'case-sensitive': '" << (*IsCaseSensitive ?
"true" :
"false")
2934 if (UseExternalNames)
2935 OS <<
" 'use-external-names': '" << (*UseExternalNames ?
"true" :
"false")
2937 bool UseOverlayRelative =
false;
2938 if (IsOverlayRelative) {
2939 UseOverlayRelative = *IsOverlayRelative;
2940 OS <<
" 'overlay-relative': '" << (UseOverlayRelative ?
"true" :
"false")
2943 OS <<
" 'roots': [\n";
2945 if (!Entries.
empty()) {
2953 if (UseOverlayRelative) {
2955 "Overlay dir must be contained in RPath");
2959 bool IsCurrentDirEmpty =
true;
2960 if (!
Entry.IsDirectory) {
2962 IsCurrentDirEmpty =
false;
2968 if (Dir == DirStack.
back()) {
2969 if (!IsCurrentDirEmpty) {
2973 bool IsDirPoppedFromStack =
false;
2974 while (!DirStack.
empty() && !containedIn(DirStack.
back(), Dir)) {
2977 IsDirPoppedFromStack =
true;
2979 if (IsDirPoppedFromStack || !IsCurrentDirEmpty) {
2982 startDirectory(Dir);
2983 IsCurrentDirEmpty =
true;
2986 if (UseOverlayRelative) {
2988 "Overlay dir must be contained in RPath");
2991 if (!
Entry.IsDirectory) {
2993 IsCurrentDirEmpty =
false;
2997 while (!DirStack.
empty()) {
3010 return LHS.VPath < RHS.VPath;
3013 JSONWriter(OS).
write(Mappings, UseExternalNames, IsCaseSensitive,
3014 IsOverlayRelative, OverlayDir);
3022 State = std::make_shared<detail::RecDirIterState>();
3023 State->Stack.push_back(
I);
3029 assert(FS && State && !State->Stack.empty() &&
"incrementing past end");
3030 assert(!State->Stack.back()->path().empty() &&
"non-canonical end iterator");
3033 if (State->HasNoPushRequest)
3034 State->HasNoPushRequest =
false;
3038 FS->dir_begin(State->Stack.back()->path(), EC);
3040 State->Stack.push_back(
I);
3046 while (!State->Stack.empty() && State->Stack.back().increment(EC) ==
End)
3047 State->Stack.pop_back();
3049 if (State->Stack.empty())
3061unsigned ::llvm::IntrusiveRefCntPtrInfo<FileSystem>::useCount(
3063 return FS->UseCount();
3066void ::llvm::IntrusiveRefCntPtrInfo<FileSystem>::retain(
FileSystem *FS) {
3070void ::llvm::IntrusiveRefCntPtrInfo<FileSystem>::release(
FileSystem *FS) {
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<T> 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)
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
bool empty() const
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",...
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
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
char back() const
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
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 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.
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.
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.
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
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.
llvm::ErrorOr< bool > equivalent(const Twine &A, const Twine &B)
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
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,...
std::error_code isLocal(const Twine &Path, bool &Result) override
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Canonicalizes Path by combining with the current working directory and normalizing the path (e....
~InMemoryFileSystem() override
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
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
llvm::ErrorOr< Status > status(const Twine &Path) override
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
void visitChildFileSystems(VisitCallbackTy Callback) override
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
void getDirectoryContentRealSources(const Twine &Dir, SmallVectorImpl< std::string > &Out) override
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
std::error_code isLocal(const Twine &Path, bool &Result) override
bool exists(const Twine &Path) override
llvm::ErrorOr< Status > status(const Twine &Path) override
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
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.
bool exists(const Twine &Path) override
Check whether Path exists.
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
friend class RedirectingFileSystemParser
std::vector< llvm::StringRef > getRoots() const
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
ErrorOr< LookupResult > lookupPath(StringRef Path) const
Looks up Path in Roots and returns a LookupResult giving the matched entry and, if the entry was a Fi...
RedirectKind
The type of redirection to perform.
@ Fallthrough
Lookup the redirected path first (ie.
@ Fallback
Lookup the provided path first and if that fails, "fallback" to a lookup of the redirected path.
@ RedirectOnly
Only lookup the redirected path, do not lookup the originally provided path.
void setFallthrough(bool Fallthrough)
Sets the redirection kind to Fallthrough if true or RedirectOnly otherwise.
void visitChildFileSystems(VisitCallbackTy Callback) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Gets real path of Path e.g.
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the text 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.
StringRef getOverlayFileDir() const
void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel=0) const
void getDirectoryContentRealSources(const Twine &Dir, SmallVectorImpl< std::string > &Out) override
Collect the paths in the real file system that contribute to a potentially virtual directory when ite...
The result of a status operation.
llvm::sys::fs::UniqueID getUniqueID() const
LLVM_ABI bool equivalent(const Status &Other) const
static LLVM_ABI Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
LLVM_ABI bool isStatusKnown() const
LLVM_ABI bool exists() const
bool ExposesExternalVFSPath
Whether this entity has an external path different from the virtual path, and the external path is ex...
uint32_t getGroup() const
static LLVM_ABI Status copyWithNewSize(const Status &In, uint64_t NewSize)
Get a copy of a Status with a different size.
LLVM_ABI bool isOther() const
LLVM_ABI bool isSymlink() const
llvm::sys::TimePoint getLastModificationTime() const
llvm::sys::fs::file_type getType() const
LLVM_ABI bool isRegularFile() const
LLVM_ABI bool isDirectory() const
LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath)
LLVM_ABI void write(llvm::raw_ostream &OS)
LLVM_ABI 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.
LLVM_ABI 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.
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.
@ Resolved
Queried, materialization begun.
LLVM_ABI std::error_code closeFile(file_t &F)
Close the file object.
@ 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 getRealPathFromHandle(file_t Handle, SmallVectorImpl< char > &RealPath)
Get the real path of an open file from its handle.
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)
Remove '.
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.
void violationIfEnabled()
ScopedSetting scopedDisable()
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.
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.
LLVM_ABI 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_ABI llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
static sys::fs::UniqueID getUniqueID(hash_code Hash)
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
LLVM_ABI std::unique_ptr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
static sys::fs::UniqueID getDirectoryID(sys::fs::UniqueID Parent, llvm::StringRef Name)
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
@ 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)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
LLVM_ABI Error write(DWPWriter &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue, raw_pwrite_stream *OS=nullptr)
Implement std::hash so that hash_code can be used in STL containers.
static constexpr value_type Invalid
Value for an invalid file descriptor.
This class wraps the platform specific file handle/descriptor type to provide an unified representati...
bool isValid() const
Is a valid file.
Entry * E
The entry the looked-up path corresponds to.
LLVM_ABI LookupResult(Entry *E, sys::path::const_iterator Start, sys::path::const_iterator End)
LLVM_ABI void getPath(llvm::SmallVectorImpl< char > &Path) const
Get the (canonical) path of the found entry.
llvm::SmallVector< Entry *, 32 > Parents
Chain of parent directory entries for E.
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
llvm::sys::fs::file_type Type
std::unique_ptr< llvm::MemoryBuffer > Buffer
llvm::sys::fs::perms Perms
llvm::sys::fs::UniqueID DirUID