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 <cstdint>
25 #include <cstdio>
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() : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr) {}
35   FileSystem(std::shared_ptr<llvm::FileCollectorBase> collector)
36       : m_fs(llvm::vfs::getRealFileSystem()), m_collector(std::move(collector)),
37         m_mapped(false) {}
38   FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
39              bool mapped = false)
40       : m_fs(std::move(fs)), m_collector(nullptr), m_mapped(mapped) {}
41 
42   FileSystem(const FileSystem &fs) = delete;
43   FileSystem &operator=(const FileSystem &fs) = delete;
44 
45   static FileSystem &Instance();
46 
47   static void Initialize();
48   static void Initialize(std::shared_ptr<llvm::FileCollectorBase> collector);
49   static llvm::Error Initialize(const FileSpec &mapping);
50   static void Initialize(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs);
51   static void Terminate();
52 
53   Status Symlink(const FileSpec &src, const FileSpec &dst);
54   Status Readlink(const FileSpec &src, FileSpec &dst);
55 
56   Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst);
57 
58   /// Wraps ::fopen in a platform-independent way.
59   FILE *Fopen(const char *path, const char *mode);
60 
61   /// Wraps ::open in a platform-independent way.
62   int Open(const char *path, int flags, int mode);
63 
64   llvm::Expected<std::unique_ptr<File>>
65   Open(const FileSpec &file_spec, File::OpenOptions options,
66        uint32_t permissions = lldb::eFilePermissionsFileDefault,
67        bool should_close_fd = true);
68 
69   /// Get a directory iterator.
70   /// \{
71   llvm::vfs::directory_iterator DirBegin(const FileSpec &file_spec,
72                                          std::error_code &ec);
73   llvm::vfs::directory_iterator DirBegin(const llvm::Twine &dir,
74                                          std::error_code &ec);
75   /// \}
76 
77   /// Returns the Status object for the given file.
78   /// \{
79   llvm::ErrorOr<llvm::vfs::Status> GetStatus(const FileSpec &file_spec) const;
80   llvm::ErrorOr<llvm::vfs::Status> GetStatus(const llvm::Twine &path) const;
81   /// \}
82 
83   /// Returns the modification time of the given file.
84   /// \{
85   llvm::sys::TimePoint<> GetModificationTime(const FileSpec &file_spec) const;
86   llvm::sys::TimePoint<> GetModificationTime(const llvm::Twine &path) const;
87   /// \}
88 
89   /// Returns the on-disk size of the given file in bytes.
90   /// \{
91   uint64_t GetByteSize(const FileSpec &file_spec) const;
92   uint64_t GetByteSize(const llvm::Twine &path) const;
93   /// \}
94 
95   /// Return the current permissions of the given file.
96   ///
97   /// Returns a bitmask for the current permissions of the file (zero or more
98   /// of the permission bits defined in File::Permissions).
99   /// \{
100   uint32_t GetPermissions(const FileSpec &file_spec) const;
101   uint32_t GetPermissions(const llvm::Twine &path) const;
102   uint32_t GetPermissions(const FileSpec &file_spec, std::error_code &ec) const;
103   uint32_t GetPermissions(const llvm::Twine &path, std::error_code &ec) const;
104   /// \}
105 
106   /// Returns whether the given file exists.
107   /// \{
108   bool Exists(const FileSpec &file_spec) const;
109   bool Exists(const llvm::Twine &path) const;
110   /// \}
111 
112   /// Returns whether the given file is readable.
113   /// \{
114   bool Readable(const FileSpec &file_spec) const;
115   bool Readable(const llvm::Twine &path) const;
116   /// \}
117 
118   /// Returns whether the given path is a directory.
119   /// \{
120   bool IsDirectory(const FileSpec &file_spec) const;
121   bool IsDirectory(const llvm::Twine &path) const;
122   /// \}
123 
124   /// Returns whether the given path is local to the file system.
125   /// \{
126   bool IsLocal(const FileSpec &file_spec) const;
127   bool IsLocal(const llvm::Twine &path) const;
128   /// \}
129 
130   /// Make the given file path absolute.
131   /// \{
132   std::error_code MakeAbsolute(llvm::SmallVectorImpl<char> &path) const;
133   std::error_code MakeAbsolute(FileSpec &file_spec) const;
134   /// \}
135 
136   /// Resolve path to make it canonical.
137   /// \{
138   void Resolve(llvm::SmallVectorImpl<char> &path);
139   void Resolve(FileSpec &file_spec);
140   /// \}
141 
142   /// Remove a single file.
143   ///
144   /// The path must specify a file and not a directory.
145   /// \{
146   Status RemoveFile(const FileSpec &file_spec);
147   Status RemoveFile(const llvm::Twine &path);
148   /// \}
149 
150   //// Create memory buffer from path.
151   /// \{
152   std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const llvm::Twine &path,
153                                                    uint64_t size = 0,
154                                                    uint64_t offset = 0);
155   std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const FileSpec &file_spec,
156                                                    uint64_t size = 0,
157                                                    uint64_t offset = 0);
158   /// \}
159 
160   /// Call into the Host to see if it can help find the file.
161   bool ResolveExecutableLocation(FileSpec &file_spec);
162 
163   /// Get the user home directory.
164   bool GetHomeDirectory(llvm::SmallVectorImpl<char> &path) const;
165   bool GetHomeDirectory(FileSpec &file_spec) const;
166 
167   enum EnumerateDirectoryResult {
168     /// Enumerate next entry in the current directory.
169     eEnumerateDirectoryResultNext,
170     /// Recurse into the current entry if it is a directory or symlink, or next
171     /// if not.
172     eEnumerateDirectoryResultEnter,
173     /// Stop directory enumerations at any level.
174     eEnumerateDirectoryResultQuit
175   };
176 
177   typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType)(
178       void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef);
179 
180   typedef std::function<EnumerateDirectoryResult(
181       llvm::sys::fs::file_type file_type, llvm::StringRef)>
182       DirectoryCallback;
183 
184   void EnumerateDirectory(llvm::Twine path, bool find_directories,
185                           bool find_files, bool find_other,
186                           EnumerateDirectoryCallbackType callback,
187                           void *callback_baton);
188 
189   std::error_code GetRealPath(const llvm::Twine &path,
190                               llvm::SmallVectorImpl<char> &output) const;
191 
192   llvm::ErrorOr<std::string> GetExternalPath(const llvm::Twine &path);
193   llvm::ErrorOr<std::string> GetExternalPath(const FileSpec &file_spec);
194 
195   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> GetVirtualFileSystem() {
196     return m_fs;
197   }
198 
199   void Collect(const FileSpec &file_spec);
200   void Collect(const llvm::Twine &file);
201 
202   void SetHomeDirectory(std::string home_directory);
203 
204 private:
205   static llvm::Optional<FileSystem> &InstanceImpl();
206   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
207   std::shared_ptr<llvm::FileCollectorBase> m_collector;
208   std::string m_home_directory;
209   bool m_mapped = false;
210 };
211 } // namespace lldb_private
212 
213 #endif
214