diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Support/VirtualFileSystem.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/lib/Support/VirtualFileSystem.cpp')
-rw-r--r-- | llvm/lib/Support/VirtualFileSystem.cpp | 165 |
1 files changed, 110 insertions, 55 deletions
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 97d63fff1069..a167e0a76795 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -14,8 +14,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -46,6 +44,7 @@ #include <iterator> #include <limits> #include <memory> +#include <optional> #include <string> #include <system_error> #include <utility> @@ -298,7 +297,7 @@ private: // The current working directory, with links resolved. (readlink .). SmallString<128> Resolved; }; - Optional<WorkingDirectory> WD; + std::optional<WorkingDirectory> WD; }; } // namespace @@ -814,10 +813,10 @@ std::string InMemoryFileSystem::toString() const { bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime, std::unique_ptr<llvm::MemoryBuffer> Buffer, - Optional<uint32_t> User, - Optional<uint32_t> Group, - Optional<llvm::sys::fs::file_type> Type, - Optional<llvm::sys::fs::perms> Perms, + std::optional<uint32_t> User, + std::optional<uint32_t> Group, + std::optional<llvm::sys::fs::file_type> Type, + std::optional<llvm::sys::fs::perms> Perms, MakeNodeFn MakeNode) { SmallString<128> Path; P.toVector(Path); @@ -891,10 +890,10 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime, bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime, std::unique_ptr<llvm::MemoryBuffer> Buffer, - Optional<uint32_t> User, - Optional<uint32_t> Group, - Optional<llvm::sys::fs::file_type> Type, - Optional<llvm::sys::fs::perms> Perms) { + std::optional<uint32_t> User, + std::optional<uint32_t> Group, + std::optional<llvm::sys::fs::file_type> Type, + std::optional<llvm::sys::fs::perms> Perms) { return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type, Perms, [](detail::NewInMemoryNodeInfo NNI) @@ -907,12 +906,11 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime, }); } -bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime, - const llvm::MemoryBufferRef &Buffer, - Optional<uint32_t> User, - Optional<uint32_t> Group, - Optional<llvm::sys::fs::file_type> Type, - Optional<llvm::sys::fs::perms> Perms) { +bool InMemoryFileSystem::addFileNoOwn( + const Twine &P, time_t ModificationTime, + const llvm::MemoryBufferRef &Buffer, std::optional<uint32_t> User, + std::optional<uint32_t> Group, std::optional<llvm::sys::fs::file_type> Type, + std::optional<llvm::sys::fs::perms> Perms) { return addFile(P, ModificationTime, llvm::MemoryBuffer::getMemBuffer(Buffer), std::move(User), std::move(Group), std::move(Type), std::move(Perms), @@ -1012,20 +1010,18 @@ bool InMemoryFileSystem::addHardLink(const Twine &NewLink, // before. Resolved ToPath must be a File. if (!TargetNode || NewLinkNode || !isa<detail::InMemoryFile>(*TargetNode)) return false; - return addFile(NewLink, 0, nullptr, None, None, None, None, - [&](detail::NewInMemoryNodeInfo NNI) { + return addFile(NewLink, 0, nullptr, std::nullopt, std::nullopt, std::nullopt, + std::nullopt, [&](detail::NewInMemoryNodeInfo NNI) { return std::make_unique<detail::InMemoryHardLink>( NNI.Path.str(), *cast<detail::InMemoryFile>(*TargetNode)); }); } -bool InMemoryFileSystem::addSymbolicLink(const Twine &NewLink, - const Twine &Target, - time_t ModificationTime, - Optional<uint32_t> User, - Optional<uint32_t> Group, - Optional<llvm::sys::fs::perms> Perms) { +bool InMemoryFileSystem::addSymbolicLink( + const Twine &NewLink, const Twine &Target, time_t ModificationTime, + std::optional<uint32_t> User, std::optional<uint32_t> Group, + std::optional<llvm::sys::fs::perms> Perms) { auto NewLinkNode = lookupNode(NewLink, /*FollowFinalSymlink=*/false); if (NewLinkNode) return false; @@ -1246,7 +1242,7 @@ class llvm::vfs::RedirectingFSDirIterImpl sys::fs::file_type Type = sys::fs::file_type::type_unknown; switch ((*Current)->getKind()) { case RedirectingFileSystem::EK_Directory: - LLVM_FALLTHROUGH; + [[fallthrough]]; case RedirectingFileSystem::EK_DirectoryRemap: Type = sys::fs::file_type::directory_file; break; @@ -1350,32 +1346,51 @@ std::error_code RedirectingFileSystem::makeAbsolute(SmallVectorImpl<char> &Path) if (llvm::sys::path::is_absolute(Path, llvm::sys::path::Style::posix) || llvm::sys::path::is_absolute(Path, llvm::sys::path::Style::windows_backslash)) + // This covers windows absolute path with forward slash as well, as the + // forward slashes are treated as path seperation in llvm::path + // regardless of what path::Style is used. return {}; auto WorkingDir = getCurrentWorkingDirectory(); if (!WorkingDir) return WorkingDir.getError(); + return makeAbsolute(WorkingDir.get(), Path); +} + +std::error_code +RedirectingFileSystem::makeAbsolute(StringRef WorkingDir, + SmallVectorImpl<char> &Path) const { // We can't use sys::fs::make_absolute because that assumes the path style // is native and there is no way to override that. Since we know WorkingDir // is absolute, we can use it to determine which style we actually have and // append Path ourselves. + if (!WorkingDir.empty() && + !sys::path::is_absolute(WorkingDir, sys::path::Style::posix) && + !sys::path::is_absolute(WorkingDir, + sys::path::Style::windows_backslash)) { + return std::error_code(); + } sys::path::Style style = sys::path::Style::windows_backslash; - if (sys::path::is_absolute(WorkingDir.get(), sys::path::Style::posix)) { + if (sys::path::is_absolute(WorkingDir, sys::path::Style::posix)) { style = sys::path::Style::posix; } else { // Distinguish between windows_backslash and windows_slash; getExistingStyle // returns posix for a path with windows_slash. - if (getExistingStyle(WorkingDir.get()) != - sys::path::Style::windows_backslash) + if (getExistingStyle(WorkingDir) != sys::path::Style::windows_backslash) style = sys::path::Style::windows_slash; } - std::string Result = WorkingDir.get(); + std::string Result = std::string(WorkingDir); StringRef Dir(Result); if (!Dir.endswith(sys::path::get_separator(style))) { Result += sys::path::get_separator(style); } + // backslashes '\' are legit path charactors under POSIX. Windows APIs + // like CreateFile accepts forward slashes '/' as path + // separator (even when mixed with backslashes). Therefore, + // `Path` should be directly appended to `WorkingDir` without converting + // path separator. Result.append(Path.data(), Path.size()); Path.assign(Result.begin(), Result.end()); @@ -1482,12 +1497,12 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir, return Combined; } -void RedirectingFileSystem::setExternalContentsPrefixDir(StringRef PrefixDir) { - ExternalContentsPrefixDir = PrefixDir.str(); +void RedirectingFileSystem::setOverlayFileDir(StringRef Dir) { + OverlayFileDir = Dir.str(); } -StringRef RedirectingFileSystem::getExternalContentsPrefixDir() const { - return ExternalContentsPrefixDir; +StringRef RedirectingFileSystem::getOverlayFileDir() const { + return OverlayFileDir; } void RedirectingFileSystem::setFallthrough(bool Fallthrough) { @@ -1505,6 +1520,7 @@ void RedirectingFileSystem::setRedirection( std::vector<StringRef> RedirectingFileSystem::getRoots() const { std::vector<StringRef> R; + R.reserve(Roots.size()); for (const auto &Root : Roots) R.push_back(Root->getName()); return R; @@ -1604,12 +1620,12 @@ class llvm::vfs::RedirectingFileSystemParser { return false; } - Optional<RedirectingFileSystem::RedirectKind> + std::optional<RedirectingFileSystem::RedirectKind> parseRedirectKind(yaml::Node *N) { SmallString<12> Storage; StringRef Value; if (!parseScalarString(N, Value, Storage)) - return None; + return std::nullopt; if (Value.equals_insensitive("fallthrough")) { return RedirectingFileSystem::RedirectKind::Fallthrough; @@ -1618,7 +1634,21 @@ class llvm::vfs::RedirectingFileSystemParser { } else if (Value.equals_insensitive("redirect-only")) { return RedirectingFileSystem::RedirectKind::RedirectOnly; } - return None; + return std::nullopt; + } + + std::optional<RedirectingFileSystem::RootRelativeKind> + parseRootRelativeKind(yaml::Node *N) { + SmallString<12> Storage; + StringRef Value; + if (!parseScalarString(N, Value, Storage)) + return std::nullopt; + if (Value.equals_insensitive("cwd")) { + return RedirectingFileSystem::RootRelativeKind::CWD; + } else if (Value.equals_insensitive("overlay-dir")) { + return RedirectingFileSystem::RootRelativeKind::OverlayDir; + } + return std::nullopt; } struct KeyStatus { @@ -1828,7 +1858,7 @@ private: SmallString<256> FullPath; if (FS->IsRelativeOverlay) { - FullPath = FS->getExternalContentsPrefixDir(); + FullPath = FS->getOverlayFileDir(); assert(!FullPath.empty() && "External contents prefix directory must exist"); llvm::sys::path::append(FullPath, Value); @@ -1885,9 +1915,19 @@ private: sys::path::Style::windows_backslash)) { path_style = sys::path::Style::windows_backslash; } else { - // Relative VFS root entries are made absolute to the current working - // directory, then we can determine the path style from that. - auto EC = sys::fs::make_absolute(Name); + // Relative VFS root entries are made absolute to either the overlay + // directory, or the current working directory, then we can determine + // the path style from that. + std::error_code EC; + if (FS->RootRelative == + RedirectingFileSystem::RootRelativeKind::OverlayDir) { + StringRef FullPath = FS->getOverlayFileDir(); + assert(!FullPath.empty() && "Overlay file directory must exist"); + EC = FS->makeAbsolute(FullPath, Name); + Name = canonicalize(Name); + } else { + EC = sys::fs::make_absolute(Name); + } if (EC) { assert(NameValueNode && "Name presence should be checked earlier"); error( @@ -1899,6 +1939,12 @@ private: ? sys::path::Style::posix : sys::path::Style::windows_backslash; } + // is::path::is_absolute(Name, sys::path::Style::windows_backslash) will + // return true even if `Name` is using forward slashes. Distinguish + // between windows_backslash and windows_slash. + if (path_style == sys::path::Style::windows_backslash && + getExistingStyle(Name) != sys::path::Style::windows_backslash) + path_style = sys::path::Style::windows_slash; } // Remove trailing slash(es), being careful not to remove the root path @@ -1962,6 +2008,7 @@ public: KeyStatusPair("version", true), KeyStatusPair("case-sensitive", false), KeyStatusPair("use-external-names", false), + KeyStatusPair("root-relative", false), KeyStatusPair("overlay-relative", false), KeyStatusPair("fallthrough", false), KeyStatusPair("redirecting-with", false), @@ -2051,6 +2098,13 @@ public: error(I.getValue(), "expected valid redirect kind"); return false; } + } else if (Key == "root-relative") { + if (auto Kind = parseRootRelativeKind(I.getValue())) { + FS->RootRelative = *Kind; + } else { + error(I.getValue(), "expected valid root-relative kind"); + return false; + } } else { llvm_unreachable("key missing from Keys"); } @@ -2100,13 +2154,13 @@ RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer, // Example: // -ivfsoverlay dummy.cache/vfs/vfs.yaml // yields: - // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs + // FS->OverlayFileDir => /<absolute_path_to>/dummy.cache/vfs // SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath); std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir); assert(!EC && "Overlay dir final path must be absolute"); (void)EC; - FS->setExternalContentsPrefixDir(OverlayAbsDir); + FS->setOverlayFileDir(OverlayAbsDir); } if (!P.parse(Root, FS.get())) @@ -2271,7 +2325,7 @@ static Status getRedirectedFileStatus(const Twine &OriginalPath, ErrorOr<Status> RedirectingFileSystem::status( const Twine &CanonicalPath, const Twine &OriginalPath, const RedirectingFileSystem::LookupResult &Result) { - if (Optional<StringRef> ExtRedirect = Result.getExternalRedirect()) { + if (std::optional<StringRef> ExtRedirect = Result.getExternalRedirect()) { SmallString<256> CanonicalRemappedPath((*ExtRedirect).str()); if (std::error_code EC = makeCanonical(CanonicalRemappedPath)) return EC; @@ -2602,9 +2656,10 @@ class JSONWriter { public: JSONWriter(llvm::raw_ostream &OS) : OS(OS) {} - void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames, - Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative, - StringRef OverlayDir); + void write(ArrayRef<YAMLVFSEntry> Entries, + std::optional<bool> UseExternalNames, + std::optional<bool> IsCaseSensitive, + std::optional<bool> IsOverlayRelative, StringRef OverlayDir); }; } // namespace @@ -2659,23 +2714,23 @@ void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) { } void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, - Optional<bool> UseExternalNames, - Optional<bool> IsCaseSensitive, - Optional<bool> IsOverlayRelative, + std::optional<bool> UseExternalNames, + std::optional<bool> IsCaseSensitive, + std::optional<bool> IsOverlayRelative, StringRef OverlayDir) { using namespace llvm::sys; OS << "{\n" " 'version': 0,\n"; if (IsCaseSensitive) - OS << " 'case-sensitive': '" - << (IsCaseSensitive.value() ? "true" : "false") << "',\n"; + OS << " 'case-sensitive': '" << (*IsCaseSensitive ? "true" : "false") + << "',\n"; if (UseExternalNames) - OS << " 'use-external-names': '" - << (UseExternalNames.value() ? "true" : "false") << "',\n"; + OS << " 'use-external-names': '" << (*UseExternalNames ? "true" : "false") + << "',\n"; bool UseOverlayRelative = false; if (IsOverlayRelative) { - UseOverlayRelative = IsOverlayRelative.value(); + UseOverlayRelative = *IsOverlayRelative; OS << " 'overlay-relative': '" << (UseOverlayRelative ? "true" : "false") << "',\n"; } |