Skip to content

Commit 3f65c73

Browse files
committed
[llvm][vfs] Avoid silent fallback to process-wide working directory
In createPhysicalFileSystem, preserve the per-instance working directory, even after the first call to getcwd fails. rdar://108213753 Differential Revision: https://reviews.llvm.org/D149173 (cherry picked from commit 5437a4c)
1 parent 7a378d8 commit 3f65c73

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

llvm/lib/Support/VirtualFileSystem.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,12 @@ class RealFileSystem : public FileSystem {
278278
explicit RealFileSystem(bool LinkCWDToProcess) {
279279
if (!LinkCWDToProcess) {
280280
SmallString<128> PWD, RealPWD;
281-
if (llvm::sys::fs::current_path(PWD))
282-
return; // Awful, but nothing to do here.
283-
if (llvm::sys::fs::real_path(PWD, RealPWD))
284-
WD = {PWD, PWD};
281+
if (std::error_code EC = llvm::sys::fs::current_path(PWD))
282+
WD = EC;
283+
else if (llvm::sys::fs::real_path(PWD, RealPWD))
284+
WD = WorkingDirectory{PWD, PWD};
285285
else
286-
WD = {PWD, RealPWD};
286+
WD = WorkingDirectory{PWD, RealPWD};
287287
}
288288
}
289289

@@ -305,10 +305,10 @@ class RealFileSystem : public FileSystem {
305305
// If this FS has its own working dir, use it to make Path absolute.
306306
// The returned twine is safe to use as long as both Storage and Path live.
307307
Twine adjustPath(const Twine &Path, SmallVectorImpl<char> &Storage) const {
308-
if (!WD)
308+
if (!WD || !*WD)
309309
return Path;
310310
Path.toVector(Storage);
311-
sys::fs::make_absolute(WD->Resolved, Storage);
311+
sys::fs::make_absolute(WD->get().Resolved, Storage);
312312
return Storage;
313313
}
314314

@@ -318,7 +318,7 @@ class RealFileSystem : public FileSystem {
318318
// The current working directory, with links resolved. (readlink .).
319319
SmallString<128> Resolved;
320320
};
321-
Optional<WorkingDirectory> WD;
321+
Optional<llvm::ErrorOr<WorkingDirectory>> WD;
322322
};
323323

324324
} // namespace
@@ -344,8 +344,10 @@ RealFileSystem::openFileForRead(const Twine &Name) {
344344
}
345345

346346
llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
347+
if (WD && *WD)
348+
return std::string(WD->get().Specified.str());
347349
if (WD)
348-
return std::string(WD->Specified.str());
350+
return WD->getError();
349351

350352
SmallString<128> Dir;
351353
if (std::error_code EC = llvm::sys::fs::current_path(Dir))
@@ -366,7 +368,7 @@ std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
366368
return std::make_error_code(std::errc::not_a_directory);
367369
if (auto Err = llvm::sys::fs::real_path(Absolute, Resolved))
368370
return Err;
369-
WD = {Absolute, Resolved};
371+
WD = WorkingDirectory{Absolute, Resolved};
370372
return std::error_code();
371373
}
372374

llvm/unittests/Support/VirtualFileSystemTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "llvm/Support/VirtualFileSystem.h"
1010
#include "llvm/ADT/Triple.h"
11+
#include "llvm/ADT/ScopeExit.h"
1112
#include "llvm/Config/llvm-config.h"
1213
#include "llvm/Support/Errc.h"
1314
#include "llvm/Support/Host.h"
@@ -541,6 +542,31 @@ TEST(VirtualFileSystemTest, MultipleWorkingDirs) {
541542
ASSERT_EQ(CIt, vfs::directory_iterator());
542543
}
543544

545+
TEST(VirtualFileSystemTest, PhysicalFileSystemWorkingDirFailure) {
546+
TempDir D2("d2", /*Unique*/ true);
547+
SmallString<128> WD, PrevWD;
548+
ASSERT_EQ(sys::fs::current_path(PrevWD), std::error_code());
549+
ASSERT_EQ(sys::fs::createUniqueDirectory("d1", WD), std::error_code());
550+
ASSERT_EQ(sys::fs::set_current_path(WD), std::error_code());
551+
auto Restore =
552+
llvm::make_scope_exit([&] { sys::fs::set_current_path(PrevWD); });
553+
554+
// Delete the working directory to create an error.
555+
ASSERT_EQ(sys::fs::remove_directories(WD), std::error_code());
556+
557+
// Verify that we still get two separate working directories.
558+
auto FS1 = vfs::createPhysicalFileSystem();
559+
auto FS2 = vfs::createPhysicalFileSystem();
560+
ASSERT_EQ(FS1->getCurrentWorkingDirectory().getError(),
561+
errc::no_such_file_or_directory);
562+
ASSERT_EQ(FS1->setCurrentWorkingDirectory(D2.path()), std::error_code());
563+
ASSERT_EQ(FS1->getCurrentWorkingDirectory().get(), D2.path());
564+
EXPECT_EQ(FS2->getCurrentWorkingDirectory().getError(),
565+
errc::no_such_file_or_directory);
566+
SmallString<128> WD2;
567+
EXPECT_EQ(sys::fs::current_path(WD2), errc::no_such_file_or_directory);
568+
}
569+
544570
TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) {
545571
TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
546572
IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();

0 commit comments

Comments
 (0)