27 #include "llvm/Config/llvm-config.h" 53 #include <system_error> 66 : UID(Status.
getUniqueID()), MTime(Status.getLastModificationTime()),
67 User(Status.getUser()), Group(Status.getGroup()),
Size(Status.getSize()),
68 Type(Status.
type()), Perms(Status.permissions()) {}
73 : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
115 bool RequiresNullTerminator,
bool IsVolatile) {
120 return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
127 auto WorkingDir = getCurrentWorkingDirectory();
129 return WorkingDir.getError();
171 class RealFile :
public File {
172 friend class RealFileSystem;
176 std::string RealName;
179 : FD(FD), S(NewName, {}, {}, {}, {}, {},
181 RealName(NewRealPathName.
str()) {
182 assert(FD >= 0 &&
"Invalid or inactive file descriptor");
186 ~RealFile()
override;
192 bool RequiresNullTerminator,
194 std::error_code close()
override;
199 RealFile::~RealFile() { close(); }
202 assert(FD != -1 &&
"cannot stat closed file");
203 if (!S.isStatusKnown()) {
213 return RealName.
empty() ? S.getName().str() : RealName;
217 RealFile::getBuffer(
const Twine &Name, int64_t FileSize,
218 bool RequiresNullTerminator,
bool IsVolatile) {
219 assert(FD != -1 &&
"cannot get buffer for closed file");
224 std::error_code RealFile::close() {
240 std::error_code setCurrentWorkingDirectory(
const Twine &Path)
override;
241 std::error_code isLocal(
const Twine &Path,
bool &Result)
override;
242 std::error_code getRealPath(
const Twine &Path,
246 mutable std::mutex CWDMutex;
247 mutable std::string CWDCache;
263 if (std::error_code EC =
266 return std::unique_ptr<File>(
new RealFile(FD, Name.
str(), RealName.
str()));
270 std::lock_guard<std::mutex>
Lock(CWDMutex);
271 if (!CWDCache.empty())
276 CWDCache = Dir.
str();
280 std::error_code RealFileSystem::setCurrentWorkingDirectory(
const Twine &Path) {
292 std::lock_guard<std::mutex>
Lock(CWDMutex);
294 return std::error_code();
297 std::error_code RealFileSystem::isLocal(
const Twine &Path,
bool &Result) {
302 RealFileSystem::getRealPath(
const Twine &Path,
318 RealFSDirIter(
const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
323 std::error_code increment()
override {
336 std::error_code &EC) {
345 FSList.push_back(std::move(BaseFS));
349 FSList.push_back(FS);
357 for (
iterator I = overlays_begin(),
E = overlays_end();
I !=
E; ++
I) {
368 for (
iterator I = overlays_begin(),
E = overlays_end();
I !=
E; ++
I) {
369 auto Result = (*I)->openFileForRead(Path);
379 return FSList.front()->getCurrentWorkingDirectory();
384 for (
auto &FS : FSList)
385 if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
391 for (
auto &FS : FSList)
392 if (FS->exists(Path))
393 return FS->isLocal(Path, Result);
400 for (
auto &FS : FSList)
401 if (FS->exists(Path))
402 return FS->getRealPath(Path, Output);
417 std::error_code incrementFS() {
420 for (
auto E = Overlays.
overlays_end(); CurrentFS !=
E; ++CurrentFS) {
422 CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
431 std::error_code incrementDirIter(
bool IsFirstTime) {
433 "incrementing past end");
442 std::error_code incrementImpl(
bool IsFirstTime) {
444 std::error_code EC = incrementDirIter(IsFirstTime);
449 CurrentEntry = *CurrentDirIter;
451 if (SeenNames.
insert(Name).second)
461 CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
462 EC = incrementImpl(
true);
465 std::error_code increment()
override {
return incrementImpl(
false); }
471 std::error_code &EC) {
473 std::make_shared<OverlayFSDirIterImpl>(Dir, *
this, EC));
476 void ProxyFileSystem::anchor() {}
489 std::string FileName;
493 : Kind(Kind), FileName(
llvm::sys::path::
filename(FileName)) {}
504 std::unique_ptr<llvm::MemoryBuffer> Buffer;
509 Buffer(
std::move(Buffer)) {}
520 return (std::string(Indent,
' ') + Stat.
getName() +
"\n").str();
535 :
InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
536 const InMemoryFile &getResolvedFile()
const {
return ResolvedFile; }
539 return std::string(Indent,
' ') +
"HardLink to -> " +
551 class InMemoryFileAdaptor :
public File {
554 std::string RequestedName;
558 std::string RequestedName)
559 : Node(Node), RequestedName(std::move(RequestedName)) {}
566 getBuffer(
const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator,
567 bool IsVolatile)
override {
573 std::error_code close()
override {
return {}; }
592 auto I = Entries.
find(Name);
593 if (
I != Entries.
end())
594 return I->second.get();
599 return Entries.
insert(make_pair(Name, std::move(Child)))
600 .first->second.get();
610 (std::string(Indent,
' ') + Stat.
getName() +
"\n").str();
611 for (
const auto &Entry : Entries)
612 Result += Entry.second->toString(Indent + 2);
623 if (
auto Dir = dyn_cast<detail::InMemoryDirectory>(Node))
624 return Dir->getStatus(RequestedName);
625 if (
auto File = dyn_cast<detail::InMemoryFile>(Node))
626 return File->getStatus(RequestedName);
627 if (
auto Link = dyn_cast<detail::InMemoryHardLink>(Node))
628 return Link->getResolvedFile().getStatus(RequestedName);
635 : Root(new detail::InMemoryDirectory(
639 UseNormalizedPaths(UseNormalizedPaths) {}
644 return Root->toString(0);
647 bool InMemoryFileSystem::addFile(
const Twine &
P, time_t ModificationTime,
648 std::unique_ptr<llvm::MemoryBuffer> Buffer,
671 const auto ResolvedGroup = Group.
getValueOr(0);
674 assert(!(HardLinkTarget && Buffer) &&
"HardLink cannot have a buffer");
685 std::unique_ptr<detail::InMemoryNode> Child;
687 Child.reset(
new detail::InMemoryHardLink(P.
str(), *HardLinkTarget));
692 ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
701 Dir->
addChild(Name, std::move(Child));
711 Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
712 Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
716 if (
auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
719 assert((isa<detail::InMemoryFile>(Node) ||
720 isa<detail::InMemoryHardLink>(Node)) &&
721 "Must be either file, hardlink or directory!");
728 if (
auto Link = dyn_cast<detail::InMemoryHardLink>(Node)) {
729 return Link->getResolvedFile().getBuffer()->getBuffer() ==
732 return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
738 bool InMemoryFileSystem::addFile(
const Twine &P, time_t ModificationTime,
739 std::unique_ptr<llvm::MemoryBuffer> Buffer,
744 return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type,
754 return addFile(P, ModificationTime,
757 std::move(User), std::move(Group), std::move(Type),
786 if (
auto File = dyn_cast<detail::InMemoryFile>(Node)) {
793 if (
auto File = dyn_cast<detail::InMemoryHardLink>(Node)) {
795 return &
File->getResolvedFile();
799 Dir = cast<detail::InMemoryDirectory>(Node);
806 const Twine &ToPath) {
811 if (!ToNode || FromNode || !isa<detail::InMemoryFile>(*ToNode))
814 cast<detail::InMemoryFile>(*ToNode));
820 return detail::getNodeStatus(*Node, Path.
str());
821 return Node.getError();
828 return Node.getError();
832 if (
auto *
F = dyn_cast<detail::InMemoryFile>(*Node))
833 return std::unique_ptr<File>(
834 new detail::InMemoryFileAdaptor(*
F, Path.
str()));
846 std::string RequestedDirName;
848 void setCurrentEntry() {
853 switch (I->second->getKind()) {
871 InMemoryDirIterator() =
default;
874 std::string RequestedDirName)
876 RequestedDirName(std::move(RequestedDirName)) {
880 std::error_code increment()
override {
890 std::error_code &EC) {
893 EC = Node.getError();
897 if (
auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
899 std::make_shared<InMemoryDirIterator>(*DirNode, Dir.
str()));
918 WorkingDirectory = Path.
str();
926 if (!CWD || CWD->empty())
961 bool IterateExternalFS;
963 bool IsExternalFSCurrent =
false;
974 std::error_code incrementImpl(
bool IsFirstTime);
976 std::error_code incrementContent(
bool IsFirstTime);
978 std::error_code incrementExternal();
986 bool IterateExternalFS,
FileSystem &ExternalFS, std::error_code &EC);
988 std::error_code increment()
override;
993 return ExternalFS->getCurrentWorkingDirectory();
998 return ExternalFS->setCurrentWorkingDirectory(Path);
1003 return ExternalFS->isLocal(Path, Result);
1007 std::error_code &EC) {
1012 return ExternalFS->dir_begin(Dir, EC);
1020 if (!S->isDirectory()) {
1022 std::system_category());
1026 auto *
D = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(*E);
1028 Dir,
D->contents_begin(),
D->contents_end(),
1029 IsFallthrough, *ExternalFS, EC));
1033 ExternalContentsPrefixDir = PrefixDir.
str();
1037 return ExternalContentsPrefixDir;
1040 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1042 for (
const auto &Root : Roots)
1043 dumpEntry(Root.get());
1048 int NumSpaces)
const {
1050 for (
int i = 0, e = NumSpaces; i < e; ++i)
1052 dbgs() <<
"'" << Name.
str().c_str() <<
"'" 1057 assert(DE &&
"Should be a directory");
1059 for (std::unique_ptr<Entry> &SubEntry :
1061 dumpEntry(SubEntry.get(), NumSpaces + 2);
1078 error(N,
"expected string");
1081 Result = S->getValue(Storage);
1086 bool parseScalarBool(
yaml::Node *N,
bool &Result) {
1089 if (!parseScalarString(N, Value, Storage))
1102 error(N,
"expected boolean value");
1110 KeyStatus(
bool Required =
false) :
Required(Required) {}
1113 using KeyStatusPair = std::pair<StringRef, KeyStatus>;
1118 if (!Keys.
count(Key)) {
1119 error(KeyNode,
"unknown key");
1122 KeyStatus &S = Keys[
Key];
1124 error(KeyNode,
Twine(
"duplicate key '") + Key +
"'");
1133 for (
const auto &
I : Keys) {
1134 if (
I.second.Required && !
I.second.Seen) {
1135 error(Obj,
Twine(
"missing key '") +
I.first +
"'");
1146 for (
const auto &Root : FS->Roots) {
1147 if (Name.
equals(Root->getName())) {
1148 ParentEntry = Root.get();
1155 for (std::unique_ptr<RedirectingFileSystem::Entry> &Content :
1160 if (DirContent && Name.
equals(Content->getName()))
1166 std::unique_ptr<RedirectingFileSystem::Entry>
E =
1167 llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
1173 FS->Roots.push_back(std::move(E));
1174 ParentEntry = FS->Roots.back().get();
1181 return DE->getLastContent();
1192 assert(DE &&
"Must be a directory");
1197 NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
1198 for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
1200 uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
1205 assert(FE &&
"Must be a file");
1206 assert(NewParentE &&
"Parent entry must exist");
1210 llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
1211 Name, FE->getExternalContentsPath(), FE->getUseName()));
1217 std::unique_ptr<RedirectingFileSystem::Entry>
1221 error(N,
"expected mapping node for file or directory entry");
1225 KeyStatusPair Fields[] = {
1226 KeyStatusPair(
"name",
true),
1227 KeyStatusPair(
"type",
true),
1228 KeyStatusPair(
"contents",
false),
1229 KeyStatusPair(
"external-contents",
false),
1230 KeyStatusPair(
"use-external-name",
false),
1235 bool HasContents =
false;
1236 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>>
1238 std::string ExternalContentsPath;
1241 auto UseExternalName =
1245 for (
auto &
I : *M) {
1250 if (!parseScalarString(
I.getKey(),
Key, Buffer))
1253 if (!checkDuplicateOrUnknownKey(
I.getKey(),
Key, Keys))
1257 if (Key ==
"name") {
1258 if (!parseScalarString(
I.getValue(), Value, Buffer))
1261 NameValueNode =
I.getValue();
1262 if (FS->UseCanonicalizedPaths) {
1272 }
else if (Key ==
"type") {
1273 if (!parseScalarString(
I.getValue(), Value, Buffer))
1275 if (Value ==
"file")
1277 else if (Value ==
"directory")
1280 error(
I.getValue(),
"unknown value for 'type'");
1283 }
else if (Key ==
"contents") {
1286 "entry already has 'contents' or 'external-contents'");
1293 error(
I.getValue(),
"expected array");
1297 for (
auto &
I : *Contents) {
1298 if (std::unique_ptr<RedirectingFileSystem::Entry>
E =
1299 parseEntry(&
I, FS,
false))
1300 EntryArrayContents.push_back(std::move(
E));
1304 }
else if (Key ==
"external-contents") {
1307 "entry already has 'contents' or 'external-contents'");
1311 if (!parseScalarString(
I.getValue(), Value, Buffer))
1315 if (FS->IsRelativeOverlay) {
1318 "External contents prefix directory must exist");
1324 if (FS->UseCanonicalizedPaths) {
1330 ExternalContentsPath = FullPath.
str();
1331 }
else if (Key ==
"use-external-name") {
1333 if (!parseScalarBool(
I.getValue(), Val))
1348 error(N,
"missing key 'contents' or 'external-contents'");
1351 if (!checkMissingKeys(N, Keys))
1358 error(N,
"'use-external-name' is not supported for directories");
1363 assert(NameValueNode &&
"Name presence should be checked earlier");
1364 error(NameValueNode,
1365 "entry with relative path at the root level is not discoverable");
1372 while (Trimmed.
size() > RootPathLen &&
1374 Trimmed = Trimmed.
slice(0, Trimmed.
size() - 1);
1378 std::unique_ptr<RedirectingFileSystem::Entry> Result;
1381 Result = llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
1382 LastComponent, std::move(ExternalContentsPath), UseExternalName);
1386 llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
1387 LastComponent, std::move(EntryArrayContents),
1402 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
1403 Entries.push_back(std::move(Result));
1405 llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
1406 *
I, std::move(Entries),
1421 error(Root,
"expected mapping node");
1425 KeyStatusPair Fields[] = {
1426 KeyStatusPair(
"version",
true),
1427 KeyStatusPair(
"case-sensitive",
false),
1428 KeyStatusPair(
"use-external-names",
false),
1429 KeyStatusPair(
"overlay-relative",
false),
1430 KeyStatusPair(
"fallthrough",
false),
1431 KeyStatusPair(
"roots",
true),
1435 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> RootEntries;
1438 for (
auto &
I : *Top) {
1441 if (!parseScalarString(
I.getKey(),
Key, KeyBuffer))
1444 if (!checkDuplicateOrUnknownKey(
I.getKey(),
Key, Keys))
1447 if (Key ==
"roots") {
1450 error(
I.getValue(),
"expected array");
1454 for (
auto &
I : *Roots) {
1455 if (std::unique_ptr<RedirectingFileSystem::Entry>
E =
1456 parseEntry(&
I, FS,
true))
1457 RootEntries.push_back(std::move(
E));
1461 }
else if (Key ==
"version") {
1464 if (!parseScalarString(
I.getValue(), VersionString, Storage))
1468 error(
I.getValue(),
"expected integer");
1472 error(
I.getValue(),
"invalid version number");
1476 error(
I.getValue(),
"version mismatch, expected 0");
1479 }
else if (Key ==
"case-sensitive") {
1480 if (!parseScalarBool(
I.getValue(), FS->CaseSensitive))
1482 }
else if (Key ==
"overlay-relative") {
1483 if (!parseScalarBool(
I.getValue(), FS->IsRelativeOverlay))
1485 }
else if (Key ==
"use-external-names") {
1486 if (!parseScalarBool(
I.getValue(), FS->UseExternalNames))
1488 }
else if (Key ==
"fallthrough") {
1489 if (!parseScalarBool(
I.getValue(), FS->IsFallthrough))
1499 if (!checkMissingKeys(Top, Keys))
1505 for (
auto &
E : RootEntries)
1506 uniqueOverlayTree(FS,
E.get());
1515 StringRef YAMLFilePath,
void *DiagContext,
1523 if (DI == Stream.end() || !Root) {
1530 std::unique_ptr<RedirectingFileSystem> FS(
1533 if (!YAMLFilePath.
empty()) {
1544 assert(!EC &&
"Overlay dir final path must be absolute");
1546 FS->setExternalContentsPrefixDir(OverlayAbsDir);
1549 if (!P.
parse(Root, FS.get()))
1552 return FS.release();
1556 RedirectingFileSystem::lookupPath(
const Twine &Path_)
const {
1567 if (UseCanonicalizedPaths) {
1577 for (
const auto &Root : Roots) {
1579 lookupPath(Start, End, Root.get());
1593 "Paths should not contain traversal components");
1597 if (Start->equals(
"."))
1604 if (!FromName.
empty()) {
1605 if (CaseSensitive ? !Start->equals(FromName)
1606 : !Start->equals_lower(FromName))
1622 for (
const std::unique_ptr<RedirectingFileSystem::Entry> &DirEntry :
1625 lookupPath(Start, End, DirEntry.get());
1634 Status S = ExternalStatus;
1635 if (!UseExternalNames)
1644 if (
auto *
F = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(E)) {
1646 assert(!S || S->getName() ==
F->getExternalContentsPath());
1652 auto *DE = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(
E);
1660 if (IsFallthrough &&
1662 return ExternalFS->status(Path);
1666 return status(Path, *Result);
1672 class FileWithFixedStatus :
public File {
1673 std::unique_ptr<File> InnerFile;
1677 FileWithFixedStatus(std::unique_ptr<File> InnerFile,
Status S)
1678 : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
1683 getBuffer(
const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator,
1684 bool IsVolatile)
override {
1685 return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
1689 std::error_code close()
override {
return InnerFile->close(); }
1698 if (IsFallthrough &&
1700 return ExternalFS->openFileForRead(Path);
1709 auto Result = ExternalFS->openFileForRead(
F->getExternalContentsPath());
1713 auto ExternalStatus = (*Result)->status();
1714 if (!ExternalStatus)
1715 return ExternalStatus.getError();
1720 return std::unique_ptr<File>(
1721 llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
1729 if (IsFallthrough &&
1731 return ExternalFS->getRealPath(Path, Output);
1737 dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(*Result)) {
1738 return ExternalFS->getRealPath(
F->getExternalContentsPath(), Output);
1742 return IsFallthrough ? ExternalFS->getRealPath(Path, Output)
1749 StringRef YAMLFilePath,
void *DiagContext,
1752 YAMLFilePath, DiagContext,
1753 std::move(ExternalFS));
1762 assert(DE &&
"Must be a directory");
1763 for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
1774 assert(FE &&
"Must be a file");
1776 for (
auto &Comp : Path)
1788 std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
1789 std::move(ExternalFS));
1799 static std::atomic<unsigned> UID;
1800 unsigned ID = ++UID;
1810 Mappings.emplace_back(VirtualPath, RealPath);
1819 unsigned getDirIndent() {
return 4 * DirStack.
size(); }
1820 unsigned getFileIndent() {
return 4 * (DirStack.
size() + 1); }
1824 void endDirectory();
1843 IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
1844 if (*IParent != *IChild)
1848 return IParent == EParent;
1853 assert(containedIn(Parent, Path));
1857 void JSONWriter::startDirectory(
StringRef Path) {
1859 DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
1860 DirStack.push_back(Path);
1861 unsigned Indent = getDirIndent();
1862 OS.indent(Indent) <<
"{\n";
1863 OS.indent(Indent + 2) <<
"'type': 'directory',\n";
1865 OS.indent(Indent + 2) <<
"'contents': [\n";
1868 void JSONWriter::endDirectory() {
1869 unsigned Indent = getDirIndent();
1870 OS.indent(Indent + 2) <<
"]\n";
1871 OS.indent(Indent) <<
"}";
1873 DirStack.pop_back();
1877 unsigned Indent = getFileIndent();
1878 OS.indent(Indent) <<
"{\n";
1879 OS.indent(Indent + 2) <<
"'type': 'file',\n";
1881 OS.indent(Indent + 2) <<
"'external-contents': \"" 1883 OS.indent(Indent) <<
"}";
1896 OS <<
" 'case-sensitive': '" 1897 << (IsCaseSensitive.
getValue() ?
"true" :
"false") <<
"',\n";
1899 OS <<
" 'use-external-names': '" 1900 << (UseExternalNames.
getValue() ?
"true" :
"false") <<
"',\n";
1901 bool UseOverlayRelative =
false;
1902 if (IsOverlayRelative.
hasValue()) {
1903 UseOverlayRelative = IsOverlayRelative.
getValue();
1904 OS <<
" 'overlay-relative': '" << (UseOverlayRelative ?
"true" :
"false")
1907 OS <<
" 'roots': [\n";
1909 if (!Entries.
empty()) {
1914 if (UseOverlayRelative) {
1915 unsigned OverlayDirLen = OverlayDir.
size();
1917 "Overlay dir must be contained in RPath");
1918 RPath = RPath.
slice(OverlayDirLen, RPath.size());
1923 for (
const auto &Entry : Entries.
slice(1)) {
1925 if (Dir == DirStack.
back())
1928 while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
1933 startDirectory(Dir);
1936 if (UseOverlayRelative) {
1937 unsigned OverlayDirLen = OverlayDir.
size();
1939 "Overlay dir must be contained in RPath");
1940 RPath = RPath.
slice(OverlayDirLen, RPath.size());
1945 while (!DirStack.empty()) {
1961 JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
1962 IsOverlayRelative, OverlayDir);
1969 bool IterateExternalFS,
FileSystem &ExternalFS, std::error_code &EC)
1970 : Dir(_Path.str()), Current(Begin), End(End),
1971 IterateExternalFS(IterateExternalFS), ExternalFS(ExternalFS) {
1972 EC = incrementImpl(
true);
1976 return incrementImpl(
false);
1979 std::error_code VFSFromYamlDirIterImpl::incrementExternal() {
1981 "incrementing past end");
1983 if (IsExternalFSCurrent) {
1985 }
else if (IterateExternalFS) {
1986 ExternalDirIter = ExternalFS.dir_begin(Dir, EC);
1987 IsExternalFSCurrent =
true;
2000 std::error_code VFSFromYamlDirIterImpl::incrementContent(
bool IsFirstTime) {
2001 assert((IsFirstTime || Current != End) &&
"cannot iterate past end");
2004 while (Current != End) {
2008 switch ((*Current)->getKind()) {
2019 return incrementExternal();
2022 std::error_code VFSFromYamlDirIterImpl::incrementImpl(
bool IsFirstTime) {
2024 std::error_code EC = IsExternalFSCurrent ? incrementExternal()
2025 : incrementContent(IsFirstTime);
2029 if (SeenNames.
insert(Name).second)
2040 State = std::make_shared<detail::RecDirIterState>();
2041 State->Stack.push(I);
2047 assert(FS && State && !State->Stack.empty() &&
"incrementing past end");
2048 assert(!State->Stack.top()->path().empty() &&
"non-canonical end iterator");
2051 if (State->HasNoPushRequest)
2052 State->HasNoPushRequest =
false;
2057 State->Stack.push(I);
2063 while (!State->Stack.empty() && State->Stack.top().increment(EC) == End)
2066 if (State->Stack.empty())
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
const T & front() const
front - Get the first element.
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
A file system that allows overlaying one AbstractFileSystem on top of another.
static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames, Status ExternalStatus)
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
llvm::MemoryBuffer * getBuffer() const
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
const_iterator end(StringRef path)
Get end iterator over path.
llvm::StringRef path() const
Represents either an error or a value T.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
InMemoryNode * getChild(StringRef Name)
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
StringRef getBuffer() const
std::string toString(unsigned Indent) const override
This class represents lattice values for constants.
InMemoryDirectory(Status Stat)
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.
~InMemoryFileSystem() override
FileSystemList::reverse_iterator iterator
LLVM_NODISCARD bool equals_lower(StringRef RHS) const
equals_lower - Check for string equality, ignoring case.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
void push_back(const T &Elt)
perms permissions() const
static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, SmallVectorImpl< StringRef > &Path, SmallVectorImpl< YAMLVFSEntry > &Entries)
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
RedirectingFileSystemParser(yaml::Stream &S)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Status getStatus(StringRef RequestedName) const
Return the Status for this node.
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION
Represents a YAML sequence created from either a block sequence for a flow sequence.
iterator find(StringRef Key)
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...
EntryKind getKind() const
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
The result of a status operation.
The in memory file system is a tree of Nodes.
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...
directory_iterator & increment(std::error_code &ec)
StringRef remove_leading_dotslash(StringRef path, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Represents the result of a call to sys::fs::status().
LLVM_ATTRIBUTE_ALWAYS_INLINE TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges=None, ArrayRef< SMFixIt > FixIts=None, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
amdgpu Simplify well known AMD library false Value Value const Twine & Name
std::string toString(Error E)
Write all error messages (if any) in E to a string.
reverse_iterator rbegin(StringRef path, Style style=Style::native)
Get reverse begin iterator over path.
InMemoryFileSystem(bool UseNormalizedPaths=true)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
void write(llvm::raw_ostream &OS)
void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
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...
std::error_code make_error_code(BitcodeError E)
static StringRef getName(Value *V)
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
StringRef getName() const
Returns the name that should be used for this file or directory.
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
StringRef root_path(StringRef path, Style style=Style::native)
Get root path.
InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
StringRef str() const
Explicit conversion to StringRef.
static bool classof(const InMemoryNode *N)
std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
const T & getValue() const LLVM_LVALUE_FUNCTION
virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const
Gets real path of Path e.g.
bool exists(const Twine &Path)
Check whether a file exists. Provided for convenience.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
directory_entry CurrentEntry
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
std::error_code is_local(const Twine &path, bool &result)
Is the file mounted on a local filesystem?
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
InMemoryNode * addChild(StringRef Name, std::unique_ptr< InMemoryNode > Child)
llvm::sys::fs::file_type getType() const
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
void addFileMapping(StringRef VirtualPath, StringRef RealPath)
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
llvm::sys::TimePoint getLastModificationTime() const
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
bool isRegularFile() const
A virtual file system parsed from a YAML file.
static 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 ...
The instances of the Type class are immutable: once they are created, they are never changed...
void printError(Node *N, const Twine &Msg)
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
UniqueID getUniqueID() const
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
static bool classof(const InMemoryNode *N)
const_iterator end() const
std::error_code getError() const
llvm::sys::fs::perms getPermissions() const
TimePoint getLastModificationTime() const
The file modification time as reported from the underlying file system.
virtual std::error_code setCurrentWorkingDirectory(const Twine &Path)=0
Set the working directory.
bool addHardLink(const Twine &From, const Twine &To)
Add a hard link to a file.
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
InMemoryFile(Status Stat, std::unique_ptr< llvm::MemoryBuffer > Buffer)
static bool pathHasTraversal(StringRef Path)
static ErrorOr< const detail::InMemoryNode * > lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir, const Twine &P)
std::error_code getUniqueID(const Twine Path, UniqueID &Result)
static bool isTraversalComponent(StringRef Component)
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
A single file or directory in the VFS.
void addContent(std::unique_ptr< Entry > Content)
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling...
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
static void write(bool isBE, void *P, T V)
bool isStatusKnown() const
static Status copyWithNewName(const Status &In, StringRef NewName)
Get a copy of a Status with a different name.
LLVM_NODISCARD char back() const
back - Get the last character in the string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
A member of a directory, yielded by a directory_iterator.
std::pair< typename base::iterator, bool > insert(StringRef Key)
A scalar node is an opaque datum that can be presented as a series of zero or more Unicode scalar val...
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
virtual ~File()
Destroy the file after closing it (if open).
const std::string & path() const
const_iterator begin() const
void sort(IteratorTy Start, IteratorTy End)
std::string toString() const
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
BlockVerifier::State From
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
VFSFromYamlDirIterImpl(const Twine &Path, RedirectingFileSystem::RedirectingDirectoryEntry::iterator Begin, RedirectingFileSystem::RedirectingDirectoryEntry::iterator End, bool IterateExternalFS, FileSystem &ExternalFS, std::error_code &EC)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
This class represents a YAML stream potentially containing multiple documents.
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
bool equivalent(const Status &Other) const
The virtual file system interface.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
std::string toString(unsigned Indent) const override
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC)=0
Get a directory_iterator for Dir.
StringRef getExternalContentsPrefixDir() const
recursive_directory_iterator()=default
Construct an 'end' iterator.
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
uint32_t getGroup() const
uint32_t getGroup() const
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
InMemoryNodeKind getKind() const
LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces=0) const
Status getStatus(StringRef RequestedName) const
Return the Status for this node.
An in-memory file system.
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...
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
std::error_code set_current_path(const Twine &path)
Set the current path.
Defines the virtual file system interface vfs::FileSystem.
IntrusiveRefCntPtr< 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.
directory_iterator - Iterates through the entries in path.
Provides a library for accessing information about this process and other processes on the operating ...
file_type
An enumeration for the file system's view of the type.
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
LLVM_NODISCARD bool empty() const
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Represents a YAML map created from either a block map for a flow map.
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
reverse_iterator rend(StringRef path)
Get reverse end iterator over path.
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
StringRef getFileName() const
Get the filename of this node (the name without the directory part).
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::string str() const
Return the twine contents as a std::string.
void setExternalContentsPrefixDir(StringRef PrefixDir)
Provides ErrorOr<T> smart pointer.
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end...
Iterator abstraction for Documents over a Stream.
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A helper class to hold the common YAML parsing state.
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
LLVM Value Representation.
LLVM_DUMP_METHOD void dump() const
bool addFileNoOwn(const Twine &Path, time_t ModificationTime, llvm::MemoryBuffer *Buffer, Optional< uint32_t > User=None, Optional< uint32_t > Group=None, Optional< llvm::sys::fs::file_type > Type=None, Optional< llvm::sys::fs::perms > Perms=None)
Add a buffer to the VFS with a path.
llvm::sys::fs::UniqueID getUniqueID() const
static std::error_code SafelyCloseFileDescriptor(int FD)
StringSet - A wrapper for StringMap that provides set-like functionality.
This class implements an extremely fast bulk output stream that can only output to a stream...
decltype(Entries)::const_iterator const_iterator
StringRef - Represent a constant reference to a string, i.e.
decltype(Contents)::iterator iterator
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
StringRef getName() const
Represents a location in source code.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
bool empty() const
empty - Check if the array is empty.
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Abstract base class for all Nodes.
bool parse(yaml::Node *Root, RedirectingFileSystem *FS)