17a9e7621SOleksiy Vyalov //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===// 27a9e7621SOleksiy Vyalov // 37a9e7621SOleksiy Vyalov // The LLVM Compiler Infrastructure 47a9e7621SOleksiy Vyalov // 57a9e7621SOleksiy Vyalov // This file is distributed under the University of Illinois Open Source 67a9e7621SOleksiy Vyalov // License. See LICENSE.TXT for details. 77a9e7621SOleksiy Vyalov // 87a9e7621SOleksiy Vyalov //===----------------------------------------------------------------------===// 97a9e7621SOleksiy Vyalov 107a9e7621SOleksiy Vyalov #include "lldb/Host/FileSystem.h" 117a9e7621SOleksiy Vyalov 120bca15a3SJonas Devlieghere #include "lldb/Utility/LLDBAssert.h" 1346376966SJonas Devlieghere #include "lldb/Utility/TildeExpressionResolver.h" 1446376966SJonas Devlieghere 151408bf72SPavel Labath #include "llvm/Support/FileSystem.h" 162c22c800SJonas Devlieghere #include "llvm/Support/Path.h" 172c22c800SJonas Devlieghere #include "llvm/Support/Program.h" 1846376966SJonas Devlieghere #include "llvm/Support/Threading.h" 197a9e7621SOleksiy Vyalov 206801be33SOleksiy Vyalov #include <algorithm> 217a9e7621SOleksiy Vyalov #include <fstream> 227a9e7621SOleksiy Vyalov #include <vector> 237a9e7621SOleksiy Vyalov 247a9e7621SOleksiy Vyalov using namespace lldb; 257a9e7621SOleksiy Vyalov using namespace lldb_private; 2646376966SJonas Devlieghere using namespace llvm; 277a9e7621SOleksiy Vyalov 2846376966SJonas Devlieghere FileSystem &FileSystem::Instance() { return *InstanceImpl(); } 2946376966SJonas Devlieghere 3046376966SJonas Devlieghere void FileSystem::Initialize() { 310bca15a3SJonas Devlieghere lldbassert(!InstanceImpl() && "Already initialized."); 3246376966SJonas Devlieghere InstanceImpl().emplace(); 3346376966SJonas Devlieghere } 3446376966SJonas Devlieghere 3546376966SJonas Devlieghere void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) { 360bca15a3SJonas Devlieghere lldbassert(!InstanceImpl() && "Already initialized."); 3746376966SJonas Devlieghere InstanceImpl().emplace(fs); 3846376966SJonas Devlieghere } 3946376966SJonas Devlieghere 4046376966SJonas Devlieghere void FileSystem::Terminate() { 410bca15a3SJonas Devlieghere lldbassert(InstanceImpl() && "Already terminated."); 4246376966SJonas Devlieghere InstanceImpl().reset(); 4346376966SJonas Devlieghere } 4446376966SJonas Devlieghere 4546376966SJonas Devlieghere Optional<FileSystem> &FileSystem::InstanceImpl() { 4646376966SJonas Devlieghere static Optional<FileSystem> g_fs; 4746376966SJonas Devlieghere return g_fs; 4846376966SJonas Devlieghere } 4946376966SJonas Devlieghere 5046376966SJonas Devlieghere void FileSystem::SetFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> fs) { 5146376966SJonas Devlieghere m_fs = fs; 5246376966SJonas Devlieghere } 5346376966SJonas Devlieghere 5446376966SJonas Devlieghere sys::TimePoint<> 5546376966SJonas Devlieghere FileSystem::GetModificationTime(const FileSpec &file_spec) const { 5646376966SJonas Devlieghere return GetModificationTime(file_spec.GetPath()); 5746376966SJonas Devlieghere } 5846376966SJonas Devlieghere 5946376966SJonas Devlieghere sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const { 6046376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 6146376966SJonas Devlieghere if (!status) 6246376966SJonas Devlieghere return sys::TimePoint<>(); 6346376966SJonas Devlieghere return status->getLastModificationTime(); 6446376966SJonas Devlieghere } 6546376966SJonas Devlieghere 6646376966SJonas Devlieghere uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const { 6746376966SJonas Devlieghere return GetByteSize(file_spec.GetPath()); 6846376966SJonas Devlieghere } 6946376966SJonas Devlieghere 7046376966SJonas Devlieghere uint64_t FileSystem::GetByteSize(const Twine &path) const { 7146376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 7246376966SJonas Devlieghere if (!status) 7346376966SJonas Devlieghere return 0; 7446376966SJonas Devlieghere return status->getSize(); 7546376966SJonas Devlieghere } 7646376966SJonas Devlieghere 7746376966SJonas Devlieghere uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const { 7846376966SJonas Devlieghere return GetPermissions(file_spec.GetPath()); 7946376966SJonas Devlieghere } 8046376966SJonas Devlieghere 8146376966SJonas Devlieghere uint32_t FileSystem::GetPermissions(const Twine &path) const { 8246376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 8346376966SJonas Devlieghere if (!status) 8446376966SJonas Devlieghere return sys::fs::perms::perms_not_known; 8546376966SJonas Devlieghere return status->getPermissions(); 8646376966SJonas Devlieghere } 8746376966SJonas Devlieghere 8846376966SJonas Devlieghere bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); } 8946376966SJonas Devlieghere 9046376966SJonas Devlieghere bool FileSystem::Exists(const FileSpec &file_spec) const { 9146376966SJonas Devlieghere return Exists(file_spec.GetPath()); 9246376966SJonas Devlieghere } 9346376966SJonas Devlieghere 9446376966SJonas Devlieghere bool FileSystem::Readable(const Twine &path) const { 9546376966SJonas Devlieghere return GetPermissions(path) & sys::fs::perms::all_read; 9646376966SJonas Devlieghere } 9746376966SJonas Devlieghere 9846376966SJonas Devlieghere bool FileSystem::Readable(const FileSpec &file_spec) const { 9946376966SJonas Devlieghere return Readable(file_spec.GetPath()); 10046376966SJonas Devlieghere } 10146376966SJonas Devlieghere 1029ca491daSJonas Devlieghere void FileSystem::EnumerateDirectory(Twine path, bool find_directories, 1039ca491daSJonas Devlieghere bool find_files, bool find_other, 1049ca491daSJonas Devlieghere EnumerateDirectoryCallbackType callback, 1059ca491daSJonas Devlieghere void *callback_baton) { 1069ca491daSJonas Devlieghere std::error_code EC; 1079ca491daSJonas Devlieghere vfs::recursive_directory_iterator Iter(*m_fs, path, EC); 1089ca491daSJonas Devlieghere vfs::recursive_directory_iterator End; 1099ca491daSJonas Devlieghere for (; Iter != End && !EC; Iter.increment(EC)) { 1109ca491daSJonas Devlieghere const auto &Item = *Iter; 1119ca491daSJonas Devlieghere ErrorOr<vfs::Status> Status = m_fs->status(Item.path()); 1129ca491daSJonas Devlieghere if (!Status) 1139ca491daSJonas Devlieghere break; 1149ca491daSJonas Devlieghere if (!find_files && Status->isRegularFile()) 1159ca491daSJonas Devlieghere continue; 1169ca491daSJonas Devlieghere if (!find_directories && Status->isDirectory()) 1179ca491daSJonas Devlieghere continue; 1189ca491daSJonas Devlieghere if (!find_other && Status->isOther()) 1199ca491daSJonas Devlieghere continue; 1209ca491daSJonas Devlieghere 1219ca491daSJonas Devlieghere auto Result = callback(callback_baton, Status->getType(), Item.path()); 1229ca491daSJonas Devlieghere if (Result == eEnumerateDirectoryResultQuit) 1239ca491daSJonas Devlieghere return; 1249ca491daSJonas Devlieghere if (Result == eEnumerateDirectoryResultNext) { 1259ca491daSJonas Devlieghere // Default behavior is to recurse. Opt out if the callback doesn't want 1269ca491daSJonas Devlieghere // this behavior. 1279ca491daSJonas Devlieghere Iter.no_push(); 1289ca491daSJonas Devlieghere } 1299ca491daSJonas Devlieghere } 1309ca491daSJonas Devlieghere } 1319ca491daSJonas Devlieghere 13246376966SJonas Devlieghere std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const { 13346376966SJonas Devlieghere return m_fs->makeAbsolute(path); 13446376966SJonas Devlieghere } 13546376966SJonas Devlieghere 13646376966SJonas Devlieghere std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const { 13746376966SJonas Devlieghere SmallString<128> path; 13846376966SJonas Devlieghere file_spec.GetPath(path, false); 13946376966SJonas Devlieghere 14046376966SJonas Devlieghere auto EC = MakeAbsolute(path); 14146376966SJonas Devlieghere if (EC) 14246376966SJonas Devlieghere return EC; 14346376966SJonas Devlieghere 144*8f3be7a3SJonas Devlieghere FileSpec new_file_spec(path, file_spec.GetPathStyle()); 14546376966SJonas Devlieghere file_spec = new_file_spec; 14646376966SJonas Devlieghere return {}; 14746376966SJonas Devlieghere } 14846376966SJonas Devlieghere 14946376966SJonas Devlieghere std::error_code FileSystem::GetRealPath(const Twine &path, 15046376966SJonas Devlieghere SmallVectorImpl<char> &output) const { 15146376966SJonas Devlieghere return m_fs->getRealPath(path, output); 15246376966SJonas Devlieghere } 15346376966SJonas Devlieghere 15446376966SJonas Devlieghere void FileSystem::Resolve(SmallVectorImpl<char> &path) { 15546376966SJonas Devlieghere if (path.empty()) 15646376966SJonas Devlieghere return; 15746376966SJonas Devlieghere 15846376966SJonas Devlieghere // Resolve tilde. 15946376966SJonas Devlieghere SmallString<128> original_path(path.begin(), path.end()); 16046376966SJonas Devlieghere StandardTildeExpressionResolver Resolver; 16146376966SJonas Devlieghere Resolver.ResolveFullPath(original_path, path); 16246376966SJonas Devlieghere 16346376966SJonas Devlieghere // Try making the path absolute if it exists. 16446376966SJonas Devlieghere SmallString<128> absolute_path(path.begin(), path.end()); 16546376966SJonas Devlieghere MakeAbsolute(path); 16646376966SJonas Devlieghere if (!Exists(path)) { 16746376966SJonas Devlieghere path.clear(); 16846376966SJonas Devlieghere path.append(original_path.begin(), original_path.end()); 16946376966SJonas Devlieghere } 17046376966SJonas Devlieghere } 17146376966SJonas Devlieghere 17246376966SJonas Devlieghere void FileSystem::Resolve(FileSpec &file_spec) { 17346376966SJonas Devlieghere // Extract path from the FileSpec. 17446376966SJonas Devlieghere SmallString<128> path; 17546376966SJonas Devlieghere file_spec.GetPath(path); 17646376966SJonas Devlieghere 17746376966SJonas Devlieghere // Resolve the path. 17846376966SJonas Devlieghere Resolve(path); 17946376966SJonas Devlieghere 18046376966SJonas Devlieghere // Update the FileSpec with the resolved path. 18146376966SJonas Devlieghere file_spec.SetPath(path); 182*8f3be7a3SJonas Devlieghere file_spec.SetIsResolved(true); 1831408bf72SPavel Labath } 1842c22c800SJonas Devlieghere 1852c22c800SJonas Devlieghere bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) { 1862c22c800SJonas Devlieghere // If the directory is set there's nothing to do. 1872c22c800SJonas Devlieghere const ConstString &directory = file_spec.GetDirectory(); 1882c22c800SJonas Devlieghere if (directory) 1892c22c800SJonas Devlieghere return false; 1902c22c800SJonas Devlieghere 1912c22c800SJonas Devlieghere // We cannot look for a file if there's no file name. 1922c22c800SJonas Devlieghere const ConstString &filename = file_spec.GetFilename(); 1932c22c800SJonas Devlieghere if (!filename) 1942c22c800SJonas Devlieghere return false; 1952c22c800SJonas Devlieghere 1962c22c800SJonas Devlieghere // Search for the file on the host. 1972c22c800SJonas Devlieghere const std::string filename_str(filename.GetCString()); 1982c22c800SJonas Devlieghere llvm::ErrorOr<std::string> error_or_path = 1992c22c800SJonas Devlieghere llvm::sys::findProgramByName(filename_str); 2002c22c800SJonas Devlieghere if (!error_or_path) 2012c22c800SJonas Devlieghere return false; 2022c22c800SJonas Devlieghere 2032c22c800SJonas Devlieghere // findProgramByName returns "." if it can't find the file. 2042c22c800SJonas Devlieghere llvm::StringRef path = *error_or_path; 2052c22c800SJonas Devlieghere llvm::StringRef parent = llvm::sys::path::parent_path(path); 2062c22c800SJonas Devlieghere if (parent.empty() || parent == ".") 2072c22c800SJonas Devlieghere return false; 2082c22c800SJonas Devlieghere 2092c22c800SJonas Devlieghere // Make sure that the result exists. 210*8f3be7a3SJonas Devlieghere FileSpec result(*error_or_path); 2112c22c800SJonas Devlieghere if (!Exists(result)) 2122c22c800SJonas Devlieghere return false; 2132c22c800SJonas Devlieghere 2142c22c800SJonas Devlieghere file_spec = result; 2152c22c800SJonas Devlieghere return true; 2162c22c800SJonas Devlieghere } 217