Skip to content

[stable/20230725][llvm][vfs] Preserve paths for fallback/fallthrough in RedirectingFileSystem #8411

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions llvm/include/llvm/Support/VirtualFileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1001,12 +1001,12 @@ class RedirectingFileSystem
/// Canonicalize path by removing ".", "..", "./", components. This is
/// a VFS request, do not bother about symlinks in the path components
/// but canonicalize in order to perform the correct entry search.
std::error_code makeCanonical(SmallVectorImpl<char> &Path) const;
std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const;

/// Get the File status, or error, from the underlying external file system.
/// This returns the status with the originally requested name, while looking
/// up the entry using the canonical path.
ErrorOr<Status> getExternalStatus(const Twine &CanonicalPath,
/// up the entry using a potentially different path.
ErrorOr<Status> getExternalStatus(const Twine &LookupPath,
const Twine &OriginalPath) const;

/// Make \a Path an absolute path.
Expand Down Expand Up @@ -1094,7 +1094,7 @@ class RedirectingFileSystem
llvm::SmallVectorImpl<Entry *> &Entries) const;

/// Get the status for a path with the provided \c LookupResult.
ErrorOr<Status> status(const Twine &CanonicalPath, const Twine &OriginalPath,
ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath,
const LookupResult &Result);

public:
Expand Down
109 changes: 53 additions & 56 deletions llvm/lib/Support/VirtualFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,7 @@ std::error_code RedirectingFileSystem::isLocal(const Twine &Path_,
SmallString<256> Path;
Path_.toVector(Path);

if (std::error_code EC = makeCanonical(Path))
if (makeAbsolute(Path))
return {};

return ExternalFS->isLocal(Path, Result);
Expand Down Expand Up @@ -1440,7 +1440,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
SmallString<256> Path;
Dir.toVector(Path);

EC = makeCanonical(Path);
EC = makeAbsolute(Path);
if (EC)
return {};

Expand Down Expand Up @@ -2290,8 +2290,8 @@ void RedirectingFileSystem::LookupResult::getPath(
llvm::sys::path::append(Result, E->getName());
}

std::error_code
RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const {
std::error_code RedirectingFileSystem::makeCanonicalForLookup(
SmallVectorImpl<char> &Path) const {
if (std::error_code EC = makeAbsolute(Path))
return EC;

Expand All @@ -2306,12 +2306,16 @@ RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const {

ErrorOr<RedirectingFileSystem::LookupResult>
RedirectingFileSystem::lookupPath(StringRef Path) const {
llvm::SmallString<128> CanonicalPath(Path);
if (std::error_code EC = makeCanonicalForLookup(CanonicalPath))
return EC;

// RedirectOnly means the VFS is always used.
if (UsageTrackingActive && Redirection == RedirectKind::RedirectOnly)
HasBeenUsed = true;

sys::path::const_iterator Start = sys::path::begin(Path);
sys::path::const_iterator End = sys::path::end(Path);
sys::path::const_iterator Start = sys::path::begin(CanonicalPath);
sys::path::const_iterator End = sys::path::end(CanonicalPath);
llvm::SmallVector<Entry *, 32> Entries;
for (const auto &Root : Roots) {
ErrorOr<RedirectingFileSystem::LookupResult> Result =
Expand Down Expand Up @@ -2388,14 +2392,14 @@ static Status getRedirectedFileStatus(const Twine &OriginalPath,
}

ErrorOr<Status> RedirectingFileSystem::status(
const Twine &CanonicalPath, const Twine &OriginalPath,
const Twine &LookupPath, const Twine &OriginalPath,
const RedirectingFileSystem::LookupResult &Result) {
if (std::optional<StringRef> ExtRedirect = Result.getExternalRedirect()) {
SmallString<256> CanonicalRemappedPath((*ExtRedirect).str());
if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
SmallString<256> RemappedPath((*ExtRedirect).str());
if (std::error_code EC = makeAbsolute(RemappedPath))
return EC;

ErrorOr<Status> S = ExternalFS->status(CanonicalRemappedPath);
ErrorOr<Status> S = ExternalFS->status(RemappedPath);
if (!S)
return S;
S = Status::copyWithNewName(*S, *ExtRedirect);
Expand All @@ -2405,13 +2409,13 @@ ErrorOr<Status> RedirectingFileSystem::status(
}

auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(Result.E);
return Status::copyWithNewName(DE->getStatus(), CanonicalPath);
return Status::copyWithNewName(DE->getStatus(), LookupPath);
}

ErrorOr<Status>
RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath,
RedirectingFileSystem::getExternalStatus(const Twine &LookupPath,
const Twine &OriginalPath) const {
auto Result = ExternalFS->status(CanonicalPath);
auto Result = ExternalFS->status(LookupPath);

// The path has been mapped by some nested VFS, don't override it with the
// original path.
Expand All @@ -2421,65 +2425,63 @@ RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath,
}

ErrorOr<Status> RedirectingFileSystem::status(const Twine &OriginalPath) {
SmallString<256> CanonicalPath;
OriginalPath.toVector(CanonicalPath);
SmallString<256> Path;
OriginalPath.toVector(Path);

if (std::error_code EC = makeCanonical(CanonicalPath))
if (std::error_code EC = makeAbsolute(Path))
return EC;

if (Redirection == RedirectKind::Fallback) {
// Attempt to find the original file first, only falling back to the
// mapped file if that fails.
ErrorOr<Status> S = getExternalStatus(CanonicalPath, OriginalPath);
ErrorOr<Status> S = getExternalStatus(Path, OriginalPath);
if (S)
return S;
}

ErrorOr<RedirectingFileSystem::LookupResult> Result =
lookupPath(CanonicalPath);
ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path);
if (!Result) {
// Was not able to map file, fallthrough to using the original path if
// that was the specified redirection type.
if (Redirection == RedirectKind::Fallthrough &&
isFileNotFound(Result.getError()))
return getExternalStatus(CanonicalPath, OriginalPath);
return getExternalStatus(Path, OriginalPath);
return Result.getError();
}

ErrorOr<Status> S = status(CanonicalPath, OriginalPath, *Result);
ErrorOr<Status> S = status(Path, OriginalPath, *Result);
if (!S && Redirection == RedirectKind::Fallthrough &&
isFileNotFound(S.getError(), Result->E)) {
// Mapped the file but it wasn't found in the underlying filesystem,
// fallthrough to using the original path if that was the specified
// redirection type.
return getExternalStatus(CanonicalPath, OriginalPath);
return getExternalStatus(Path, OriginalPath);
}

return S;
}

bool RedirectingFileSystem::exists(const Twine &OriginalPath) {
SmallString<256> CanonicalPath;
OriginalPath.toVector(CanonicalPath);
SmallString<256> Path;
OriginalPath.toVector(Path);

if (makeCanonical(CanonicalPath))
if (makeAbsolute(Path))
return false;

if (Redirection == RedirectKind::Fallback) {
// Attempt to find the original file first, only falling back to the
// mapped file if that fails.
if (ExternalFS->exists(CanonicalPath))
if (ExternalFS->exists(Path))
return true;
}

ErrorOr<RedirectingFileSystem::LookupResult> Result =
lookupPath(CanonicalPath);
ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path);
if (!Result) {
// Was not able to map file, fallthrough to using the original path if
// that was the specified redirection type.
if (Redirection == RedirectKind::Fallthrough &&
isFileNotFound(Result.getError()))
return ExternalFS->exists(CanonicalPath);
return ExternalFS->exists(Path);
return false;
}

Expand All @@ -2489,18 +2491,18 @@ bool RedirectingFileSystem::exists(const Twine &OriginalPath) {
return true;
}

SmallString<256> CanonicalRemappedPath((*ExtRedirect).str());
if (makeCanonical(CanonicalRemappedPath))
SmallString<256> RemappedPath((*ExtRedirect).str());
if (makeAbsolute(RemappedPath))
return false;

if (ExternalFS->exists(CanonicalRemappedPath))
if (ExternalFS->exists(RemappedPath))
return true;

if (Redirection == RedirectKind::Fallthrough) {
// Mapped the file but it wasn't found in the underlying filesystem,
// fallthrough to using the original path if that was the specified
// redirection type.
return ExternalFS->exists(CanonicalPath);
return ExternalFS->exists(Path);
}

return false;
Expand Down Expand Up @@ -2549,53 +2551,49 @@ File::getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P) {

ErrorOr<std::unique_ptr<File>>
RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) {
SmallString<256> CanonicalPath;
OriginalPath.toVector(CanonicalPath);
SmallString<256> Path;
OriginalPath.toVector(Path);

if (std::error_code EC = makeCanonical(CanonicalPath))
if (std::error_code EC = makeAbsolute(Path))
return EC;

if (Redirection == RedirectKind::Fallback) {
// Attempt to find the original file first, only falling back to the
// mapped file if that fails.
auto F = File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
OriginalPath);
auto F = File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
if (F)
return F;
}

ErrorOr<RedirectingFileSystem::LookupResult> Result =
lookupPath(CanonicalPath);
ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path);
if (!Result) {
// Was not able to map file, fallthrough to using the original path if
// that was the specified redirection type.
if (Redirection == RedirectKind::Fallthrough &&
isFileNotFound(Result.getError()))
return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
OriginalPath);
return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
return Result.getError();
}

if (!Result->getExternalRedirect()) // FIXME: errc::not_a_file?
return make_error_code(llvm::errc::invalid_argument);

StringRef ExtRedirect = *Result->getExternalRedirect();
SmallString<256> CanonicalRemappedPath(ExtRedirect.str());
if (std::error_code EC = makeCanonical(CanonicalRemappedPath))
SmallString<256> RemappedPath(ExtRedirect.str());
if (std::error_code EC = makeAbsolute(RemappedPath))
return EC;

auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);

auto ExternalFile = File::getWithPath(
ExternalFS->openFileForRead(CanonicalRemappedPath), ExtRedirect);
auto ExternalFile =
File::getWithPath(ExternalFS->openFileForRead(RemappedPath), ExtRedirect);
if (!ExternalFile) {
if (Redirection == RedirectKind::Fallthrough &&
isFileNotFound(ExternalFile.getError(), Result->E)) {
// Mapped the file but it wasn't found in the underlying filesystem,
// fallthrough to using the original path if that was the specified
// redirection type.
return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath),
OriginalPath);
return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
}
return ExternalFile;
}
Expand All @@ -2615,28 +2613,27 @@ RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) {
std::error_code
RedirectingFileSystem::getRealPath(const Twine &OriginalPath,
SmallVectorImpl<char> &Output) const {
SmallString<256> CanonicalPath;
OriginalPath.toVector(CanonicalPath);
SmallString<256> Path;
OriginalPath.toVector(Path);

if (std::error_code EC = makeCanonical(CanonicalPath))
if (std::error_code EC = makeAbsolute(Path))
return EC;

if (Redirection == RedirectKind::Fallback) {
// Attempt to find the original file first, only falling back to the
// mapped file if that fails.
std::error_code EC = ExternalFS->getRealPath(CanonicalPath, Output);
std::error_code EC = ExternalFS->getRealPath(Path, Output);
if (!EC)
return EC;
}

ErrorOr<RedirectingFileSystem::LookupResult> Result =
lookupPath(CanonicalPath);
ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path);
if (!Result) {
// Was not able to map file, fallthrough to using the original path if
// that was the specified redirection type.
if (Redirection == RedirectKind::Fallthrough &&
isFileNotFound(Result.getError()))
return ExternalFS->getRealPath(CanonicalPath, Output);
return ExternalFS->getRealPath(Path, Output);
return Result.getError();
}

Expand All @@ -2649,7 +2646,7 @@ RedirectingFileSystem::getRealPath(const Twine &OriginalPath,
// Mapped the file but it wasn't found in the underlying filesystem,
// fallthrough to using the original path if that was the specified
// redirection type.
return ExternalFS->getRealPath(CanonicalPath, Output);
return ExternalFS->getRealPath(Path, Output);
}
return P;
}
Expand Down
Loading