1 //===-- FileSystem.h --------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_HOST_FILESYSTEM_H 10 #define LLDB_HOST_FILESYSTEM_H 11 12 #include "lldb/Host/File.h" 13 #include "lldb/Utility/DataBuffer.h" 14 #include "lldb/Utility/FileSpec.h" 15 #include "lldb/Utility/LLDBAssert.h" 16 #include "lldb/Utility/Status.h" 17 #include "lldb/Utility/TildeExpressionResolver.h" 18 19 #include "llvm/Support/Chrono.h" 20 #include "llvm/Support/VirtualFileSystem.h" 21 22 #include "lldb/lldb-types.h" 23 24 #include <cstdint> 25 #include <cstdio> 26 #include <optional> 27 #include <sys/stat.h> 28 29 namespace lldb_private { 30 class FileSystem { 31 public: 32 static const char *DEV_NULL; 33 static const char *PATH_CONVERSION_ERROR; 34 FileSystem()35 FileSystem() 36 : m_fs(llvm::vfs::getRealFileSystem()), 37 m_tilde_resolver(std::make_unique<StandardTildeExpressionResolver>()) {} FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs)38 FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs) 39 : m_fs(std::move(fs)), 40 m_tilde_resolver(std::make_unique<StandardTildeExpressionResolver>()) {} FileSystem(std::unique_ptr<TildeExpressionResolver> tilde_resolver)41 FileSystem(std::unique_ptr<TildeExpressionResolver> tilde_resolver) 42 : m_fs(llvm::vfs::getRealFileSystem()), 43 m_tilde_resolver(std::move(tilde_resolver)) {} 44 45 FileSystem(const FileSystem &fs) = delete; 46 FileSystem &operator=(const FileSystem &fs) = delete; 47 48 static FileSystem &Instance(); 49 Initialize(T &&...t)50 template <class... T> static void Initialize(T &&...t) { 51 lldbassert(!InstanceImpl() && "Already initialized."); 52 InstanceImpl().emplace(std::forward<T>(t)...); 53 } 54 static void Terminate(); 55 56 Status Symlink(const FileSpec &src, const FileSpec &dst); 57 Status Readlink(const FileSpec &src, FileSpec &dst); 58 59 Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst); 60 61 /// Wraps ::fopen in a platform-independent way. 62 FILE *Fopen(const char *path, const char *mode); 63 64 /// Wraps ::open in a platform-independent way. 65 int Open(const char *path, int flags, int mode = 0600); 66 67 llvm::Expected<std::unique_ptr<File>> 68 Open(const FileSpec &file_spec, File::OpenOptions options, 69 uint32_t permissions = lldb::eFilePermissionsFileDefault, 70 bool should_close_fd = true); 71 72 /// Get a directory iterator. 73 /// \{ 74 llvm::vfs::directory_iterator DirBegin(const FileSpec &file_spec, 75 std::error_code &ec); 76 llvm::vfs::directory_iterator DirBegin(const llvm::Twine &dir, 77 std::error_code &ec); 78 /// \} 79 80 /// Returns the Status object for the given file. 81 /// \{ 82 llvm::ErrorOr<llvm::vfs::Status> GetStatus(const FileSpec &file_spec) const; 83 llvm::ErrorOr<llvm::vfs::Status> GetStatus(const llvm::Twine &path) const; 84 /// \} 85 86 /// Returns the modification time of the given file. 87 /// \{ 88 llvm::sys::TimePoint<> GetModificationTime(const FileSpec &file_spec) const; 89 llvm::sys::TimePoint<> GetModificationTime(const llvm::Twine &path) const; 90 /// \} 91 92 /// Returns the on-disk size of the given file in bytes. 93 /// \{ 94 uint64_t GetByteSize(const FileSpec &file_spec) const; 95 uint64_t GetByteSize(const llvm::Twine &path) const; 96 /// \} 97 98 /// Return the current permissions of the given file. 99 /// 100 /// Returns a bitmask for the current permissions of the file (zero or more 101 /// of the permission bits defined in File::Permissions). 102 /// \{ 103 uint32_t GetPermissions(const FileSpec &file_spec) const; 104 uint32_t GetPermissions(const llvm::Twine &path) const; 105 uint32_t GetPermissions(const FileSpec &file_spec, std::error_code &ec) const; 106 uint32_t GetPermissions(const llvm::Twine &path, std::error_code &ec) const; 107 /// \} 108 109 /// Returns whether the given file exists. 110 /// \{ 111 bool Exists(const FileSpec &file_spec) const; 112 bool Exists(const llvm::Twine &path) const; 113 /// \} 114 115 /// Returns whether the given file is readable. 116 /// \{ 117 bool Readable(const FileSpec &file_spec) const; 118 bool Readable(const llvm::Twine &path) const; 119 /// \} 120 121 /// Returns whether the given path is a directory. 122 /// \{ 123 bool IsDirectory(const FileSpec &file_spec) const; 124 bool IsDirectory(const llvm::Twine &path) const; 125 /// \} 126 127 /// Returns whether the given path is local to the file system. 128 /// \{ 129 bool IsLocal(const FileSpec &file_spec) const; 130 bool IsLocal(const llvm::Twine &path) const; 131 /// \} 132 133 /// Make the given file path absolute. 134 /// \{ 135 std::error_code MakeAbsolute(llvm::SmallVectorImpl<char> &path) const; 136 std::error_code MakeAbsolute(FileSpec &file_spec) const; 137 /// \} 138 139 /// Resolve path to make it canonical. 140 /// \{ 141 void Resolve(llvm::SmallVectorImpl<char> &path); 142 void Resolve(FileSpec &file_spec); 143 /// \} 144 145 /// Remove a single file. 146 /// 147 /// The path must specify a file and not a directory. 148 /// \{ 149 Status RemoveFile(const FileSpec &file_spec); 150 Status RemoveFile(const llvm::Twine &path); 151 /// \} 152 153 //// Create memory buffer from path. 154 /// \{ 155 std::shared_ptr<DataBuffer> CreateDataBuffer(const llvm::Twine &path, 156 uint64_t size = 0, 157 uint64_t offset = 0); 158 std::shared_ptr<DataBuffer> CreateDataBuffer(const FileSpec &file_spec, 159 uint64_t size = 0, 160 uint64_t offset = 0); 161 std::shared_ptr<WritableDataBuffer> 162 CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size = 0, 163 uint64_t offset = 0); 164 std::shared_ptr<WritableDataBuffer> 165 CreateWritableDataBuffer(const FileSpec &file_spec, uint64_t size = 0, 166 uint64_t offset = 0); 167 /// \} 168 169 /// Call into the Host to see if it can help find the file. 170 bool ResolveExecutableLocation(FileSpec &file_spec); 171 172 /// Get the user home directory. 173 bool GetHomeDirectory(llvm::SmallVectorImpl<char> &path) const; 174 bool GetHomeDirectory(FileSpec &file_spec) const; 175 176 enum EnumerateDirectoryResult { 177 /// Enumerate next entry in the current directory. 178 eEnumerateDirectoryResultNext, 179 /// Recurse into the current entry if it is a directory or symlink, or next 180 /// if not. 181 eEnumerateDirectoryResultEnter, 182 /// Stop directory enumerations at any level. 183 eEnumerateDirectoryResultQuit 184 }; 185 186 typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType)( 187 void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef); 188 189 typedef std::function<EnumerateDirectoryResult( 190 llvm::sys::fs::file_type file_type, llvm::StringRef)> 191 DirectoryCallback; 192 193 void EnumerateDirectory(llvm::Twine path, bool find_directories, 194 bool find_files, bool find_other, 195 EnumerateDirectoryCallbackType callback, 196 void *callback_baton); 197 198 std::error_code GetRealPath(const llvm::Twine &path, 199 llvm::SmallVectorImpl<char> &output) const; 200 GetVirtualFileSystem()201 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> GetVirtualFileSystem() { 202 return m_fs; 203 } 204 205 void SetHomeDirectory(std::string home_directory); 206 207 private: 208 static std::optional<FileSystem> &InstanceImpl(); 209 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs; 210 std::unique_ptr<TildeExpressionResolver> m_tilde_resolver; 211 std::string m_home_directory; 212 }; 213 } // namespace lldb_private 214 215 #endif 216