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