diff options
Diffstat (limited to 'llvm/lib/Support/VirtualFileSystem.cpp')
-rw-r--r-- | llvm/lib/Support/VirtualFileSystem.cpp | 103 |
1 files changed, 30 insertions, 73 deletions
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index f400a7c..360f8d0 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -228,28 +228,9 @@ std::error_code RealFile::close() { namespace { -/// A file system according to your operating system. -/// This may be linked to the process's working directory, or maintain its own. -/// -/// Currently, its own working directory is emulated by storing the path and -/// sending absolute paths to llvm::sys::fs:: functions. -/// A more principled approach would be to push this down a level, modelling -/// the working dir as an llvm::sys::fs::WorkingDir or similar. -/// This would enable the use of openat()-style functions on some platforms. +/// The file system according to your operating system. class RealFileSystem : public FileSystem { public: - explicit RealFileSystem(bool LinkCWDToProcess) { - if (!LinkCWDToProcess) { - SmallString<128> PWD, RealPWD; - if (llvm::sys::fs::current_path(PWD)) - return; // Awful, but nothing to do here. - if (llvm::sys::fs::real_path(PWD, RealPWD)) - WD = {PWD, PWD}; - else - WD = {PWD, RealPWD}; - } - } - ErrorOr<Status> status(const Twine &Path) override; ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -261,32 +242,15 @@ public: SmallVectorImpl<char> &Output) const override; private: - // If this FS has its own working dir, use it to make Path absolute. - // The returned twine is safe to use as long as both Storage and Path live. - Twine adjustPath(const Twine &Path, SmallVectorImpl<char> &Storage) const { - if (!WD) - return Path; - Path.toVector(Storage); - sys::fs::make_absolute(WD->Resolved, Storage); - return Storage; - } - - struct WorkingDirectory { - // The current working directory, without symlinks resolved. (echo $PWD). - SmallString<128> Specified; - // The current working directory, with links resolved. (readlink .). - SmallString<128> Resolved; - }; - Optional<WorkingDirectory> WD; + mutable std::mutex CWDMutex; + mutable std::string CWDCache; }; } // namespace ErrorOr<Status> RealFileSystem::status(const Twine &Path) { - SmallString<256> Storage; sys::fs::file_status RealStatus; - if (std::error_code EC = - sys::fs::status(adjustPath(Path, Storage), RealStatus)) + if (std::error_code EC = sys::fs::status(Path, RealStatus)) return EC; return Status::copyWithNewName(RealStatus, Path.str()); } @@ -294,61 +258,56 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) { ErrorOr<std::unique_ptr<File>> RealFileSystem::openFileForRead(const Twine &Name) { int FD; - SmallString<256> RealName, Storage; - if (std::error_code EC = sys::fs::openFileForRead( - adjustPath(Name, Storage), FD, sys::fs::OF_None, &RealName)) + SmallString<256> RealName; + if (std::error_code EC = + sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName)) return EC; return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str())); } llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const { - if (WD) - return WD->Specified.str(); - - SmallString<128> Dir; + std::lock_guard<std::mutex> Lock(CWDMutex); + if (!CWDCache.empty()) + return CWDCache; + SmallString<256> Dir; if (std::error_code EC = llvm::sys::fs::current_path(Dir)) return EC; - return Dir.str(); + CWDCache = Dir.str(); + return CWDCache; } std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) { - if (!WD) - return llvm::sys::fs::set_current_path(Path); - - SmallString<128> Absolute, Resolved, Storage; - adjustPath(Path, Storage).toVector(Absolute); - bool IsDir; - if (auto Err = llvm::sys::fs::is_directory(Absolute, IsDir)) - return Err; - if (!IsDir) - return std::make_error_code(std::errc::not_a_directory); - if (auto Err = llvm::sys::fs::real_path(Absolute, Resolved)) - return Err; - WD = {Absolute, Resolved}; + // FIXME: chdir is thread hostile; on the other hand, creating the same + // behavior as chdir is complex: chdir resolves the path once, thus + // guaranteeing that all subsequent relative path operations work + // on the same path the original chdir resulted in. This makes a + // difference for example on network filesystems, where symlinks might be + // switched during runtime of the tool. Fixing this depends on having a + // file system abstraction that allows openat() style interactions. + if (auto EC = llvm::sys::fs::set_current_path(Path)) + return EC; + + // Invalidate cache. + std::lock_guard<std::mutex> Lock(CWDMutex); + CWDCache.clear(); return std::error_code(); } std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) { - SmallString<256> Storage; - return llvm::sys::fs::is_local(adjustPath(Path, Storage), Result); + return llvm::sys::fs::is_local(Path, Result); } std::error_code RealFileSystem::getRealPath(const Twine &Path, SmallVectorImpl<char> &Output) const { - SmallString<256> Storage; - return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output); + return llvm::sys::fs::real_path(Path, Output); } IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() { - static IntrusiveRefCntPtr<FileSystem> FS(new RealFileSystem(true)); + static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem(); return FS; } -std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() { - return llvm::make_unique<RealFileSystem>(false); -} - namespace { class RealFSDirIter : public llvm::vfs::detail::DirIterImpl { @@ -374,9 +333,7 @@ public: directory_iterator RealFileSystem::dir_begin(const Twine &Dir, std::error_code &EC) { - SmallString<128> Storage; - return directory_iterator( - std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC)); + return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC)); } //===-----------------------------------------------------------------------===/ |