LLVM  14.0.0git
FileCollector.cpp
Go to the documentation of this file.
1 //===-- FileCollector.cpp ---------------------------------------*- 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 
10 #include "llvm/ADT/SmallString.h"
11 #include "llvm/ADT/Twine.h"
13 #include "llvm/Support/Path.h"
14 #include "llvm/Support/Process.h"
15 
16 using namespace llvm;
17 
20 
22  std::lock_guard<std::mutex> lock(Mutex);
23  std::string FileStr = File.str();
24  if (markAsSeen(FileStr))
25  addFileImpl(FileStr);
26 }
27 
30  std::error_code EC;
32 }
33 
34 static bool isCaseSensitivePath(StringRef Path) {
35  SmallString<256> TmpDest = Path, UpperDest, RealDest;
36 
37  // Remove component traversals, links, etc.
38  if (sys::fs::real_path(Path, TmpDest))
39  return true; // Current default value in vfs.yaml
40  Path = TmpDest;
41 
42  // Change path to all upper case and ask for its real path, if the latter
43  // exists and is equal to path, it's not case sensitive. Default to case
44  // sensitive in the absence of real_path, since this is the YAMLVFSWriter
45  // default.
46  UpperDest = Path.upper();
47  if (!sys::fs::real_path(UpperDest, RealDest) && Path.equals(RealDest))
48  return false;
49  return true;
50 }
51 
52 FileCollector::FileCollector(std::string Root, std::string OverlayRoot)
53  : Root(std::move(Root)), OverlayRoot(std::move(OverlayRoot)) {
54 }
55 
56 void FileCollector::PathCanonicalizer::updateWithRealPath(
57  SmallVectorImpl<char> &Path) {
58  StringRef SrcPath(Path.begin(), Path.size());
59  StringRef Filename = sys::path::filename(SrcPath);
60  StringRef Directory = sys::path::parent_path(SrcPath);
61 
62  // Use real_path to fix any symbolic link component present in the directory
63  // part of the path, caching the search because computing the real path is
64  // expensive.
65  SmallString<256> RealPath;
66  auto DirWithSymlink = CachedDirs.find(Directory);
67  if (DirWithSymlink == CachedDirs.end()) {
68  // FIXME: Should this be a call to FileSystem::getRealpath(), in some
69  // cases? What if there is nothing on disk?
70  if (sys::fs::real_path(Directory, RealPath))
71  return;
72  CachedDirs[Directory] = std::string(RealPath.str());
73  } else {
74  RealPath = DirWithSymlink->second;
75  }
76 
77  // Finish recreating the path by appending the original filename, since we
78  // don't need to resolve symlinks in the filename.
79  //
80  // FIXME: If we can cope with this, maybe we can cope without calling
81  // getRealPath() at all when there's no ".." component.
82  sys::path::append(RealPath, Filename);
83 
84  // Swap to create the output.
85  Path.swap(RealPath);
86 }
87 
88 /// Make Path absolute.
89 static void makeAbsolute(SmallVectorImpl<char> &Path) {
90  // We need an absolute src path to append to the root.
92 
93  // Canonicalize src to a native path to avoid mixed separator styles.
94  sys::path::native(Path);
95 
96  // Remove redundant leading "./" pieces and consecutive separators.
97  Path.erase(Path.begin(), sys::path::remove_leading_dotslash(
98  StringRef(Path.begin(), Path.size()))
99  .begin());
100 }
101 
104  PathStorage Paths;
105  Paths.VirtualPath = SrcPath;
106  makeAbsolute(Paths.VirtualPath);
107 
108  // If a ".." component is present after a symlink component, remove_dots may
109  // lead to the wrong real destination path. Let the source be canonicalized
110  // like that but make sure we always use the real path for the destination.
111  Paths.CopyFrom = Paths.VirtualPath;
112  updateWithRealPath(Paths.CopyFrom);
113 
114  // Canonicalize the virtual path by removing "..", "." components.
115  sys::path::remove_dots(Paths.VirtualPath, /*remove_dot_dot=*/true);
116 
117  return Paths;
118 }
119 
122 
123  SmallString<256> DstPath = StringRef(Root);
125 
126  // Always map a canonical src path to its real path into the YAML, by doing
127  // this we map different virtual src paths to the same entry in the VFS
128  // overlay, which is a way to emulate symlink inside the VFS; this is also
129  // needed for correctness, not doing that can lead to module redefinition
130  // errors.
131  addFileToMapping(Paths.VirtualPath, DstPath);
132 }
133 
137  std::error_code &EC) {
138  auto It = FS->dir_begin(Dir, EC);
139  if (EC)
140  return It;
141  addFile(Dir);
142  for (; !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
143  if (It->type() == sys::fs::file_type::regular_file ||
144  It->type() == sys::fs::file_type::directory_file ||
145  It->type() == sys::fs::file_type::symlink_file) {
146  addFile(It->path());
147  }
148  }
149  if (EC)
150  return It;
151  // Return a new iterator.
152  return FS->dir_begin(Dir, EC);
153 }
154 
155 /// Set the access and modification time for the given file from the given
156 /// status object.
157 static std::error_code
159  const sys::fs::file_status &Stat) {
160  int FD;
161 
162  if (auto EC =
164  return EC;
165 
167  FD, Stat.getLastAccessedTime(), Stat.getLastModificationTime()))
168  return EC;
169 
170  if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
171  return EC;
172 
173  return {};
174 }
175 
176 std::error_code FileCollector::copyFiles(bool StopOnError) {
177  auto Err = sys::fs::create_directories(Root, /*IgnoreExisting=*/true);
178  if (Err) {
179  return Err;
180  }
181 
182  std::lock_guard<std::mutex> lock(Mutex);
183 
184  for (auto &entry : VFSWriter.getMappings()) {
185  // Get the status of the original file/directory.
187  if (std::error_code EC = sys::fs::status(entry.VPath, Stat)) {
188  if (StopOnError)
189  return EC;
190  continue;
191  }
192 
193  // Continue if the file doesn't exist.
195  continue;
196 
197  // Create directory tree.
198  if (std::error_code EC =
200  /*IgnoreExisting=*/true)) {
201  if (StopOnError)
202  return EC;
203  }
204 
206  // Construct a directory when it's just a directory entry.
207  if (std::error_code EC =
209  /*IgnoreExisting=*/true)) {
210  if (StopOnError)
211  return EC;
212  }
213  continue;
214  }
215 
216  // Copy file over.
217  if (std::error_code EC = sys::fs::copy_file(entry.VPath, entry.RPath)) {
218  if (StopOnError)
219  return EC;
220  }
221 
222  // Copy over permissions.
223  if (auto perms = sys::fs::getPermissions(entry.VPath)) {
224  if (std::error_code EC = sys::fs::setPermissions(entry.RPath, *perms)) {
225  if (StopOnError)
226  return EC;
227  }
228  }
229 
230  // Copy over modification time.
232  }
233  return {};
234 }
235 
236 std::error_code FileCollector::writeMapping(StringRef MappingFile) {
237  std::lock_guard<std::mutex> lock(Mutex);
238 
242 
243  std::error_code EC;
244  raw_fd_ostream os(MappingFile, EC, sys::fs::OF_TextWithCRLF);
245  if (EC)
246  return EC;
247 
248  VFSWriter.write(os);
249 
250  return {};
251 }
252 
253 namespace llvm {
254 
256 public:
258  std::shared_ptr<FileCollector> Collector)
259  : FS(std::move(FS)), Collector(std::move(Collector)) {}
260 
262  auto Result = FS->status(Path);
263  if (Result && Result->exists())
264  Collector->addFile(Path);
265  return Result;
266  }
267 
269  openFileForRead(const Twine &Path) override {
270  auto Result = FS->openFileForRead(Path);
271  if (Result && *Result)
272  Collector->addFile(Path);
273  return Result;
274  }
275 
277  std::error_code &EC) override {
278  return Collector->addDirectoryImpl(Dir, FS, EC);
279  }
280 
281  std::error_code getRealPath(const Twine &Path,
282  SmallVectorImpl<char> &Output) const override {
283  auto EC = FS->getRealPath(Path, Output);
284  if (!EC) {
285  Collector->addFile(Path);
286  if (Output.size() > 0)
287  Collector->addFile(Output);
288  }
289  return EC;
290  }
291 
292  std::error_code isLocal(const Twine &Path, bool &Result) override {
293  return FS->isLocal(Path, Result);
294  }
295 
297  return FS->getCurrentWorkingDirectory();
298  }
299 
300  std::error_code setCurrentWorkingDirectory(const llvm::Twine &Path) override {
301  return FS->setCurrentWorkingDirectory(Path);
302  }
303 
304 private:
306  std::shared_ptr<FileCollector> Collector;
307 };
308 
309 } // namespace llvm
310 
313  std::shared_ptr<FileCollector> Collector) {
315 }
llvm::sys::fs::openFileForWrite
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp=CD_CreateAlways, OpenFlags Flags=OF_None, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
Definition: FileSystem.h:1040
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::SmallVectorImpl::erase
iterator erase(const_iterator CI)
Definition: SmallVector.h:705
FileSystem.h
llvm::FileCollector::Root
const std::string Root
The directory where collected files are copied to in copyFiles().
Definition: FileCollector.h:133
FileCollector.h
llvm::FileCollectorBase::markAsSeen
bool markAsSeen(StringRef Path)
Definition: FileCollector.h:32
llvm::sys::path::remove_leading_dotslash
StringRef remove_leading_dotslash(StringRef path, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
Definition: Path.cpp:702
Path.h
llvm::FileCollector::OverlayRoot
const std::string OverlayRoot
The root directory where the VFS overlay lives.
Definition: FileCollector.h:136
llvm::FileCollector::addFileImpl
void addFileImpl(StringRef SrcPath) override
Definition: FileCollector.cpp:120
isCaseSensitivePath
static bool isCaseSensitivePath(StringRef Path)
Definition: FileCollector.cpp:34
llvm::FileCollector::createCollectorVFS
static IntrusiveRefCntPtr< vfs::FileSystem > createCollectorVFS(IntrusiveRefCntPtr< vfs::FileSystem > BaseFS, std::shared_ptr< FileCollector > Collector)
Create a VFS that uses Collector to collect files accessed via BaseFS.
Definition: FileCollector.cpp:312
llvm::StringMap::end
iterator end()
Definition: StringMap.h:203
llvm::sys::fs::file_type::file_not_found
@ file_not_found
llvm::vfs::directory_iterator
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
Definition: VirtualFileSystem.h:159
llvm::sys::fs::file_type::regular_file
@ regular_file
llvm::sys::fs::CD_OpenExisting
@ CD_OpenExisting
CD_OpenExisting - When opening a file:
Definition: FileSystem.h:743
llvm::sys::path::native
void native(const Twine &path, SmallVectorImpl< char > &result, Style style=Style::native)
Convert path to the native form.
Definition: Path.cpp:538
llvm::FileCollector::PathCanonicalizer::PathStorage
Definition: FileCollector.h:76
makeAbsolute
static void makeAbsolute(SmallVectorImpl< char > &Path)
Make Path absolute.
Definition: FileCollector.cpp:89
llvm::FileCollectorFileSystem::status
llvm::ErrorOr< llvm::vfs::Status > status(const Twine &Path) override
Get the status of the entry at Path, if one exists.
Definition: FileCollector.cpp:261
llvm::StringMap::find
iterator find(StringRef Key)
Definition: StringMap.h:216
llvm::sys::fs::setLastAccessAndModificationTime
std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, TimePoint<> ModificationTime)
Set the file modification and access time.
llvm::FileCollectorFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
Definition: FileCollector.cpp:292
copyAccessAndModificationTime
static std::error_code copyAccessAndModificationTime(StringRef Filename, const sys::fs::file_status &Stat)
Set the access and modification time for the given file from the given status object.
Definition: FileCollector.cpp:158
Collector
Register Usage Information Collector
Definition: RegUsageInfoCollector.cpp:74
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:454
llvm::FileCollectorBase::addFileImpl
virtual void addFileImpl(StringRef SrcPath)=0
Process.h
llvm::sys::fs::file_type::symlink_file
@ symlink_file
SmallString.h
llvm::FileCollector::writeMapping
std::error_code writeMapping(StringRef MappingFile)
Write the yaml mapping (for the VFS) to the given file.
Definition: FileCollector.cpp:236
Twine.h
llvm::sys::fs::real_path
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
llvm::FileCollector::addDirectoryImpl
llvm::vfs::directory_iterator addDirectoryImpl(const llvm::Twine &Dir, IntrusiveRefCntPtr< vfs::FileSystem > FS, std::error_code &EC) override
Definition: FileCollector.cpp:135
llvm::sys::fs::basic_file_status::getLastAccessedTime
TimePoint getLastAccessedTime() const
The file access time as reported from the underlying file system.
llvm::sys::fs::create_directories
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition: Path.cpp:963
llvm::FileCollectorFileSystem::getRealPath
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) const override
Gets real path of Path e.g.
Definition: FileCollector.cpp:281
llvm::FileCollector::Canonicalizer
PathCanonicalizer Canonicalizer
Helper utility for canonicalizing paths.
Definition: FileCollector.h:142
llvm::FileCollectorFileSystem::FileCollectorFileSystem
FileCollectorFileSystem(IntrusiveRefCntPtr< vfs::FileSystem > FS, std::shared_ptr< FileCollector > Collector)
Definition: FileCollector.cpp:257
llvm::FileCollectorBase::~FileCollectorBase
virtual ~FileCollectorBase()
llvm::sys::SmartMutex< false >
llvm::StringRef::equals
LLVM_NODISCARD bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:187
llvm::SmallString< 256 >
llvm::sys::fs::OF_TextWithCRLF
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
Definition: FileSystem.h:770
llvm::FileCollector::copyFiles
std::error_code copyFiles(bool StopOnError=true)
Copy the files into the root directory.
Definition: FileCollector.cpp:176
llvm::sys::Process::SafelyCloseFileDescriptor
static std::error_code SafelyCloseFileDescriptor(int FD)
llvm::sys::fs::file_status
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:226
llvm::sys::path::remove_dots
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
Definition: Path.cpp:714
llvm::vfs::getRealFileSystem
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition: VirtualFileSystem.cpp:346
llvm::StringRef::upper
LLVM_NODISCARD std::string upper() const
Convert the given ASCII string to uppercase.
Definition: StringRef.cpp:110
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::sys::path::parent_path
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:465
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1609
llvm::FileCollectorFileSystem
Definition: FileCollector.cpp:255
llvm::sys::fs::setPermissions
std::error_code setPermissions(const Twine &Path, perms Permissions)
Set file permissions.
llvm::FileCollectorFileSystem::dir_begin
llvm::vfs::directory_iterator dir_begin(const llvm::Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Definition: FileCollector.cpp:276
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:901
llvm::sys::fs::basic_file_status::type
file_type type() const
Definition: FileSystem.h:184
llvm::FileCollectorBase::addFile
void addFile(const Twine &file)
Definition: FileCollector.cpp:21
llvm::FileCollectorFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const llvm::Twine &Path) override
Set the working directory.
Definition: FileCollector.cpp:300
llvm::FileCollectorFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition: FileCollector.cpp:296
llvm::vfs::YAMLVFSWriter::setCaseSensitivity
void setCaseSensitivity(bool CaseSensitive)
Definition: VirtualFileSystem.h:898
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::sys::fs::getPermissions
ErrorOr< perms > getPermissions(const Twine &Path)
Get file permissions.
Definition: Path.cpp:1147
llvm::vfs::YAMLVFSWriter::write
void write(llvm::raw_ostream &OS)
Definition: VirtualFileSystem.cpp:2328
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:443
llvm::vfs::YAMLVFSWriter::setOverlayDir
void setOverlayDir(StringRef OverlayDirectory)
Definition: VirtualFileSystem.h:904
llvm::FileCollector::PathCanonicalizer::PathStorage::VirtualPath
SmallString< 256 > VirtualPath
Definition: FileCollector.h:78
llvm::vfs::YAMLVFSWriter::setUseExternalNames
void setUseExternalNames(bool UseExtNames)
Definition: VirtualFileSystem.h:902
llvm::sys::fs::file_type::directory_file
@ directory_file
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::vfs::FileSystem
The virtual file system interface.
Definition: VirtualFileSystem.h:245
std
Definition: BitVector.h:838
llvm::SmallVectorImpl::swap
void swap(SmallVectorImpl &RHS)
Definition: SmallVector.h:936
llvm::X86AS::FS
@ FS
Definition: X86.h:188
llvm::FileCollectorBase::FileCollectorBase
FileCollectorBase()
llvm::sys::fs::is_directory
bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition: Path.cpp:1088
llvm::FileCollectorBase::addDirectoryImpl
virtual llvm::vfs::directory_iterator addDirectoryImpl(const llvm::Twine &Dir, IntrusiveRefCntPtr< vfs::FileSystem > FS, std::error_code &EC)=0
llvm::FileCollector::PathCanonicalizer::PathStorage::CopyFrom
SmallString< 256 > CopyFrom
Definition: FileCollector.h:77
llvm::SmallString::str
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:259
llvm::sys::fs::perms
perms
Definition: FileSystem.h:86
llvm::sys::path::filename
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:575
llvm::FileCollector::PathCanonicalizer::canonicalize
PathStorage canonicalize(StringRef SrcPath)
Canonicalize a pair of virtual and real paths.
Definition: FileCollector.cpp:103
llvm::vfs::YAMLVFSWriter::getMappings
const std::vector< YAMLVFSEntry > & getMappings() const
Definition: VirtualFileSystem.h:909
llvm::sys::fs::status
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
llvm::FileCollectorFileSystem::openFileForRead
llvm::ErrorOr< std::unique_ptr< llvm::vfs::File > > openFileForRead(const Twine &Path) override
Get a File object for the file at Path, if one exists.
Definition: FileCollector.cpp:269
llvm::SmallVectorImpl< char >
llvm::FileCollector::FileCollector
FileCollector(std::string Root, std::string OverlayRoot)
Root is the directory where collected files are will be stored.
Definition: FileCollector.cpp:52
llvm::sys::fs::basic_file_status::getLastModificationTime
TimePoint getLastModificationTime() const
The file modification time as reported from the underlying file system.
llvm::sys::path::relative_path
StringRef relative_path(StringRef path, Style style=Style::native)
Get relative path.
Definition: Path.cpp:411
llvm::FileCollectorBase::addDirectory
void addDirectory(const Twine &Dir)
Definition: FileCollector.cpp:28
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:128
llvm::FileCollector::VFSWriter
vfs::YAMLVFSWriter VFSWriter
The yaml mapping writer.
Definition: FileCollector.h:139
File
Instrumentation for Order File
Definition: InstrOrderFile.cpp:205
llvm::IntrusiveRefCntPtr
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
Definition: IntrusiveRefCntPtr.h:163
entry
print Instructions which execute on loop entry
Definition: MustExecute.cpp:339
llvm::sys::fs::copy_file
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:1012