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