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 12*46376966SJonas Devlieghere #include "lldb/Utility/TildeExpressionResolver.h" 13*46376966SJonas Devlieghere 141408bf72SPavel Labath #include "llvm/Support/FileSystem.h" 15*46376966SJonas 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; 23*46376966SJonas Devlieghere using namespace llvm; 247a9e7621SOleksiy Vyalov 25*46376966SJonas Devlieghere FileSystem &FileSystem::Instance() { return *InstanceImpl(); } 26*46376966SJonas Devlieghere 27*46376966SJonas Devlieghere void FileSystem::Initialize() { 28*46376966SJonas Devlieghere assert(!InstanceImpl()); 29*46376966SJonas Devlieghere InstanceImpl().emplace(); 30*46376966SJonas Devlieghere } 31*46376966SJonas Devlieghere 32*46376966SJonas Devlieghere void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) { 33*46376966SJonas Devlieghere assert(!InstanceImpl()); 34*46376966SJonas Devlieghere InstanceImpl().emplace(fs); 35*46376966SJonas Devlieghere } 36*46376966SJonas Devlieghere 37*46376966SJonas Devlieghere void FileSystem::Terminate() { 38*46376966SJonas Devlieghere assert(InstanceImpl()); 39*46376966SJonas Devlieghere InstanceImpl().reset(); 40*46376966SJonas Devlieghere } 41*46376966SJonas Devlieghere 42*46376966SJonas Devlieghere Optional<FileSystem> &FileSystem::InstanceImpl() { 43*46376966SJonas Devlieghere static Optional<FileSystem> g_fs; 44*46376966SJonas Devlieghere return g_fs; 45*46376966SJonas Devlieghere } 46*46376966SJonas Devlieghere 47*46376966SJonas Devlieghere void FileSystem::SetFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> fs) { 48*46376966SJonas Devlieghere m_fs = fs; 49*46376966SJonas Devlieghere } 50*46376966SJonas Devlieghere 51*46376966SJonas Devlieghere sys::TimePoint<> 52*46376966SJonas Devlieghere FileSystem::GetModificationTime(const FileSpec &file_spec) const { 53*46376966SJonas Devlieghere return GetModificationTime(file_spec.GetPath()); 54*46376966SJonas Devlieghere } 55*46376966SJonas Devlieghere 56*46376966SJonas Devlieghere sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const { 57*46376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 58*46376966SJonas Devlieghere if (!status) 59*46376966SJonas Devlieghere return sys::TimePoint<>(); 60*46376966SJonas Devlieghere return status->getLastModificationTime(); 61*46376966SJonas Devlieghere } 62*46376966SJonas Devlieghere 63*46376966SJonas Devlieghere uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const { 64*46376966SJonas Devlieghere return GetByteSize(file_spec.GetPath()); 65*46376966SJonas Devlieghere } 66*46376966SJonas Devlieghere 67*46376966SJonas Devlieghere uint64_t FileSystem::GetByteSize(const Twine &path) const { 68*46376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 69*46376966SJonas Devlieghere if (!status) 70*46376966SJonas Devlieghere return 0; 71*46376966SJonas Devlieghere return status->getSize(); 72*46376966SJonas Devlieghere } 73*46376966SJonas Devlieghere 74*46376966SJonas Devlieghere uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const { 75*46376966SJonas Devlieghere return GetPermissions(file_spec.GetPath()); 76*46376966SJonas Devlieghere } 77*46376966SJonas Devlieghere 78*46376966SJonas Devlieghere uint32_t FileSystem::GetPermissions(const Twine &path) const { 79*46376966SJonas Devlieghere ErrorOr<vfs::Status> status = m_fs->status(path); 80*46376966SJonas Devlieghere if (!status) 81*46376966SJonas Devlieghere return sys::fs::perms::perms_not_known; 82*46376966SJonas Devlieghere return status->getPermissions(); 83*46376966SJonas Devlieghere } 84*46376966SJonas Devlieghere 85*46376966SJonas Devlieghere bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); } 86*46376966SJonas Devlieghere 87*46376966SJonas Devlieghere bool FileSystem::Exists(const FileSpec &file_spec) const { 88*46376966SJonas Devlieghere return Exists(file_spec.GetPath()); 89*46376966SJonas Devlieghere } 90*46376966SJonas Devlieghere 91*46376966SJonas Devlieghere bool FileSystem::Readable(const Twine &path) const { 92*46376966SJonas Devlieghere return GetPermissions(path) & sys::fs::perms::all_read; 93*46376966SJonas Devlieghere } 94*46376966SJonas Devlieghere 95*46376966SJonas Devlieghere bool FileSystem::Readable(const FileSpec &file_spec) const { 96*46376966SJonas Devlieghere return Readable(file_spec.GetPath()); 97*46376966SJonas Devlieghere } 98*46376966SJonas Devlieghere 99*46376966SJonas Devlieghere void FileSystem::EnumerateDirectory(Twine path, bool find_directories, 100*46376966SJonas Devlieghere bool find_files, bool find_other, 101*46376966SJonas Devlieghere EnumerateDirectoryCallbackType callback, 102*46376966SJonas Devlieghere void *callback_baton) { 103*46376966SJonas Devlieghere std::error_code EC; 104*46376966SJonas Devlieghere vfs::recursive_directory_iterator Iter(*m_fs, path, EC); 105*46376966SJonas Devlieghere vfs::recursive_directory_iterator End; 106*46376966SJonas Devlieghere for (; Iter != End && !EC; Iter.increment(EC)) { 107*46376966SJonas Devlieghere const auto &Item = *Iter; 108*46376966SJonas Devlieghere ErrorOr<vfs::Status> Status = m_fs->status(Item.path()); 109*46376966SJonas Devlieghere if (!Status) 110*46376966SJonas Devlieghere break; 111*46376966SJonas Devlieghere if (!find_files && Status->isRegularFile()) 112*46376966SJonas Devlieghere continue; 113*46376966SJonas Devlieghere if (!find_directories && Status->isDirectory()) 114*46376966SJonas Devlieghere continue; 115*46376966SJonas Devlieghere if (!find_other && Status->isOther()) 116*46376966SJonas Devlieghere continue; 117*46376966SJonas Devlieghere 118*46376966SJonas Devlieghere auto Result = callback(callback_baton, Status->getType(), Item.path()); 119*46376966SJonas Devlieghere if (Result == eEnumerateDirectoryResultQuit) 120*46376966SJonas Devlieghere return; 121*46376966SJonas Devlieghere if (Result == eEnumerateDirectoryResultNext) { 122*46376966SJonas Devlieghere // Default behavior is to recurse. Opt out if the callback doesn't want 123*46376966SJonas Devlieghere // this behavior. 124*46376966SJonas Devlieghere Iter.no_push(); 125*46376966SJonas Devlieghere } 126*46376966SJonas Devlieghere } 127*46376966SJonas Devlieghere } 128*46376966SJonas Devlieghere 129*46376966SJonas Devlieghere std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const { 130*46376966SJonas Devlieghere return m_fs->makeAbsolute(path); 131*46376966SJonas Devlieghere } 132*46376966SJonas Devlieghere 133*46376966SJonas Devlieghere std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const { 134*46376966SJonas Devlieghere SmallString<128> path; 135*46376966SJonas Devlieghere file_spec.GetPath(path, false); 136*46376966SJonas Devlieghere 137*46376966SJonas Devlieghere auto EC = MakeAbsolute(path); 138*46376966SJonas Devlieghere if (EC) 139*46376966SJonas Devlieghere return EC; 140*46376966SJonas Devlieghere 141*46376966SJonas Devlieghere FileSpec new_file_spec(path, false, file_spec.GetPathStyle()); 142*46376966SJonas Devlieghere file_spec = new_file_spec; 143*46376966SJonas Devlieghere return {}; 144*46376966SJonas Devlieghere } 145*46376966SJonas Devlieghere 146*46376966SJonas Devlieghere std::error_code FileSystem::GetRealPath(const Twine &path, 147*46376966SJonas Devlieghere SmallVectorImpl<char> &output) const { 148*46376966SJonas Devlieghere return m_fs->getRealPath(path, output); 149*46376966SJonas Devlieghere } 150*46376966SJonas Devlieghere 151*46376966SJonas Devlieghere void FileSystem::Resolve(SmallVectorImpl<char> &path) { 152*46376966SJonas Devlieghere if (path.empty()) 153*46376966SJonas Devlieghere return; 154*46376966SJonas Devlieghere 155*46376966SJonas Devlieghere // Resolve tilde. 156*46376966SJonas Devlieghere SmallString<128> original_path(path.begin(), path.end()); 157*46376966SJonas Devlieghere StandardTildeExpressionResolver Resolver; 158*46376966SJonas Devlieghere Resolver.ResolveFullPath(original_path, path); 159*46376966SJonas Devlieghere 160*46376966SJonas Devlieghere // Try making the path absolute if it exists. 161*46376966SJonas Devlieghere SmallString<128> absolute_path(path.begin(), path.end()); 162*46376966SJonas Devlieghere MakeAbsolute(path); 163*46376966SJonas Devlieghere if (!Exists(path)) { 164*46376966SJonas Devlieghere path.clear(); 165*46376966SJonas Devlieghere path.append(original_path.begin(), original_path.end()); 166*46376966SJonas Devlieghere } 167*46376966SJonas Devlieghere } 168*46376966SJonas Devlieghere 169*46376966SJonas Devlieghere void FileSystem::Resolve(FileSpec &file_spec) { 170*46376966SJonas Devlieghere // Extract path from the FileSpec. 171*46376966SJonas Devlieghere SmallString<128> path; 172*46376966SJonas Devlieghere file_spec.GetPath(path); 173*46376966SJonas Devlieghere 174*46376966SJonas Devlieghere // Resolve the path. 175*46376966SJonas Devlieghere Resolve(path); 176*46376966SJonas Devlieghere 177*46376966SJonas Devlieghere // Update the FileSpec with the resolved path. 178*46376966SJonas Devlieghere file_spec.SetPath(path); 1791408bf72SPavel Labath } 180