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