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/DataBufferLLVM.h" |
14 | #include "lldb/Utility/FileSpec.h" |
15 | #include "lldb/Utility/Status.h" |
16 | |
17 | #include "llvm/ADT/Optional.h" |
18 | #include "llvm/Support/Chrono.h" |
19 | #include "llvm/Support/FileCollector.h" |
20 | #include "llvm/Support/VirtualFileSystem.h" |
21 | |
22 | #include "lldb/lldb-types.h" |
23 | |
24 | #include <stdint.h> |
25 | #include <stdio.h> |
26 | #include <sys/stat.h> |
27 | |
28 | namespace lldb_private { |
29 | class FileSystem { |
30 | public: |
31 | static const char *DEV_NULL; |
32 | static const char *PATH_CONVERSION_ERROR; |
33 | |
34 | FileSystem() |
35 | : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr), |
36 | m_home_directory(), m_mapped(false) {} |
37 | FileSystem(std::shared_ptr<llvm::FileCollectorBase> collector) |
38 | : m_fs(llvm::vfs::getRealFileSystem()), m_collector(std::move(collector)), |
39 | m_home_directory(), m_mapped(false) {} |
40 | FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs, |
41 | bool mapped = false) |
42 | : m_fs(std::move(fs)), m_collector(nullptr), m_home_directory(), |
43 | m_mapped(mapped) {} |
44 | |
45 | FileSystem(const FileSystem &fs) = delete; |
46 | FileSystem &operator=(const FileSystem &fs) = delete; |
47 | |
48 | static FileSystem &Instance(); |
49 | |
50 | static void Initialize(); |
51 | static void Initialize(std::shared_ptr<llvm::FileCollectorBase> collector); |
52 | static llvm::Error Initialize(const FileSpec &mapping); |
53 | static void Initialize(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs); |
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); |
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 | //// Create memory buffer from path. |
146 | /// \{ |
147 | std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const llvm::Twine &path, |
148 | uint64_t size = 0, |
149 | uint64_t offset = 0); |
150 | std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const FileSpec &file_spec, |
151 | uint64_t size = 0, |
152 | uint64_t offset = 0); |
153 | /// \} |
154 | |
155 | /// Call into the Host to see if it can help find the file. |
156 | bool ResolveExecutableLocation(FileSpec &file_spec); |
157 | |
158 | /// Get the user home directory. |
159 | bool GetHomeDirectory(llvm::SmallVectorImpl<char> &path) const; |
160 | bool GetHomeDirectory(FileSpec &file_spec) const; |
161 | |
162 | enum EnumerateDirectoryResult { |
163 | /// Enumerate next entry in the current directory. |
164 | eEnumerateDirectoryResultNext, |
165 | /// Recurse into the current entry if it is a directory or symlink, or next |
166 | /// if not. |
167 | eEnumerateDirectoryResultEnter, |
168 | /// Stop directory enumerations at any level. |
169 | eEnumerateDirectoryResultQuit |
170 | }; |
171 | |
172 | typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType)( |
173 | void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef); |
174 | |
175 | typedef std::function<EnumerateDirectoryResult( |
176 | llvm::sys::fs::file_type file_type, llvm::StringRef)> |
177 | DirectoryCallback; |
178 | |
179 | void EnumerateDirectory(llvm::Twine path, bool find_directories, |
180 | bool find_files, bool find_other, |
181 | EnumerateDirectoryCallbackType callback, |
182 | void *callback_baton); |
183 | |
184 | std::error_code GetRealPath(const llvm::Twine &path, |
185 | llvm::SmallVectorImpl<char> &output) const; |
186 | |
187 | llvm::ErrorOr<std::string> GetExternalPath(const llvm::Twine &path); |
188 | llvm::ErrorOr<std::string> GetExternalPath(const FileSpec &file_spec); |
189 | |
190 | llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> GetVirtualFileSystem() { |
191 | return m_fs; |
192 | } |
193 | |
194 | void Collect(const FileSpec &file_spec); |
195 | void Collect(const llvm::Twine &file); |
196 | |
197 | void SetHomeDirectory(std::string home_directory); |
198 | |
199 | private: |
200 | static llvm::Optional<FileSystem> &InstanceImpl(); |
201 | llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs; |
202 | std::shared_ptr<llvm::FileCollectorBase> m_collector; |
203 | std::string m_home_directory; |
204 | bool m_mapped; |
205 | }; |
206 | } // namespace lldb_private |
207 | |
208 | #endif |
209 | |