1651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===//
2651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//
3651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//                     The LLVM Compiler Infrastructure
4651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//
5651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// This file is distributed under the University of Illinois Open Source
6651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// License. See LICENSE.TXT for details.
7651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//
8651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===//
9651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \file
10651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Defines the virtual file system interface vfs::FileSystem.
11651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===//
12651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
13176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
14176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#define LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
15651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
16651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Basic/LLVM.h"
17651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/IntrusiveRefCntPtr.h"
186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/ADT/Optional.h"
19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/ErrorOr.h"
20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/FileSystem.h"
21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/SourceMgr.h"
220e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "llvm/Support/raw_ostream.h"
23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace llvm {
25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass MemoryBuffer;
26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
27651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace clang {
29651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace vfs {
30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief The result of a \p status operation.
32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass Status {
33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::string Name;
34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::fs::UniqueID UID;
35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::TimeValue MTime;
36651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  uint32_t User;
37651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  uint32_t Group;
38651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  uint64_t Size;
39651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::fs::file_type Type;
40651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::fs::perms Perms;
41651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
42651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool IsVFSMapped; // FIXME: remove when files support multiple names
446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
46651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status() : Type(llvm::sys::fs::file_type::status_error) {}
47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status(const llvm::sys::fs::file_status &Status);
48651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status(StringRef Name, StringRef RealName, llvm::sys::fs::UniqueID UID,
49651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines         llvm::sys::TimeValue MTime, uint32_t User, uint32_t Group,
50651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines         uint64_t Size, llvm::sys::fs::file_type Type,
51651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines         llvm::sys::fs::perms Perms);
52651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Returns the name that should be used for this file or directory.
54651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StringRef getName() const { return Name; }
55651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void setName(StringRef N) { Name = N; }
56651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// @name Status interface from llvm::sys::fs
58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// @{
59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::fs::file_type getType() const { return Type; }
60651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::fs::perms getPermissions() const { return Perms; }
61651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::TimeValue getLastModificationTime() const { return MTime; }
62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  uint32_t getUser() const { return User; }
64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  uint32_t getGroup() const { return Group; }
65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  uint64_t getSize() const { return Size; }
66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void setType(llvm::sys::fs::file_type v) { Type = v; }
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void setPermissions(llvm::sys::fs::perms p) { Perms = p; }
68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// @}
69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// @name Status queries
70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// These are static queries in llvm::sys::fs.
71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// @{
72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool equivalent(const Status &Other) const;
73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isDirectory() const;
74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isRegularFile() const;
75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isOther() const;
76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isSymlink() const;
77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isStatusKnown() const;
78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool exists() const;
79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// @}
80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Represents an open file.
83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass File {
84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Destroy the file after closing it (if open).
86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// Sub-classes should generally call close() inside their destructors.  We
87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// cannot do that from the base class, since close is virtual.
88651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  virtual ~File();
89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Get the status of the file.
90651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  virtual llvm::ErrorOr<Status> status() = 0;
91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Get the contents of the file as a \p MemoryBuffer.
92176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
93176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  getBuffer(const Twine &Name, int64_t FileSize = -1,
94176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines            bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Closes the file.
96c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  virtual std::error_code close() = 0;
97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Sets the name to use for this file.
98651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  virtual void setName(StringRef Name) = 0;
99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
100651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
101c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesnamespace detail {
102c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// \brief An interface for virtual file systems to provide an iterator over the
103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// (non-recursive) contents of a directory.
104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstruct DirIterImpl {
105c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  virtual ~DirIterImpl();
106c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Sets \c CurrentEntry to the next entry in the directory on success,
107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// or returns a system-defined \c error_code.
108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  virtual std::error_code increment() = 0;
109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Status CurrentEntry;
110c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
111c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines} // end namespace detail
112c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
113c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// \brief An input iterator over the entries in a virtual path, similar to
114c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// llvm::sys::fs::directory_iterator.
115c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass directory_iterator {
116c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
117c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
118c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic:
119c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  directory_iterator(std::shared_ptr<detail::DirIterImpl> I) : Impl(I) {
120c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Impl.get() != nullptr && "requires non-null implementation");
121c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (!Impl->CurrentEntry.isStatusKnown())
122c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Impl.reset(); // Normalize the end iterator to Impl == nullptr.
123c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
124c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Construct an 'end' iterator.
126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  directory_iterator() { }
127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
128c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Equivalent to operator++, with an error code.
129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  directory_iterator &increment(std::error_code &EC) {
130c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    assert(Impl && "attempting to increment past end");
131c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    EC = Impl->increment();
132c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (EC || !Impl->CurrentEntry.isStatusKnown())
133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Impl.reset(); // Normalize the end iterator to Impl == nullptr.
134c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return *this;
135c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
136c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
137c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  const Status &operator*() const { return Impl->CurrentEntry; }
138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  const Status *operator->() const { return &Impl->CurrentEntry; }
139c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
140c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool operator==(const directory_iterator &RHS) const {
141c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Impl && RHS.Impl)
142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry);
143c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return !Impl && !RHS.Impl;
144c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
145c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool operator!=(const directory_iterator &RHS) const {
146c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return !(*this == RHS);
147c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
148c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
149c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
150c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass FileSystem;
151c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
152c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// \brief An input iterator over the recursive contents of a virtual path,
153c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/// similar to llvm::sys::fs::recursive_directory_iterator.
154c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesclass recursive_directory_iterator {
155c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  typedef std::stack<directory_iterator, std::vector<directory_iterator>>
156c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      IterState;
157c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
158c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  FileSystem *FS;
159c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::shared_ptr<IterState> State; // Input iterator semantics on copy.
160c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
161c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinespublic:
162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  recursive_directory_iterator(FileSystem &FS, const Twine &Path,
163c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                               std::error_code &EC);
164c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Construct an 'end' iterator.
165c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  recursive_directory_iterator() { }
166c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
167c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Equivalent to operator++, with an error code.
168c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  recursive_directory_iterator &increment(std::error_code &EC);
169c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
170c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  const Status &operator*() const { return *State->top(); }
171c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  const Status *operator->() const { return &*State->top(); }
172c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
173c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool operator==(const recursive_directory_iterator &Other) const {
174c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return State == Other.State; // identity
175c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
176c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  bool operator!=(const recursive_directory_iterator &RHS) const {
177c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return !(*this == RHS);
178c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
179c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
180c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief The virtual file system interface.
182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  virtual ~FileSystem();
185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Get the status of the entry at \p Path, if one exists.
187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Get a \p File object for the file at \p Path, if one exists.
189176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  virtual llvm::ErrorOr<std::unique_ptr<File>>
190176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  openFileForRead(const Twine &Path) = 0;
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// This is a convenience method that opens a file, gets its content and then
193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// closes the file.
194176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
195176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  getBufferForFile(const Twine &Name, int64_t FileSize = -1,
196176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                   bool RequiresNullTerminator = true, bool IsVolatile = false);
197c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
198c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Get a directory_iterator for \p Dir.
199c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \note The 'end' iterator is directory_iterator().
200c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  virtual directory_iterator dir_begin(const Twine &Dir,
201c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                       std::error_code &EC) = 0;
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by
205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// the operating system.
206651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesIntrusiveRefCntPtr<FileSystem> getRealFileSystem();
207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief A file system that allows overlaying one \p AbstractFileSystem on top
209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// of another.
210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines///
211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// one merged file system. When there is a directory that exists in more than
213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// one file system, the \p OverlayFileSystem contains a directory containing
214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// the union of their contents.  The attributes (permissions, etc.) of the
215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// top-most (most recently added) directory are used.  When there is a file
216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// that exists in more than one file system, the file in the top-most file
217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// system overrides the other(s).
218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass OverlayFileSystem : public FileSystem {
219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  typedef SmallVector<IntrusiveRefCntPtr<FileSystem>, 1> FileSystemList;
220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief The stack of file systems, implemented as a list in order of
221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// their addition.
222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FileSystemList FSList;
223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base);
226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Pushes a file system on top of the stack.
227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::ErrorOr<Status> status(const Twine &Path) override;
230176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::ErrorOr<std::unique_ptr<File>>
231176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  openFileForRead(const Twine &Path) override;
232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
233c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  typedef FileSystemList::reverse_iterator iterator;
235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Get an iterator pointing to the most recently added file system.
237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  iterator overlays_begin() { return FSList.rbegin(); }
238c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
239c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// \brief Get an iterator pointing one-past the least recently added file
240c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  /// system.
241c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  iterator overlays_end() { return FSList.rend(); }
242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Get a globally unique ID for a virtual file or directory.
245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesllvm::sys::fs::UniqueID getNextVirtualUniqueID();
246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Gets a \p FileSystem for a virtual file system described in YAML
248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// format.
249651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesIntrusiveRefCntPtr<FileSystem>
250176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesgetVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines               llvm::SourceMgr::DiagHandlerTy DiagHandler,
2526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               void *DiagContext = nullptr,
253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines               IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstruct YAMLVFSEntry {
2566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  template <typename T1, typename T2> YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
2576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
2586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  std::string VPath;
2596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  std::string RPath;
2606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
2616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesclass YAMLVFSWriter {
2636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  std::vector<YAMLVFSEntry> Mappings;
2646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Optional<bool> IsCaseSensitive;
2656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
2676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  YAMLVFSWriter() {}
2686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void addFileMapping(StringRef VirtualPath, StringRef RealPath);
2696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void setCaseSensitivity(bool CaseSensitive) {
2706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    IsCaseSensitive = CaseSensitive;
2716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void write(llvm::raw_ostream &OS);
2736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
2746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} // end namespace vfs
276651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} // end namespace clang
277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#endif
278