aboutsummaryrefslogtreecommitdiffstats
path: root/include/lldb/Host/FileSystem.h
blob: 528c43519a326231d362fc0b3ed1c29bb4cd7b55 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//===-- FileSystem.h --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_Host_FileSystem_h
#define liblldb_Host_FileSystem_h

#include "lldb/Host/File.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"

#include "llvm/ADT/Optional.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/FileCollector.h"
#include "llvm/Support/VirtualFileSystem.h"

#include "lldb/lldb-types.h"

#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>

namespace lldb_private {
class FileSystem {
public:
  static const char *DEV_NULL;
  static const char *PATH_CONVERSION_ERROR;

  FileSystem()
      : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr),
        m_mapped(false) {}
  FileSystem(std::shared_ptr<llvm::FileCollector> collector)
      : m_fs(llvm::vfs::getRealFileSystem()), m_collector(collector),
        m_mapped(false) {}
  FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
             bool mapped = false)
      : m_fs(fs), m_collector(nullptr), m_mapped(mapped) {}

  FileSystem(const FileSystem &fs) = delete;
  FileSystem &operator=(const FileSystem &fs) = delete;

  static FileSystem &Instance();

  static void Initialize();
  static void Initialize(std::shared_ptr<llvm::FileCollector> collector);
  static llvm::Error Initialize(const FileSpec &mapping);
  static void Initialize(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs);
  static void Terminate();

  Status Symlink(const FileSpec &src, const FileSpec &dst);
  Status Readlink(const FileSpec &src, FileSpec &dst);

  Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst);

  /// Wraps ::fopen in a platform-independent way.
  FILE *Fopen(const char *path, const char *mode);

  /// Wraps ::open in a platform-independent way.
  int Open(const char *path, int flags, int mode);

  llvm::Expected<std::unique_ptr<File>>
  Open(const FileSpec &file_spec, File::OpenOptions options,
       uint32_t permissions = lldb::eFilePermissionsFileDefault,
       bool should_close_fd = true);

  /// Get a directory iterator.
  /// \{
  llvm::vfs::directory_iterator DirBegin(const FileSpec &file_spec,
                                         std::error_code &ec);
  llvm::vfs::directory_iterator DirBegin(const llvm::Twine &dir,
                                         std::error_code &ec);
  /// \}

  /// Returns the Status object for the given file.
  /// \{
  llvm::ErrorOr<llvm::vfs::Status> GetStatus(const FileSpec &file_spec) const;
  llvm::ErrorOr<llvm::vfs::Status> GetStatus(const llvm::Twine &path) const;
  /// \}

  /// Returns the modification time of the given file.
  /// \{
  llvm::sys::TimePoint<> GetModificationTime(const FileSpec &file_spec) const;
  llvm::sys::TimePoint<> GetModificationTime(const llvm::Twine &path) const;
  /// \}

  /// Returns the on-disk size of the given file in bytes.
  /// \{
  uint64_t GetByteSize(const FileSpec &file_spec) const;
  uint64_t GetByteSize(const llvm::Twine &path) const;
  /// \}

  /// Return the current permissions of the given file.
  ///
  /// Returns a bitmask for the current permissions of the file (zero or more
  /// of the permission bits defined in File::Permissions).
  /// \{
  uint32_t GetPermissions(const FileSpec &file_spec) const;
  uint32_t GetPermissions(const llvm::Twine &path) const;
  uint32_t GetPermissions(const FileSpec &file_spec, std::error_code &ec) const;
  uint32_t GetPermissions(const llvm::Twine &path, std::error_code &ec) const;
  /// \}

  /// Returns whether the given file exists.
  /// \{
  bool Exists(const FileSpec &file_spec) const;
  bool Exists(const llvm::Twine &path) const;
  /// \}

  /// Returns whether the given file is readable.
  /// \{
  bool Readable(const FileSpec &file_spec) const;
  bool Readable(const llvm::Twine &path) const;
  /// \}

  /// Returns whether the given path is a directory.
  /// \{
  bool IsDirectory(const FileSpec &file_spec) const;
  bool IsDirectory(const llvm::Twine &path) const;
  /// \}

  /// Returns whether the given path is local to the file system.
  /// \{
  bool IsLocal(const FileSpec &file_spec) const;
  bool IsLocal(const llvm::Twine &path) const;
  /// \}

  /// Make the given file path absolute.
  /// \{
  std::error_code MakeAbsolute(llvm::SmallVectorImpl<char> &path) const;
  std::error_code MakeAbsolute(FileSpec &file_spec) const;
  /// \}

  /// Resolve path to make it canonical.
  /// \{
  void Resolve(llvm::SmallVectorImpl<char> &path);
  void Resolve(FileSpec &file_spec);
  /// \}

  //// Create memory buffer from path.
  /// \{
  std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const llvm::Twine &path,
                                                   uint64_t size = 0,
                                                   uint64_t offset = 0);
  std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const FileSpec &file_spec,
                                                   uint64_t size = 0,
                                                   uint64_t offset = 0);
  /// \}

  /// Call into the Host to see if it can help find the file.
  bool ResolveExecutableLocation(FileSpec &file_spec);

  enum EnumerateDirectoryResult {
    /// Enumerate next entry in the current directory.
    eEnumerateDirectoryResultNext,
    /// Recurse into the current entry if it is a directory or symlink, or next
    /// if not.
    eEnumerateDirectoryResultEnter,
    /// Stop directory enumerations at any level.
    eEnumerateDirectoryResultQuit
  };

  typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType)(
      void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef);

  typedef std::function<EnumerateDirectoryResult(
      llvm::sys::fs::file_type file_type, llvm::StringRef)>
      DirectoryCallback;

  void EnumerateDirectory(llvm::Twine path, bool find_directories,
                          bool find_files, bool find_other,
                          EnumerateDirectoryCallbackType callback,
                          void *callback_baton);

  std::error_code GetRealPath(const llvm::Twine &path,
                              llvm::SmallVectorImpl<char> &output) const;

  llvm::ErrorOr<std::string> GetExternalPath(const llvm::Twine &path);
  llvm::ErrorOr<std::string> GetExternalPath(const FileSpec &file_spec);

  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> GetVirtualFileSystem() {
    return m_fs;
  }

private:
  static llvm::Optional<FileSystem> &InstanceImpl();
  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
  std::shared_ptr<llvm::FileCollector> m_collector;
  bool m_mapped;
};
} // namespace lldb_private

#endif