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 | |
35 | FileSystem() |
36 | : m_fs(llvm::vfs::getRealFileSystem()), |
37 | m_tilde_resolver(std::make_unique<StandardTildeExpressionResolver>()) {} |
38 | FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs) |
39 | : m_fs(std::move(fs)), |
40 | m_tilde_resolver(std::make_unique<StandardTildeExpressionResolver>()) {} |
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 | |
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 | |
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 | |