LLVM  10.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 
348 
349  /// Get an iterator pointing to the most recently added file system.
350  iterator overlays_begin() { return FSList.rbegin(); }
351  const_iterator overlays_begin() const { return FSList.rbegin(); }
352 
353  /// Get an iterator pointing one-past the least recently added file system.
354  iterator overlays_end() { return FSList.rend(); }
355  const_iterator overlays_end() const { return FSList.rend(); }
356 
357  /// Get an iterator pointing to the least recently added file system.
358  reverse_iterator overlays_rbegin() { return FSList.begin(); }
359  const_reverse_iterator overlays_rbegin() const { return FSList.begin(); }
360 
361  /// Get an iterator pointing one-past the most recently added file system.
362  reverse_iterator overlays_rend() { return FSList.end(); }
363  const_reverse_iterator overlays_rend() const { return FSList.end(); }
364 };
365 
366 /// By default, this delegates all calls to the underlying file system. This
367 /// is useful when derived file systems want to override some calls and still
368 /// proxy other calls.
369 class ProxyFileSystem : public FileSystem {
370 public:
372  : FS(std::move(FS)) {}
373 
374  llvm::ErrorOr<Status> status(const Twine &Path) override {
375  return FS->status(Path);
376  }
378  openFileForRead(const Twine &Path) override {
379  return FS->openFileForRead(Path);
380  }
381  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
382  return FS->dir_begin(Dir, EC);
383  }
385  return FS->getCurrentWorkingDirectory();
386  }
387  std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
388  return FS->setCurrentWorkingDirectory(Path);
389  }
390  std::error_code getRealPath(const Twine &Path,
391  SmallVectorImpl<char> &Output) const override {
392  return FS->getRealPath(Path, Output);
393  }
394  std::error_code isLocal(const Twine &Path, bool &Result) override {
395  return FS->isLocal(Path, Result);
396  }
397 
398 protected:
399  FileSystem &getUnderlyingFS() { return *FS; }
400 
401 private:
403 
404  virtual void anchor();
405 };
406 
407 namespace detail {
408 
409 class InMemoryDirectory;
410 class InMemoryFile;
411 
412 } // namespace detail
413 
414 /// An in-memory file system.
416  std::unique_ptr<detail::InMemoryDirectory> Root;
417  std::string WorkingDirectory;
418  bool UseNormalizedPaths = true;
419 
420  /// If HardLinkTarget is non-null, a hardlink is created to the To path which
421  /// must be a file. If it is null then it adds the file as the public addFile.
422  bool addFile(const Twine &Path, time_t ModificationTime,
423  std::unique_ptr<llvm::MemoryBuffer> Buffer,
427  const detail::InMemoryFile *HardLinkTarget);
428 
429 public:
430  explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
431  ~InMemoryFileSystem() override;
432 
433  /// Add a file containing a buffer or a directory to the VFS with a
434  /// path. The VFS owns the buffer. If present, User, Group, Type
435  /// and Perms apply to the newly-created file or directory.
436  /// \return true if the file or directory was successfully added,
437  /// false if the file or directory already exists in the file system with
438  /// different contents.
439  bool addFile(const Twine &Path, time_t ModificationTime,
440  std::unique_ptr<llvm::MemoryBuffer> Buffer,
444 
445  /// Add a hard link to a file.
446  /// Here hard links are not intended to be fully equivalent to the classical
447  /// filesystem. Both the hard link and the file share the same buffer and
448  /// status (and thus have the same UniqueID). Because of this there is no way
449  /// to distinguish between the link and the file after the link has been
450  /// added.
451  ///
452  /// The To path must be an existing file or a hardlink. The From file must not
453  /// have been added before. The To Path must not be a directory. The From Node
454  /// is added as a hard link which points to the resolved file of To Node.
455  /// \return true if the above condition is satisfied and hardlink was
456  /// successfully created, false otherwise.
457  bool addHardLink(const Twine &From, const Twine &To);
458 
459  /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
460  /// If present, User, Group, Type and Perms apply to the newly-created file
461  /// or directory.
462  /// \return true if the file or directory was successfully added,
463  /// false if the file or directory already exists in the file system with
464  /// different contents.
465  bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
467  Optional<uint32_t> Group = None,
470 
471  std::string toString() const;
472 
473  /// Return true if this file system normalizes . and .. in paths.
474  bool useNormalizedPaths() const { return UseNormalizedPaths; }
475 
476  llvm::ErrorOr<Status> status(const Twine &Path) override;
478  openFileForRead(const Twine &Path) override;
479  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
480 
482  return WorkingDirectory;
483  }
484  /// Canonicalizes \p Path by combining with the current working
485  /// directory and normalizing the path (e.g. remove dots). If the current
486  /// working directory is not set, this returns errc::operation_not_permitted.
487  ///
488  /// This doesn't resolve symlinks as they are not supported in in-memory file
489  /// system.
490  std::error_code getRealPath(const Twine &Path,
491  SmallVectorImpl<char> &Output) const override;
492  std::error_code isLocal(const Twine &Path, bool &Result) override;
493  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
494 };
495 
496 /// Get a globally unique ID for a virtual file or directory.
498 
499 /// Gets a \p FileSystem for a virtual file system described in YAML
500 /// format.
502 getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
504  StringRef YAMLFilePath, void *DiagContext = nullptr,
506 
507 struct YAMLVFSEntry {
508  template <typename T1, typename T2>
509  YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
510  : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
511  std::string VPath;
512  std::string RPath;
513 };
514 
517 
518 /// A virtual file system parsed from a YAML file.
519 ///
520 /// Currently, this class allows creating virtual directories and mapping
521 /// virtual file paths to existing external files, available in \c ExternalFS.
522 ///
523 /// The basic structure of the parsed file is:
524 /// \verbatim
525 /// {
526 /// 'version': <version number>,
527 /// <optional configuration>
528 /// 'roots': [
529 /// <directory entries>
530 /// ]
531 /// }
532 /// \endverbatim
533 ///
534 /// All configuration options are optional.
535 /// 'case-sensitive': <boolean, default=true>
536 /// 'use-external-names': <boolean, default=true>
537 /// 'overlay-relative': <boolean, default=false>
538 /// 'fallthrough': <boolean, default=true>
539 ///
540 /// Virtual directories are represented as
541 /// \verbatim
542 /// {
543 /// 'type': 'directory',
544 /// 'name': <string>,
545 /// 'contents': [ <file or directory entries> ]
546 /// }
547 /// \endverbatim
548 ///
549 /// The default attributes for virtual directories are:
550 /// \verbatim
551 /// MTime = now() when created
552 /// Perms = 0777
553 /// User = Group = 0
554 /// Size = 0
555 /// UniqueID = unspecified unique value
556 /// \endverbatim
557 ///
558 /// Re-mapped files are represented as
559 /// \verbatim
560 /// {
561 /// 'type': 'file',
562 /// 'name': <string>,
563 /// 'use-external-name': <boolean> # Optional
564 /// 'external-contents': <path to external file>
565 /// }
566 /// \endverbatim
567 ///
568 /// and inherit their attributes from the external contents.
569 ///
570 /// In both cases, the 'name' field may contain multiple path components (e.g.
571 /// /path/to/file). However, any directory that contains more than one child
572 /// must be uniquely represented by a directory entry.
574 public:
575  enum EntryKind { EK_Directory, EK_File };
576 
577  /// A single file or directory in the VFS.
578  class Entry {
579  EntryKind Kind;
580  std::string Name;
581 
582  public:
583  Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
584  virtual ~Entry() = default;
585 
586  StringRef getName() const { return Name; }
587  EntryKind getKind() const { return Kind; }
588  };
589 
591  std::vector<std::unique_ptr<Entry>> Contents;
592  Status S;
593 
594  public:
596  std::vector<std::unique_ptr<Entry>> Contents,
597  Status S)
598  : Entry(EK_Directory, Name), Contents(std::move(Contents)),
599  S(std::move(S)) {}
601  : Entry(EK_Directory, Name), S(std::move(S)) {}
602 
603  Status getStatus() { return S; }
604 
605  void addContent(std::unique_ptr<Entry> Content) {
606  Contents.push_back(std::move(Content));
607  }
608 
609  Entry *getLastContent() const { return Contents.back().get(); }
610 
611  using iterator = decltype(Contents)::iterator;
612 
613  iterator contents_begin() { return Contents.begin(); }
614  iterator contents_end() { return Contents.end(); }
615 
616  static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
617  };
618 
619  class RedirectingFileEntry : public Entry {
620  public:
621  enum NameKind { NK_NotSet, NK_External, NK_Virtual };
622 
623  private:
624  std::string ExternalContentsPath;
625  NameKind UseName;
626 
627  public:
628  RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
629  NameKind UseName)
630  : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
631  UseName(UseName) {}
632 
633  StringRef getExternalContentsPath() const { return ExternalContentsPath; }
634 
635  /// whether to use the external path as the name for this file.
636  bool useExternalName(bool GlobalUseExternalName) const {
637  return UseName == NK_NotSet ? GlobalUseExternalName
638  : (UseName == NK_External);
639  }
640 
641  NameKind getUseName() const { return UseName; }
642 
643  static bool classof(const Entry *E) { return E->getKind() == EK_File; }
644  };
645 
646 private:
649 
650  bool shouldUseExternalFS() const {
651  return ExternalFSValidWD && IsFallthrough;
652  }
653 
654  /// The root(s) of the virtual file system.
655  std::vector<std::unique_ptr<Entry>> Roots;
656 
657  /// The current working directory of the file system.
658  std::string WorkingDirectory;
659 
660  /// Whether the current working directory is valid for the external FS.
661  bool ExternalFSValidWD = false;
662 
663  /// The file system to use for external references.
665 
666  /// If IsRelativeOverlay is set, this represents the directory
667  /// path that should be prefixed to each 'external-contents' entry
668  /// when reading from YAML files.
669  std::string ExternalContentsPrefixDir;
670 
671  /// @name Configuration
672  /// @{
673 
674  /// Whether to perform case-sensitive comparisons.
675  ///
676  /// Currently, case-insensitive matching only works correctly with ASCII.
677  bool CaseSensitive = true;
678 
679  /// IsRelativeOverlay marks whether a ExternalContentsPrefixDir path must
680  /// be prefixed in every 'external-contents' when reading from YAML files.
681  bool IsRelativeOverlay = false;
682 
683  /// Whether to use to use the value of 'external-contents' for the
684  /// names of files. This global value is overridable on a per-file basis.
685  bool UseExternalNames = true;
686 
687  /// Whether to attempt a file lookup in external file system after it wasn't
688  /// found in VFS.
689  bool IsFallthrough = true;
690  /// @}
691 
692  /// Virtual file paths and external files could be canonicalized without "..",
693  /// "." and "./" in their paths. FIXME: some unittests currently fail on
694  /// win32 when using remove_dots and remove_leading_dotslash on paths.
695  bool UseCanonicalizedPaths =
696 #ifdef _WIN32
697  false;
698 #else
699  true;
700 #endif
701 
703 
704  /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
705  /// recursing into the contents of \p From if it is a directory.
708  Entry *From) const;
709 
710  /// Get the status of a given an \c Entry.
711  ErrorOr<Status> status(const Twine &Path, Entry *E);
712 
713 public:
714  /// Looks up \p Path in \c Roots.
715  ErrorOr<Entry *> lookupPath(const Twine &Path) const;
716 
717  /// Parses \p Buffer, which is expected to be in YAML format and
718  /// returns a virtual file system representing its contents.
719  static RedirectingFileSystem *
720  create(std::unique_ptr<MemoryBuffer> Buffer,
721  SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
722  void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
723 
724  ErrorOr<Status> status(const Twine &Path) override;
725  ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
726 
727  std::error_code getRealPath(const Twine &Path,
728  SmallVectorImpl<char> &Output) const override;
729 
730  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
731 
732  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
733 
734  std::error_code isLocal(const Twine &Path, bool &Result) override;
735 
736  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
737 
738  void setExternalContentsPrefixDir(StringRef PrefixDir);
739 
740  StringRef getExternalContentsPrefixDir() const;
741 
742  void dump(raw_ostream &OS) const;
743  void dumpEntry(raw_ostream &OS, Entry *E, int NumSpaces = 0) const;
744 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
745  LLVM_DUMP_METHOD void dump() const;
746 #endif
747 };
748 
749 /// Collect all pairs of <virtual path, real path> entries from the
750 /// \p YAMLFilePath. This is used by the module dependency collector to forward
751 /// the entries into the reproducer output VFS YAML file.
752 void collectVFSFromYAML(
753  std::unique_ptr<llvm::MemoryBuffer> Buffer,
754  llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
755  SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
756  void *DiagContext = nullptr,
758 
760  std::vector<YAMLVFSEntry> Mappings;
761  Optional<bool> IsCaseSensitive;
762  Optional<bool> IsOverlayRelative;
763  Optional<bool> UseExternalNames;
764  std::string OverlayDir;
765 
766 public:
767  YAMLVFSWriter() = default;
768 
769  void addFileMapping(StringRef VirtualPath, StringRef RealPath);
770 
771  void setCaseSensitivity(bool CaseSensitive) {
772  IsCaseSensitive = CaseSensitive;
773  }
774 
775  void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
776 
777  void setOverlayDir(StringRef OverlayDirectory) {
778  IsOverlayRelative = true;
779  OverlayDir.assign(OverlayDirectory.str());
780  }
781 
782  const std::vector<YAMLVFSEntry> &getMappings() const { return Mappings; }
783 
784  void write(llvm::raw_ostream &OS);
785 };
786 
787 } // namespace vfs
788 } // namespace llvm
789 
790 #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:232
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.
typename SuperClass::const_iterator const_iterator
Definition: SmallVector.h:320
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:484
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
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:953
llvm::sys::fs::file_type type() const
The result of a status operation.
FileSystemList::const_reverse_iterator const_iterator
Entry(EntryKind K, StringRef Name)
FileSystemList::const_iterator const_reverse_iterator
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:986
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
const_reverse_iterator overlays_rbegin() const
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:1093
const_iterator overlays_begin() const
void setCaseSensitivity(bool CaseSensitive)
const_reverse_iterator overlays_rend() const
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
FileSystemList::iterator reverse_iterator
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:46
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
reverse_iterator overlays_rbegin()
Get an iterator pointing to the least recently added file system.
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.
reverse_iterator overlays_rend()
Get an iterator pointing one-past the most recently added file 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.