LLVM  9.0.0svn
VirtualFileSystem.h
Go to the documentation of this file.
1 //===- VirtualFileSystem.h - Virtual File System Layer ----------*- 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 /// \file
10 /// Defines the virtual file system interface vfs::FileSystem.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_SUPPORT_VIRTUALFILESYSTEM_H
15 #define LLVM_SUPPORT_VIRTUALFILESYSTEM_H
16 
18 #include "llvm/ADT/None.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/Support/Chrono.h"
24 #include "llvm/Support/ErrorOr.h"
26 #include "llvm/Support/Path.h"
27 #include "llvm/Support/SourceMgr.h"
28 #include <cassert>
29 #include <cstdint>
30 #include <ctime>
31 #include <memory>
32 #include <stack>
33 #include <string>
34 #include <system_error>
35 #include <utility>
36 #include <vector>
37 
38 namespace llvm {
39 
40 class MemoryBuffer;
41 
42 namespace vfs {
43 
44 /// The result of a \p status operation.
45 class Status {
46  std::string Name;
49  uint32_t User;
50  uint32_t Group;
51  uint64_t Size;
54 
55 public:
56  // FIXME: remove when files support multiple names
57  bool IsVFSMapped = false;
58 
59  Status() = default;
61  Status(const Twine &Name, llvm::sys::fs::UniqueID UID,
62  llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
63  uint64_t Size, llvm::sys::fs::file_type Type,
64  llvm::sys::fs::perms Perms);
65 
66  /// Get a copy of a Status with a different name.
67  static Status copyWithNewName(const Status &In, const Twine &NewName);
69  const Twine &NewName);
70 
71  /// Returns the name that should be used for this file or directory.
72  StringRef getName() const { return Name; }
73 
74  /// @name Status interface from llvm::sys::fs
75  /// @{
76  llvm::sys::fs::file_type getType() const { return Type; }
77  llvm::sys::fs::perms getPermissions() const { return Perms; }
79  llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
80  uint32_t getUser() const { return User; }
81  uint32_t getGroup() const { return Group; }
82  uint64_t getSize() const { return Size; }
83  /// @}
84  /// @name Status queries
85  /// These are static queries in llvm::sys::fs.
86  /// @{
87  bool equivalent(const Status &Other) const;
88  bool isDirectory() const;
89  bool isRegularFile() const;
90  bool isOther() const;
91  bool isSymlink() const;
92  bool isStatusKnown() const;
93  bool exists() const;
94  /// @}
95 };
96 
97 /// Represents an open file.
98 class File {
99 public:
100  /// Destroy the file after closing it (if open).
101  /// Sub-classes should generally call close() inside their destructors. We
102  /// cannot do that from the base class, since close is virtual.
103  virtual ~File();
104 
105  /// Get the status of the file.
106  virtual llvm::ErrorOr<Status> status() = 0;
107 
108  /// Get the name of the file
110  if (auto Status = status())
111  return Status->getName().str();
112  else
113  return Status.getError();
114  }
115 
116  /// Get the contents of the file as a \p MemoryBuffer.
118  getBuffer(const Twine &Name, int64_t FileSize = -1,
119  bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
120 
121  /// Closes the file.
122  virtual std::error_code close() = 0;
123 };
124 
125 /// A member of a directory, yielded by a directory_iterator.
126 /// Only information available on most platforms is included.
128  std::string Path;
130 
131 public:
132  directory_entry() = default;
134  : Path(std::move(Path)), Type(Type) {}
135 
136  llvm::StringRef path() const { return Path; }
137  llvm::sys::fs::file_type type() const { return Type; }
138 };
139 
140 namespace detail {
141 
142 /// An interface for virtual file systems to provide an iterator over the
143 /// (non-recursive) contents of a directory.
144 struct DirIterImpl {
145  virtual ~DirIterImpl();
146 
147  /// Sets \c CurrentEntry to the next entry in the directory on success,
148  /// to directory_entry() at end, or returns a system-defined \c error_code.
149  virtual std::error_code increment() = 0;
150 
152 };
153 
154 } // namespace detail
155 
156 /// An input iterator over the entries in a virtual path, similar to
157 /// llvm::sys::fs::directory_iterator.
159  std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
160 
161 public:
162  directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
163  : Impl(std::move(I)) {
164  assert(Impl.get() != nullptr && "requires non-null implementation");
165  if (Impl->CurrentEntry.path().empty())
166  Impl.reset(); // Normalize the end iterator to Impl == nullptr.
167  }
168 
169  /// Construct an 'end' iterator.
170  directory_iterator() = default;
171 
172  /// Equivalent to operator++, with an error code.
173  directory_iterator &increment(std::error_code &EC) {
174  assert(Impl && "attempting to increment past end");
175  EC = Impl->increment();
176  if (Impl->CurrentEntry.path().empty())
177  Impl.reset(); // Normalize the end iterator to Impl == nullptr.
178  return *this;
179  }
180 
181  const directory_entry &operator*() const { return Impl->CurrentEntry; }
182  const directory_entry *operator->() const { return &Impl->CurrentEntry; }
183 
184  bool operator==(const directory_iterator &RHS) const {
185  if (Impl && RHS.Impl)
186  return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path();
187  return !Impl && !RHS.Impl;
188  }
189  bool operator!=(const directory_iterator &RHS) const {
190  return !(*this == RHS);
191  }
192 };
193 
194 class FileSystem;
195 
196 namespace detail {
197 
198 /// Keeps state for the recursive_directory_iterator.
200  std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
201  bool HasNoPushRequest = false;
202 };
203 
204 } // end namespace detail
205 
206 /// An input iterator over the recursive contents of a virtual path,
207 /// similar to llvm::sys::fs::recursive_directory_iterator.
209  FileSystem *FS;
210  std::shared_ptr<detail::RecDirIterState>
211  State; // Input iterator semantics on copy.
212 
213 public:
215  std::error_code &EC);
216 
217  /// Construct an 'end' iterator.
218  recursive_directory_iterator() = default;
219 
220  /// Equivalent to operator++, with an error code.
221  recursive_directory_iterator &increment(std::error_code &EC);
222 
223  const directory_entry &operator*() const { return *State->Stack.top(); }
224  const directory_entry *operator->() const { return &*State->Stack.top(); }
225 
226  bool operator==(const recursive_directory_iterator &Other) const {
227  return State == Other.State; // identity
228  }
229  bool operator!=(const recursive_directory_iterator &RHS) const {
230  return !(*this == RHS);
231  }
232 
233  /// Gets the current level. Starting path is at level 0.
234  int level() const {
235  assert(!State->Stack.empty() &&
236  "Cannot get level without any iteration state");
237  return State->Stack.size() - 1;
238  }
239 
240  void no_push() { State->HasNoPushRequest = true; }
241 };
242 
243 /// The virtual file system interface.
244 class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
245 public:
246  virtual ~FileSystem();
247 
248  /// Get the status of the entry at \p Path, if one exists.
249  virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
250 
251  /// Get a \p File object for the file at \p Path, if one exists.
253  openFileForRead(const Twine &Path) = 0;
254 
255  /// This is a convenience method that opens a file, gets its content and then
256  /// closes the file.
258  getBufferForFile(const Twine &Name, int64_t FileSize = -1,
259  bool RequiresNullTerminator = true, bool IsVolatile = false);
260 
261  /// Get a directory_iterator for \p Dir.
262  /// \note The 'end' iterator is directory_iterator().
263  virtual directory_iterator dir_begin(const Twine &Dir,
264  std::error_code &EC) = 0;
265 
266  /// Set the working directory. This will affect all following operations on
267  /// this file system and may propagate down for nested file systems.
268  virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
269 
270  /// Get the working directory of this file system.
271  virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
272 
273  /// Gets real path of \p Path e.g. collapse all . and .. patterns, resolve
274  /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`.
275  /// This returns errc::operation_not_permitted if not implemented by subclass.
276  virtual std::error_code getRealPath(const Twine &Path,
277  SmallVectorImpl<char> &Output) const;
278 
279  /// Check whether a file exists. Provided for convenience.
280  bool exists(const Twine &Path);
281 
282  /// Is the file mounted on a local filesystem?
283  virtual std::error_code isLocal(const Twine &Path, bool &Result);
284 
285  /// Make \a Path an absolute path.
286  ///
287  /// Makes \a Path absolute using the current directory if it is not already.
288  /// An empty \a Path will result in the current directory.
289  ///
290  /// /absolute/path => /absolute/path
291  /// relative/../path => <current-directory>/relative/../path
292  ///
293  /// \param Path A path that is modified to be an absolute path.
294  /// \returns success if \a path has been made absolute, otherwise a
295  /// platform-specific error_code.
296  std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
297 };
298 
299 /// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
300 /// the operating system.
301 /// The working directory is linked to the process's working directory.
302 /// (This is usually thread-hostile).
304 
305 /// Create an \p vfs::FileSystem for the 'real' file system, as seen by
306 /// the operating system.
307 /// It has its own working directory, independent of (but initially equal to)
308 /// that of the process.
309 std::unique_ptr<FileSystem> createPhysicalFileSystem();
310 
311 /// A file system that allows overlaying one \p AbstractFileSystem on top
312 /// of another.
313 ///
314 /// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
315 /// one merged file system. When there is a directory that exists in more than
316 /// one file system, the \p OverlayFileSystem contains a directory containing
317 /// the union of their contents. The attributes (permissions, etc.) of the
318 /// top-most (most recently added) directory are used. When there is a file
319 /// that exists in more than one file system, the file in the top-most file
320 /// system overrides the other(s).
323 
324  /// The stack of file systems, implemented as a list in order of
325  /// their addition.
326  FileSystemList FSList;
327 
328 public:
330 
331  /// Pushes a file system on top of the stack.
332  void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
333 
334  llvm::ErrorOr<Status> status(const Twine &Path) override;
336  openFileForRead(const Twine &Path) override;
337  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
338  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
339  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
340  std::error_code isLocal(const Twine &Path, bool &Result) override;
341  std::error_code getRealPath(const Twine &Path,
342  SmallVectorImpl<char> &Output) const override;
343 
346 
347  /// Get an iterator pointing to the most recently added file system.
348  iterator overlays_begin() { return FSList.rbegin(); }
349  const_iterator overlays_begin() const { return FSList.rbegin(); }
350 
351  /// Get an iterator pointing one-past the least recently added file
352  /// system.
353  iterator overlays_end() { return FSList.rend(); }
354  const_iterator overlays_end() const { return FSList.rend(); }
355 };
356 
357 /// By default, this delegates all calls to the underlying file system. This
358 /// is useful when derived file systems want to override some calls and still
359 /// proxy other calls.
360 class ProxyFileSystem : public FileSystem {
361 public:
363  : FS(std::move(FS)) {}
364 
365  llvm::ErrorOr<Status> status(const Twine &Path) override {
366  return FS->status(Path);
367  }
369  openFileForRead(const Twine &Path) override {
370  return FS->openFileForRead(Path);
371  }
372  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
373  return FS->dir_begin(Dir, EC);
374  }
376  return FS->getCurrentWorkingDirectory();
377  }
378  std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
379  return FS->setCurrentWorkingDirectory(Path);
380  }
381  std::error_code getRealPath(const Twine &Path,
382  SmallVectorImpl<char> &Output) const override {
383  return FS->getRealPath(Path, Output);
384  }
385  std::error_code isLocal(const Twine &Path, bool &Result) override {
386  return FS->isLocal(Path, Result);
387  }
388 
389 protected:
390  FileSystem &getUnderlyingFS() { return *FS; }
391 
392 private:
394 
395  virtual void anchor();
396 };
397 
398 namespace detail {
399 
400 class InMemoryDirectory;
401 class InMemoryFile;
402 
403 } // namespace detail
404 
405 /// An in-memory file system.
407  std::unique_ptr<detail::InMemoryDirectory> Root;
408  std::string WorkingDirectory;
409  bool UseNormalizedPaths = true;
410 
411  /// If HardLinkTarget is non-null, a hardlink is created to the To path which
412  /// must be a file. If it is null then it adds the file as the public addFile.
413  bool addFile(const Twine &Path, time_t ModificationTime,
414  std::unique_ptr<llvm::MemoryBuffer> Buffer,
418  const detail::InMemoryFile *HardLinkTarget);
419 
420 public:
421  explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
422  ~InMemoryFileSystem() override;
423 
424  /// Add a file containing a buffer or a directory to the VFS with a
425  /// path. The VFS owns the buffer. If present, User, Group, Type
426  /// and Perms apply to the newly-created file or directory.
427  /// \return true if the file or directory was successfully added,
428  /// false if the file or directory already exists in the file system with
429  /// different contents.
430  bool addFile(const Twine &Path, time_t ModificationTime,
431  std::unique_ptr<llvm::MemoryBuffer> Buffer,
435 
436  /// Add a hard link to a file.
437  /// Here hard links are not intended to be fully equivalent to the classical
438  /// filesystem. Both the hard link and the file share the same buffer and
439  /// status (and thus have the same UniqueID). Because of this there is no way
440  /// to distinguish between the link and the file after the link has been
441  /// added.
442  ///
443  /// The To path must be an existing file or a hardlink. The From file must not
444  /// have been added before. The To Path must not be a directory. The From Node
445  /// is added as a hard link which points to the resolved file of To Node.
446  /// \return true if the above condition is satisfied and hardlink was
447  /// successfully created, false otherwise.
448  bool addHardLink(const Twine &From, const Twine &To);
449 
450  /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
451  /// If present, User, Group, Type and Perms apply to the newly-created file
452  /// or directory.
453  /// \return true if the file or directory was successfully added,
454  /// false if the file or directory already exists in the file system with
455  /// different contents.
456  bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
458  Optional<uint32_t> Group = None,
461 
462  std::string toString() const;
463 
464  /// Return true if this file system normalizes . and .. in paths.
465  bool useNormalizedPaths() const { return UseNormalizedPaths; }
466 
467  llvm::ErrorOr<Status> status(const Twine &Path) override;
469  openFileForRead(const Twine &Path) override;
470  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
471 
473  return WorkingDirectory;
474  }
475  /// Canonicalizes \p Path by combining with the current working
476  /// directory and normalizing the path (e.g. remove dots). If the current
477  /// working directory is not set, this returns errc::operation_not_permitted.
478  ///
479  /// This doesn't resolve symlinks as they are not supported in in-memory file
480  /// system.
481  std::error_code getRealPath(const Twine &Path,
482  SmallVectorImpl<char> &Output) const override;
483  std::error_code isLocal(const Twine &Path, bool &Result) override;
484  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
485 };
486 
487 /// Get a globally unique ID for a virtual file or directory.
489 
490 /// Gets a \p FileSystem for a virtual file system described in YAML
491 /// format.
493 getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
495  StringRef YAMLFilePath, void *DiagContext = nullptr,
497 
498 struct YAMLVFSEntry {
499  template <typename T1, typename T2>
500  YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
501  : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
502  std::string VPath;
503  std::string RPath;
504 };
505 
508 
509 /// A virtual file system parsed from a YAML file.
510 ///
511 /// Currently, this class allows creating virtual directories and mapping
512 /// virtual file paths to existing external files, available in \c ExternalFS.
513 ///
514 /// The basic structure of the parsed file is:
515 /// \verbatim
516 /// {
517 /// 'version': <version number>,
518 /// <optional configuration>
519 /// 'roots': [
520 /// <directory entries>
521 /// ]
522 /// }
523 /// \endverbatim
524 ///
525 /// All configuration options are optional.
526 /// 'case-sensitive': <boolean, default=true>
527 /// 'use-external-names': <boolean, default=true>
528 /// 'overlay-relative': <boolean, default=false>
529 /// 'fallthrough': <boolean, default=true>
530 ///
531 /// Virtual directories are represented as
532 /// \verbatim
533 /// {
534 /// 'type': 'directory',
535 /// 'name': <string>,
536 /// 'contents': [ <file or directory entries> ]
537 /// }
538 /// \endverbatim
539 ///
540 /// The default attributes for virtual directories are:
541 /// \verbatim
542 /// MTime = now() when created
543 /// Perms = 0777
544 /// User = Group = 0
545 /// Size = 0
546 /// UniqueID = unspecified unique value
547 /// \endverbatim
548 ///
549 /// Re-mapped files are represented as
550 /// \verbatim
551 /// {
552 /// 'type': 'file',
553 /// 'name': <string>,
554 /// 'use-external-name': <boolean> # Optional
555 /// 'external-contents': <path to external file>
556 /// }
557 /// \endverbatim
558 ///
559 /// and inherit their attributes from the external contents.
560 ///
561 /// In both cases, the 'name' field may contain multiple path components (e.g.
562 /// /path/to/file). However, any directory that contains more than one child
563 /// must be uniquely represented by a directory entry.
565 public:
566  enum EntryKind { EK_Directory, EK_File };
567 
568  /// A single file or directory in the VFS.
569  class Entry {
570  EntryKind Kind;
571  std::string Name;
572 
573  public:
574  Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
575  virtual ~Entry() = default;
576 
577  StringRef getName() const { return Name; }
578  EntryKind getKind() const { return Kind; }
579  };
580 
582  std::vector<std::unique_ptr<Entry>> Contents;
583  Status S;
584 
585  public:
587  std::vector<std::unique_ptr<Entry>> Contents,
588  Status S)
589  : Entry(EK_Directory, Name), Contents(std::move(Contents)),
590  S(std::move(S)) {}
592  : Entry(EK_Directory, Name), S(std::move(S)) {}
593 
594  Status getStatus() { return S; }
595 
596  void addContent(std::unique_ptr<Entry> Content) {
597  Contents.push_back(std::move(Content));
598  }
599 
600  Entry *getLastContent() const { return Contents.back().get(); }
601 
602  using iterator = decltype(Contents)::iterator;
603 
604  iterator contents_begin() { return Contents.begin(); }
605  iterator contents_end() { return Contents.end(); }
606 
607  static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
608  };
609 
610  class RedirectingFileEntry : public Entry {
611  public:
612  enum NameKind { NK_NotSet, NK_External, NK_Virtual };
613 
614  private:
615  std::string ExternalContentsPath;
616  NameKind UseName;
617 
618  public:
619  RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
620  NameKind UseName)
621  : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
622  UseName(UseName) {}
623 
624  StringRef getExternalContentsPath() const { return ExternalContentsPath; }
625 
626  /// whether to use the external path as the name for this file.
627  bool useExternalName(bool GlobalUseExternalName) const {
628  return UseName == NK_NotSet ? GlobalUseExternalName
629  : (UseName == NK_External);
630  }
631 
632  NameKind getUseName() const { return UseName; }
633 
634  static bool classof(const Entry *E) { return E->getKind() == EK_File; }
635  };
636 
637 private:
640 
641  /// The root(s) of the virtual file system.
642  std::vector<std::unique_ptr<Entry>> Roots;
643 
644  /// The file system to use for external references.
646 
647  /// If IsRelativeOverlay is set, this represents the directory
648  /// path that should be prefixed to each 'external-contents' entry
649  /// when reading from YAML files.
650  std::string ExternalContentsPrefixDir;
651 
652  /// @name Configuration
653  /// @{
654 
655  /// Whether to perform case-sensitive comparisons.
656  ///
657  /// Currently, case-insensitive matching only works correctly with ASCII.
658  bool CaseSensitive = true;
659 
660  /// IsRelativeOverlay marks whether a ExternalContentsPrefixDir path must
661  /// be prefixed in every 'external-contents' when reading from YAML files.
662  bool IsRelativeOverlay = false;
663 
664  /// Whether to use to use the value of 'external-contents' for the
665  /// names of files. This global value is overridable on a per-file basis.
666  bool UseExternalNames = true;
667 
668  /// Whether to attempt a file lookup in external file system after it wasn't
669  /// found in VFS.
670  bool IsFallthrough = true;
671  /// @}
672 
673  /// Virtual file paths and external files could be canonicalized without "..",
674  /// "." and "./" in their paths. FIXME: some unittests currently fail on
675  /// win32 when using remove_dots and remove_leading_dotslash on paths.
676  bool UseCanonicalizedPaths =
677 #ifdef _WIN32
678  false;
679 #else
680  true;
681 #endif
682 
684  : ExternalFS(std::move(ExternalFS)) {}
685 
686  /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
687  /// recursing into the contents of \p From if it is a directory.
690  Entry *From) const;
691 
692  /// Get the status of a given an \c Entry.
693  ErrorOr<Status> status(const Twine &Path, Entry *E);
694 
695 public:
696  /// Looks up \p Path in \c Roots.
697  ErrorOr<Entry *> lookupPath(const Twine &Path) const;
698 
699  /// Parses \p Buffer, which is expected to be in YAML format and
700  /// returns a virtual file system representing its contents.
701  static RedirectingFileSystem *
702  create(std::unique_ptr<MemoryBuffer> Buffer,
703  SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
704  void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
705 
706  ErrorOr<Status> status(const Twine &Path) override;
707  ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
708 
709  std::error_code getRealPath(const Twine &Path,
710  SmallVectorImpl<char> &Output) const override;
711 
712  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
713 
714  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
715 
716  std::error_code isLocal(const Twine &Path, bool &Result) override;
717 
718  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
719 
720  void setExternalContentsPrefixDir(StringRef PrefixDir);
721 
722  StringRef getExternalContentsPrefixDir() const;
723 
724 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
725  LLVM_DUMP_METHOD void dump() const;
726  LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const;
727 #endif
728 };
729 
730 /// Collect all pairs of <virtual path, real path> entries from the
731 /// \p YAMLFilePath. This is used by the module dependency collector to forward
732 /// the entries into the reproducer output VFS YAML file.
733 void collectVFSFromYAML(
734  std::unique_ptr<llvm::MemoryBuffer> Buffer,
735  llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
736  SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
737  void *DiagContext = nullptr,
739 
741  std::vector<YAMLVFSEntry> Mappings;
742  Optional<bool> IsCaseSensitive;
743  Optional<bool> IsOverlayRelative;
744  Optional<bool> UseExternalNames;
745  std::string OverlayDir;
746 
747 public:
748  YAMLVFSWriter() = default;
749 
750  void addFileMapping(StringRef VirtualPath, StringRef RealPath);
751 
752  void setCaseSensitivity(bool CaseSensitive) {
753  IsCaseSensitive = CaseSensitive;
754  }
755 
756  void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
757 
758  void setOverlayDir(StringRef OverlayDirectory) {
759  IsOverlayRelative = true;
760  OverlayDir.assign(OverlayDirectory.str());
761  }
762 
763  const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
764 
765  void write(llvm::raw_ostream &OS);
766 };
767 
768 } // namespace vfs
769 } // namespace llvm
770 
771 #endif // LLVM_SUPPORT_VIRTUALFILESYSTEM_H
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
const NoneType None
Definition: None.h:23
const directory_entry * operator->() const
const directory_entry & operator*() const
A file system that allows overlaying one AbstractFileSystem on top of another.
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: SmallVector.h:118
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
llvm::StringRef path() const
Represents either an error or a value T.
Definition: ErrorOr.h:56
RedirectingDirectoryEntry(StringRef Name, std::vector< std::unique_ptr< Entry >> Contents, Status S)
const directory_entry & operator*() const
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:218
bool operator==(const directory_iterator &RHS) const
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the &#39;real&#39; file system, as seen by the operating system.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds...
Definition: Compiler.h:464
ProxyFileSystem(IntrusiveRefCntPtr< FileSystem > FS)
FileSystemList::reverse_iterator iterator
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
directory_entry(std::string Path, llvm::sys::fs::file_type Type)
uint32_t getUser() const
const std::vector< YAMLVFSEntry > & getMappings() const
llvm::sys::fs::file_type type() const
The result of a status operation.
FileSystemList::const_reverse_iterator const_iterator
Entry(EntryKind K, StringRef Name)
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:246
Represents an open file.
bool useExternalName(bool GlobalUseExternalName) const
whether to use the external path as the name for this file.
int level() const
Gets the current level. Starting path is at level 0.
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Definition: BitVector.h:937
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:966
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
StringRef getName() const
Returns the name that should be used for this file or directory.
static Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:611
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:838
const_iterator overlays_begin() const
void setCaseSensitivity(bool CaseSensitive)
bool operator==(const recursive_directory_iterator &Other) const
RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
llvm::sys::fs::file_type getType() const
llvm::sys::TimePoint getLastModificationTime() const
bool isRegularFile() const
A virtual file system parsed from a YAML file.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::sys::fs::perms getPermissions() const
std::reverse_iterator< iterator > reverse_iterator
Definition: SmallVector.h:119
std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the &#39;real&#39; file system, as seen by the operating system.
A single file or directory in the VFS.
Keeps state for the recursive_directory_iterator.
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition: SourceMgr.h:53
By default, this delegates all calls to the underlying file system.
static void write(bool isBE, void *P, T V)
bool isStatusKnown() const
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
A member of a directory, yielded by a directory_iterator.
virtual llvm::ErrorOr< std::string > getName()
Get the name of the file.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
uint64_t getSize() const
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
BlockVerifier::State From
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
bool equivalent(const Status &Other) const
void setUseExternalNames(bool UseExtNames)
The virtual file system interface.
const directory_entry * operator->() const
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:41
uint32_t getGroup() const
A thread-safe version of RefCountedBase.
An in-memory file system.
Path iterator.
Definition: Path.h:52
bool operator!=(const directory_iterator &RHS) const
IntrusiveRefCntPtr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
file_type
An enumeration for the file system&#39;s view of the type.
Definition: FileSystem.h:66
#define I(x, y, z)
Definition: MD5.cpp:58
bool isDirectory() const
Provides ErrorOr<T> smart pointer.
std::stack< directory_iterator, std::vector< directory_iterator > > Stack
void collectVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Collect all pairs of <virtual path, real path> entries from the YAMLFilePath.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A helper class to hold the common YAML parsing state.
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
llvm::sys::fs::UniqueID getUniqueID() const
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
bool operator!=(const recursive_directory_iterator &RHS) const
void setOverlayDir(StringRef OverlayDirectory)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
const_iterator overlays_end() const
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
#define T1
directory_iterator(std::shared_ptr< detail::DirIterImpl > I)
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition: Chrono.h:33
llvm::ErrorOr< Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.