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 1246376966SJonas Devlieghere #include "lldb/Utility/TildeExpressionResolver.h" 1346376966SJonas Devlieghere 141408bf72SPavel Labath #include "llvm/Support/FileSystem.h" 1546376966SJonas Devlieghere #include "llvm/Support/Threading.h" 167a9e7621SOleksiy Vyalov 176801be33SOleksiy Vyalov #include <algorithm> 187a9e7621SOleksiy Vyalov #include <fstream> 197a9e7621SOleksiy Vyalov #include <vector> 207a9e7621SOleksiy Vyalov 217a9e7621SOleksiy Vyalov using namespace lldb; 227a9e7621SOleksiy Vyalov using namespace lldb_private; 2346376966SJonas Devlieghere using namespace llvm; 247a9e7621SOleksiy Vyalov 2546376966SJonas Devlieghere FileSystem &FileSystem::Instance() { return *InstanceImpl(); } 2646376966SJonas Devlieghere 2746376966SJonas Devlieghere void FileSystem::Initialize() { 2846376966SJonas Devlieghere assert(!InstanceImpl()); 2946376966SJonas Devlieghere InstanceImpl().emplace(); 3046376966SJonas Devlieghere } 3146376966SJonas Devlieghere 3246376966SJonas Devlieghere void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) { 3346376966SJonas Devlieghere assert(!InstanceImpl()); 3446376966SJonas Devlieghere InstanceImpl().emplace(fs); 3546376966SJonas Devlieghere } 3646376966SJonas Devlieghere 3746376966SJonas Devlieghere void FileSystem::Terminate() { 3846376966SJonas Devlieghere assert(InstanceImpl()); 3946376966SJonas Devlieghere InstanceImpl().reset(); 4046376966SJonas Devlieghere } 4146376966SJonas Devlieghere 4246376966SJonas Devlieghere Optional<FileSystem> &FileSystem::InstanceImpl() { 4346376966SJonas Devlieghere static Optional<FileSystem> g_fs; 4446376966SJonas Devlieghere return g_fs; 4546376966SJonas Devlieghere } 4646376966SJonas Devlieghere 4746376966SJonas Devlieghere void FileSystem::SetFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> fs) { 4846376966SJonas Devlieghere m_fs = fs; 4946376966SJonas Devlieghere } 5046376966SJonas Devlieghere 5146376966SJonas Devlieghere sys::TimePoint<> 5246376966SJonas Devlieghere FileSystem::GetModificationTime(const FileSpec &file_spec) const { 5346376966SJonas Devlieghere return GetModificationTime(file_spec.GetPath()); 5446376966SJonas Devlieghere } 5546376966SJonas Devlieghere 5646376966SJonas Devlieghere sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const { 5746376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 5846376966SJonas Devlieghere if (!status) 5946376966SJonas Devlieghere return sys::TimePoint<>(); 6046376966SJonas Devlieghere return status->getLastModificationTime(); 6146376966SJonas Devlieghere } 6246376966SJonas Devlieghere 6346376966SJonas Devlieghere uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const { 6446376966SJonas Devlieghere return GetByteSize(file_spec.GetPath()); 6546376966SJonas Devlieghere } 6646376966SJonas Devlieghere 6746376966SJonas Devlieghere uint64_t FileSystem::GetByteSize(const Twine &path) const { 6846376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 6946376966SJonas Devlieghere if (!status) 7046376966SJonas Devlieghere return 0; 7146376966SJonas Devlieghere return status->getSize(); 7246376966SJonas Devlieghere } 7346376966SJonas Devlieghere 7446376966SJonas Devlieghere uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const { 7546376966SJonas Devlieghere return GetPermissions(file_spec.GetPath()); 7646376966SJonas Devlieghere } 7746376966SJonas Devlieghere 7846376966SJonas Devlieghere uint32_t FileSystem::GetPermissions(const Twine &path) const { 7946376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 8046376966SJonas Devlieghere if (!status) 8146376966SJonas Devlieghere return sys::fs::perms::perms_not_known; 8246376966SJonas Devlieghere return status->getPermissions(); 8346376966SJonas Devlieghere } 8446376966SJonas Devlieghere 8546376966SJonas Devlieghere bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); } 8646376966SJonas Devlieghere 8746376966SJonas Devlieghere bool FileSystem::Exists(const FileSpec &file_spec) const { 8846376966SJonas Devlieghere return Exists(file_spec.GetPath()); 8946376966SJonas Devlieghere } 9046376966SJonas Devlieghere 9146376966SJonas Devlieghere bool FileSystem::Readable(const Twine &path) const { 9246376966SJonas Devlieghere return GetPermissions(path) & sys::fs::perms::all_read; 9346376966SJonas Devlieghere } 9446376966SJonas Devlieghere 9546376966SJonas Devlieghere bool FileSystem::Readable(const FileSpec &file_spec) const { 9646376966SJonas Devlieghere return Readable(file_spec.GetPath()); 9746376966SJonas Devlieghere } 9846376966SJonas Devlieghere 99*9ca491daSJonas Devlieghere void FileSystem::EnumerateDirectory(Twine path, bool find_directories, 100*9ca491daSJonas Devlieghere bool find_files, bool find_other, 101*9ca491daSJonas Devlieghere EnumerateDirectoryCallbackType callback, 102*9ca491daSJonas Devlieghere void *callback_baton) { 103*9ca491daSJonas Devlieghere std::error_code EC; 104*9ca491daSJonas Devlieghere vfs::recursive_directory_iterator Iter(*m_fs, path, EC); 105*9ca491daSJonas Devlieghere vfs::recursive_directory_iterator End; 106*9ca491daSJonas Devlieghere for (; Iter != End && !EC; Iter.increment(EC)) { 107*9ca491daSJonas Devlieghere const auto &Item = *Iter; 108*9ca491daSJonas Devlieghere ErrorOr<vfs::Status> Status = m_fs->status(Item.path()); 109*9ca491daSJonas Devlieghere if (!Status) 110*9ca491daSJonas Devlieghere break; 111*9ca491daSJonas Devlieghere if (!find_files && Status->isRegularFile()) 112*9ca491daSJonas Devlieghere continue; 113*9ca491daSJonas Devlieghere if (!find_directories && Status->isDirectory()) 114*9ca491daSJonas Devlieghere continue; 115*9ca491daSJonas Devlieghere if (!find_other && Status->isOther()) 116*9ca491daSJonas Devlieghere continue; 117*9ca491daSJonas Devlieghere 118*9ca491daSJonas Devlieghere auto Result = callback(callback_baton, Status->getType(), Item.path()); 119*9ca491daSJonas Devlieghere if (Result == eEnumerateDirectoryResultQuit) 120*9ca491daSJonas Devlieghere return; 121*9ca491daSJonas Devlieghere if (Result == eEnumerateDirectoryResultNext) { 122*9ca491daSJonas Devlieghere // Default behavior is to recurse. Opt out if the callback doesn't want 123*9ca491daSJonas Devlieghere // this behavior. 124*9ca491daSJonas Devlieghere Iter.no_push(); 125*9ca491daSJonas Devlieghere } 126*9ca491daSJonas Devlieghere } 127*9ca491daSJonas Devlieghere } 128*9ca491daSJonas Devlieghere 12946376966SJonas Devlieghere std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const { 13046376966SJonas Devlieghere return m_fs->makeAbsolute(path); 13146376966SJonas Devlieghere } 13246376966SJonas Devlieghere 13346376966SJonas Devlieghere std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const { 13446376966SJonas Devlieghere SmallString<128> path; 13546376966SJonas Devlieghere file_spec.GetPath(path, false); 13646376966SJonas Devlieghere 13746376966SJonas Devlieghere auto EC = MakeAbsolute(path); 13846376966SJonas Devlieghere if (EC) 13946376966SJonas Devlieghere return EC; 14046376966SJonas Devlieghere 14146376966SJonas Devlieghere FileSpec new_file_spec(path, false, file_spec.GetPathStyle()); 14246376966SJonas Devlieghere file_spec = new_file_spec; 14346376966SJonas Devlieghere return {}; 14446376966SJonas Devlieghere } 14546376966SJonas Devlieghere 14646376966SJonas Devlieghere std::error_code FileSystem::GetRealPath(const Twine &path, 14746376966SJonas Devlieghere SmallVectorImpl<char> &output) const { 14846376966SJonas Devlieghere return m_fs->getRealPath(path, output); 14946376966SJonas Devlieghere } 15046376966SJonas Devlieghere 15146376966SJonas Devlieghere void FileSystem::Resolve(SmallVectorImpl<char> &path) { 15246376966SJonas Devlieghere if (path.empty()) 15346376966SJonas Devlieghere return; 15446376966SJonas Devlieghere 15546376966SJonas Devlieghere // Resolve tilde. 15646376966SJonas Devlieghere SmallString<128> original_path(path.begin(), path.end()); 15746376966SJonas Devlieghere StandardTildeExpressionResolver Resolver; 15846376966SJonas Devlieghere Resolver.ResolveFullPath(original_path, path); 15946376966SJonas Devlieghere 16046376966SJonas Devlieghere // Try making the path absolute if it exists. 16146376966SJonas Devlieghere SmallString<128> absolute_path(path.begin(), path.end()); 16246376966SJonas Devlieghere MakeAbsolute(path); 16346376966SJonas Devlieghere if (!Exists(path)) { 16446376966SJonas Devlieghere path.clear(); 16546376966SJonas Devlieghere path.append(original_path.begin(), original_path.end()); 16646376966SJonas Devlieghere } 16746376966SJonas Devlieghere } 16846376966SJonas Devlieghere 16946376966SJonas Devlieghere void FileSystem::Resolve(FileSpec &file_spec) { 17046376966SJonas Devlieghere // Extract path from the FileSpec. 17146376966SJonas Devlieghere SmallString<128> path; 17246376966SJonas Devlieghere file_spec.GetPath(path); 17346376966SJonas Devlieghere 17446376966SJonas Devlieghere // Resolve the path. 17546376966SJonas Devlieghere Resolve(path); 17646376966SJonas Devlieghere 17746376966SJonas Devlieghere // Update the FileSpec with the resolved path. 17846376966SJonas Devlieghere file_spec.SetPath(path); 1791408bf72SPavel Labath } 180