aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/VirtualFileSystem.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Support/VirtualFileSystem.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'llvm/lib/Support/VirtualFileSystem.cpp')
-rw-r--r--llvm/lib/Support/VirtualFileSystem.cpp165
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";
}