clang  3.7.0
VirtualFileSystem.h
Go to the documentation of this file.
1 //===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// \brief Defines the virtual file system interface vfs::FileSystem.
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
14 #define LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
15 
16 #include "clang/Basic/LLVM.h"
17 #include "llvm/ADT/IntrusiveRefCntPtr.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/Support/ErrorOr.h"
20 #include "llvm/Support/FileSystem.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/raw_ostream.h"
23 
24 namespace llvm {
25 class MemoryBuffer;
26 }
27 
28 namespace clang {
29 namespace vfs {
30 
31 /// \brief The result of a \p status operation.
32 class Status {
33  std::string Name;
34  llvm::sys::fs::UniqueID UID;
35  llvm::sys::TimeValue MTime;
36  uint32_t User;
37  uint32_t Group;
38  uint64_t Size;
39  llvm::sys::fs::file_type Type;
40  llvm::sys::fs::perms Perms;
41 
42 public:
43  bool IsVFSMapped; // FIXME: remove when files support multiple names
44 
45 public:
46  Status() : Type(llvm::sys::fs::file_type::status_error) {}
47  Status(const llvm::sys::fs::file_status &Status);
48  Status(StringRef Name, StringRef RealName, llvm::sys::fs::UniqueID UID,
49  llvm::sys::TimeValue MTime, uint32_t User, uint32_t Group,
50  uint64_t Size, llvm::sys::fs::file_type Type,
51  llvm::sys::fs::perms Perms);
52 
53  /// \brief Returns the name that should be used for this file or directory.
54  StringRef getName() const { return Name; }
55  void setName(StringRef N) { Name = N; }
56 
57  /// @name Status interface from llvm::sys::fs
58  /// @{
59  llvm::sys::fs::file_type getType() const { return Type; }
60  llvm::sys::fs::perms getPermissions() const { return Perms; }
61  llvm::sys::TimeValue getLastModificationTime() const { return MTime; }
62  llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
63  uint32_t getUser() const { return User; }
64  uint32_t getGroup() const { return Group; }
65  uint64_t getSize() const { return Size; }
66  void setType(llvm::sys::fs::file_type v) { Type = v; }
67  void setPermissions(llvm::sys::fs::perms p) { Perms = p; }
68  /// @}
69  /// @name Status queries
70  /// These are static queries in llvm::sys::fs.
71  /// @{
72  bool equivalent(const Status &Other) const;
73  bool isDirectory() const;
74  bool isRegularFile() const;
75  bool isOther() const;
76  bool isSymlink() const;
77  bool isStatusKnown() const;
78  bool exists() const;
79  /// @}
80 };
81 
82 /// \brief Represents an open file.
83 class File {
84 public:
85  /// \brief Destroy the file after closing it (if open).
86  /// Sub-classes should generally call close() inside their destructors. We
87  /// cannot do that from the base class, since close is virtual.
88  virtual ~File();
89  /// \brief Get the status of the file.
90  virtual llvm::ErrorOr<Status> status() = 0;
91  /// \brief Get the contents of the file as a \p MemoryBuffer.
92  virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
93  getBuffer(const Twine &Name, int64_t FileSize = -1,
94  bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
95  /// \brief Closes the file.
96  virtual std::error_code close() = 0;
97  /// \brief Sets the name to use for this file.
98  virtual void setName(StringRef Name) = 0;
99 };
100 
101 namespace detail {
102 /// \brief An interface for virtual file systems to provide an iterator over the
103 /// (non-recursive) contents of a directory.
104 struct DirIterImpl {
105  virtual ~DirIterImpl();
106  /// \brief Sets \c CurrentEntry to the next entry in the directory on success,
107  /// or returns a system-defined \c error_code.
108  virtual std::error_code increment() = 0;
110 };
111 } // end namespace detail
112 
113 /// \brief An input iterator over the entries in a virtual path, similar to
114 /// llvm::sys::fs::directory_iterator.
116  std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
117 
118 public:
119  directory_iterator(std::shared_ptr<detail::DirIterImpl> I) : Impl(I) {
120  assert(Impl.get() != nullptr && "requires non-null implementation");
121  if (!Impl->CurrentEntry.isStatusKnown())
122  Impl.reset(); // Normalize the end iterator to Impl == nullptr.
123  }
124 
125  /// \brief Construct an 'end' iterator.
127 
128  /// \brief Equivalent to operator++, with an error code.
129  directory_iterator &increment(std::error_code &EC) {
130  assert(Impl && "attempting to increment past end");
131  EC = Impl->increment();
132  if (EC || !Impl->CurrentEntry.isStatusKnown())
133  Impl.reset(); // Normalize the end iterator to Impl == nullptr.
134  return *this;
135  }
136 
137  const Status &operator*() const { return Impl->CurrentEntry; }
138  const Status *operator->() const { return &Impl->CurrentEntry; }
139 
140  bool operator==(const directory_iterator &RHS) const {
141  if (Impl && RHS.Impl)
142  return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry);
143  return !Impl && !RHS.Impl;
144  }
145  bool operator!=(const directory_iterator &RHS) const {
146  return !(*this == RHS);
147  }
148 };
149 
150 class FileSystem;
151 
152 /// \brief An input iterator over the recursive contents of a virtual path,
153 /// similar to llvm::sys::fs::recursive_directory_iterator.
155  typedef std::stack<directory_iterator, std::vector<directory_iterator>>
156  IterState;
157 
158  FileSystem *FS;
159  std::shared_ptr<IterState> State; // Input iterator semantics on copy.
160 
161 public:
162  recursive_directory_iterator(FileSystem &FS, const Twine &Path,
163  std::error_code &EC);
164  /// \brief Construct an 'end' iterator.
166 
167  /// \brief Equivalent to operator++, with an error code.
168  recursive_directory_iterator &increment(std::error_code &EC);
169 
170  const Status &operator*() const { return *State->top(); }
171  const Status *operator->() const { return &*State->top(); }
172 
173  bool operator==(const recursive_directory_iterator &Other) const {
174  return State == Other.State; // identity
175  }
176  bool operator!=(const recursive_directory_iterator &RHS) const {
177  return !(*this == RHS);
178  }
179 };
180 
181 /// \brief The virtual file system interface.
182 class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
183 public:
184  virtual ~FileSystem();
185 
186  /// \brief Get the status of the entry at \p Path, if one exists.
187  virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
188  /// \brief Get a \p File object for the file at \p Path, if one exists.
189  virtual llvm::ErrorOr<std::unique_ptr<File>>
190  openFileForRead(const Twine &Path) = 0;
191 
192  /// This is a convenience method that opens a file, gets its content and then
193  /// closes the file.
194  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
195  getBufferForFile(const Twine &Name, int64_t FileSize = -1,
196  bool RequiresNullTerminator = true, bool IsVolatile = false);
197 
198  /// \brief Get a directory_iterator for \p Dir.
199  /// \note The 'end' iterator is directory_iterator().
200  virtual directory_iterator dir_begin(const Twine &Dir,
201  std::error_code &EC) = 0;
202 };
203 
204 /// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by
205 /// the operating system.
207 
208 /// \brief A file system that allows overlaying one \p AbstractFileSystem on top
209 /// of another.
210 ///
211 /// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
212 /// one merged file system. When there is a directory that exists in more than
213 /// one file system, the \p OverlayFileSystem contains a directory containing
214 /// the union of their contents. The attributes (permissions, etc.) of the
215 /// top-most (most recently added) directory are used. When there is a file
216 /// that exists in more than one file system, the file in the top-most file
217 /// system overrides the other(s).
220  /// \brief The stack of file systems, implemented as a list in order of
221  /// their addition.
222  FileSystemList FSList;
223 
224 public:
226  /// \brief Pushes a file system on top of the stack.
228 
229  llvm::ErrorOr<Status> status(const Twine &Path) override;
230  llvm::ErrorOr<std::unique_ptr<File>>
231  openFileForRead(const Twine &Path) override;
232  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
233 
234  typedef FileSystemList::reverse_iterator iterator;
235 
236  /// \brief Get an iterator pointing to the most recently added file system.
237  iterator overlays_begin() { return FSList.rbegin(); }
238 
239  /// \brief Get an iterator pointing one-past the least recently added file
240  /// system.
241  iterator overlays_end() { return FSList.rend(); }
242 };
243 
244 /// \brief Get a globally unique ID for a virtual file or directory.
245 llvm::sys::fs::UniqueID getNextVirtualUniqueID();
246 
247 /// \brief Gets a \p FileSystem for a virtual file system described in YAML
248 /// format.
250 getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
251  llvm::SourceMgr::DiagHandlerTy DiagHandler,
252  void *DiagContext = nullptr,
254 
255 struct YAMLVFSEntry {
256  template <typename T1, typename T2> YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
257  : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
258  std::string VPath;
259  std::string RPath;
260 };
261 
263  std::vector<YAMLVFSEntry> Mappings;
264  Optional<bool> IsCaseSensitive;
265 
266 public:
268  void addFileMapping(StringRef VirtualPath, StringRef RealPath);
269  void setCaseSensitivity(bool CaseSensitive) {
270  IsCaseSensitive = CaseSensitive;
271  }
272  void write(llvm::raw_ostream &OS);
273 };
274 
275 } // end namespace vfs
276 } // end namespace clang
277 #endif
virtual void setName(StringRef Name)=0
Sets the name to use for this file.
const Status * operator->() const
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
void setName(StringRef N)
virtual llvm::ErrorOr< Status > status()=0
Get the status of the file.
bool equivalent(const Status &Other) const
bool isStatusKnown() const
uint32_t getUser() const
llvm::sys::TimeValue getLastModificationTime() const
virtual llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBuffer(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)=0
Get the contents of the file as a MemoryBuffer.
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0
Get a File object for the file at Path, if one exists.
virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC)=0
Get a directory_iterator for Dir.
The virtual file system interface.
IntrusiveRefCntPtr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
void write(llvm::raw_ostream &OS)
virtual std::error_code close()=0
Closes the file.
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
directory_iterator(std::shared_ptr< detail::DirIterImpl > I)
directory_iterator()
Construct an 'end' iterator.
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
A file system that allows overlaying one AbstractFileSystem on top of another.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
llvm::sys::fs::file_type getType() const
void addFileMapping(StringRef VirtualPath, StringRef RealPath)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
bool operator!=(const recursive_directory_iterator &RHS) const
FileSystemList::reverse_iterator iterator
The result of a status operation.
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
recursive_directory_iterator()
Construct an 'end' iterator.
llvm::sys::fs::UniqueID getUniqueID() const
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
uint64_t getSize() const
Represents an open file.
void setType(llvm::sys::fs::file_type v)
void setCaseSensitivity(bool CaseSensitive)
do v
Definition: arm_acle.h:77
recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
bool operator!=(const directory_iterator &RHS) const
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
uint32_t getGroup() const
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
bool isDirectory() const
YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
static __inline__ uint32_t volatile uint32_t * p
Definition: arm_acle.h:75
bool isRegularFile() const
bool operator==(const directory_iterator &RHS) const
llvm::sys::fs::perms getPermissions() const
void setPermissions(llvm::sys::fs::perms p)
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
const Status & operator*() const
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
StringRef getName() const
Returns the name that should be used for this file or directory.
virtual ~File()
Destroy the file after closing it (if open). Sub-classes should generally call close() inside their d...
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
bool operator==(const recursive_directory_iterator &Other) const
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
virtual std::error_code increment()=0
Sets CurrentEntry to the next entry in the directory on success, or returns a system-defined error_co...