1e5dd7070Spatrick //===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick /// 9e5dd7070Spatrick /// \file 10e5dd7070Spatrick /// Defines the clang::FileManager interface and associated types. 11e5dd7070Spatrick /// 12e5dd7070Spatrick //===----------------------------------------------------------------------===// 13e5dd7070Spatrick 14e5dd7070Spatrick #ifndef LLVM_CLANG_BASIC_FILEMANAGER_H 15e5dd7070Spatrick #define LLVM_CLANG_BASIC_FILEMANAGER_H 16e5dd7070Spatrick 17a9ac8606Spatrick #include "clang/Basic/DirectoryEntry.h" 18a9ac8606Spatrick #include "clang/Basic/FileEntry.h" 19e5dd7070Spatrick #include "clang/Basic/FileSystemOptions.h" 20e5dd7070Spatrick #include "clang/Basic/LLVM.h" 21e5dd7070Spatrick #include "llvm/ADT/DenseMap.h" 22e5dd7070Spatrick #include "llvm/ADT/IntrusiveRefCntPtr.h" 23ec727ea7Spatrick #include "llvm/ADT/PointerUnion.h" 24e5dd7070Spatrick #include "llvm/ADT/SmallVector.h" 25e5dd7070Spatrick #include "llvm/ADT/StringMap.h" 26e5dd7070Spatrick #include "llvm/ADT/StringRef.h" 27e5dd7070Spatrick #include "llvm/Support/Allocator.h" 28e5dd7070Spatrick #include "llvm/Support/ErrorOr.h" 29e5dd7070Spatrick #include "llvm/Support/FileSystem.h" 30e5dd7070Spatrick #include "llvm/Support/VirtualFileSystem.h" 31e5dd7070Spatrick #include <ctime> 32e5dd7070Spatrick #include <map> 33e5dd7070Spatrick #include <memory> 34e5dd7070Spatrick #include <string> 35e5dd7070Spatrick 36e5dd7070Spatrick namespace llvm { 37e5dd7070Spatrick 38e5dd7070Spatrick class MemoryBuffer; 39e5dd7070Spatrick 40e5dd7070Spatrick } // end namespace llvm 41e5dd7070Spatrick 42e5dd7070Spatrick namespace clang { 43e5dd7070Spatrick 44e5dd7070Spatrick class FileSystemStatCache; 45e5dd7070Spatrick 46e5dd7070Spatrick /// Implements support for file system lookup, file system caching, 47e5dd7070Spatrick /// and directory search management. 48e5dd7070Spatrick /// 49e5dd7070Spatrick /// This also handles more advanced properties, such as uniquing files based 50e5dd7070Spatrick /// on "inode", so that a file with two names (e.g. symlinked) will be treated 51e5dd7070Spatrick /// as a single file. 52e5dd7070Spatrick /// 53e5dd7070Spatrick class FileManager : public RefCountedBase<FileManager> { 54e5dd7070Spatrick IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; 55e5dd7070Spatrick FileSystemOptions FileSystemOpts; 56*12c85518Srobert llvm::SpecificBumpPtrAllocator<FileEntry> FilesAlloc; 57*12c85518Srobert llvm::SpecificBumpPtrAllocator<DirectoryEntry> DirsAlloc; 58e5dd7070Spatrick 59e5dd7070Spatrick /// Cache for existing real directories. 60*12c85518Srobert llvm::DenseMap<llvm::sys::fs::UniqueID, DirectoryEntry *> UniqueRealDirs; 61e5dd7070Spatrick 62e5dd7070Spatrick /// Cache for existing real files. 63*12c85518Srobert llvm::DenseMap<llvm::sys::fs::UniqueID, FileEntry *> UniqueRealFiles; 64e5dd7070Spatrick 65e5dd7070Spatrick /// The virtual directories that we have allocated. 66e5dd7070Spatrick /// 67e5dd7070Spatrick /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent 68e5dd7070Spatrick /// directories (foo/ and foo/bar/) here. 69*12c85518Srobert SmallVector<DirectoryEntry *, 4> VirtualDirectoryEntries; 70e5dd7070Spatrick /// The virtual files that we have allocated. 71*12c85518Srobert SmallVector<FileEntry *, 4> VirtualFileEntries; 72e5dd7070Spatrick 73e5dd7070Spatrick /// A set of files that bypass the maps and uniquing. They can have 74e5dd7070Spatrick /// conflicting filenames. 75*12c85518Srobert SmallVector<FileEntry *, 0> BypassFileEntries; 76e5dd7070Spatrick 77e5dd7070Spatrick /// A cache that maps paths to directory entries (either real or 78e5dd7070Spatrick /// virtual) we have looked up, or an error that occurred when we looked up 79e5dd7070Spatrick /// the directory. 80e5dd7070Spatrick /// 81e5dd7070Spatrick /// The actual Entries for real directories/files are 82e5dd7070Spatrick /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries 83e5dd7070Spatrick /// for virtual directories/files are owned by 84e5dd7070Spatrick /// VirtualDirectoryEntries/VirtualFileEntries above. 85e5dd7070Spatrick /// 86e5dd7070Spatrick llvm::StringMap<llvm::ErrorOr<DirectoryEntry &>, llvm::BumpPtrAllocator> 87e5dd7070Spatrick SeenDirEntries; 88e5dd7070Spatrick 89e5dd7070Spatrick /// A cache that maps paths to file entries (either real or 90e5dd7070Spatrick /// virtual) we have looked up, or an error that occurred when we looked up 91e5dd7070Spatrick /// the file. 92e5dd7070Spatrick /// 93e5dd7070Spatrick /// \see SeenDirEntries 94a9ac8606Spatrick llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>, llvm::BumpPtrAllocator> 95e5dd7070Spatrick SeenFileEntries; 96e5dd7070Spatrick 97a9ac8606Spatrick /// A mirror of SeenFileEntries to give fake answers for getBypassFile(). 98a9ac8606Spatrick /// 99a9ac8606Spatrick /// Don't bother hooking up a BumpPtrAllocator. This should be rarely used, 100a9ac8606Spatrick /// and only on error paths. 101a9ac8606Spatrick std::unique_ptr<llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>>> 102a9ac8606Spatrick SeenBypassFileEntries; 103a9ac8606Spatrick 104a9ac8606Spatrick /// The file entry for stdin, if it has been accessed through the FileManager. 105*12c85518Srobert OptionalFileEntryRef STDIN; 106a9ac8606Spatrick 107e5dd7070Spatrick /// The canonical names of files and directories . 108e5dd7070Spatrick llvm::DenseMap<const void *, llvm::StringRef> CanonicalNames; 109e5dd7070Spatrick 110e5dd7070Spatrick /// Storage for canonical names that we have computed. 111e5dd7070Spatrick llvm::BumpPtrAllocator CanonicalNameStorage; 112e5dd7070Spatrick 113e5dd7070Spatrick /// Each FileEntry we create is assigned a unique ID #. 114e5dd7070Spatrick /// 115e5dd7070Spatrick unsigned NextFileUID; 116e5dd7070Spatrick 117e5dd7070Spatrick // Caching. 118e5dd7070Spatrick std::unique_ptr<FileSystemStatCache> StatCache; 119e5dd7070Spatrick 120e5dd7070Spatrick std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status, 121e5dd7070Spatrick bool isFile, 122e5dd7070Spatrick std::unique_ptr<llvm::vfs::File> *F); 123e5dd7070Spatrick 124e5dd7070Spatrick /// Add all ancestors of the given path (pointing to either a file 125e5dd7070Spatrick /// or a directory) as virtual directories. 126e5dd7070Spatrick void addAncestorsAsVirtualDirs(StringRef Path); 127e5dd7070Spatrick 128e5dd7070Spatrick /// Fills the RealPathName in file entry. 129e5dd7070Spatrick void fillRealPathName(FileEntry *UFE, llvm::StringRef FileName); 130e5dd7070Spatrick 131e5dd7070Spatrick public: 132e5dd7070Spatrick /// Construct a file manager, optionally with a custom VFS. 133e5dd7070Spatrick /// 134e5dd7070Spatrick /// \param FS if non-null, the VFS to use. Otherwise uses 135e5dd7070Spatrick /// llvm::vfs::getRealFileSystem(). 136e5dd7070Spatrick FileManager(const FileSystemOptions &FileSystemOpts, 137e5dd7070Spatrick IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr); 138e5dd7070Spatrick ~FileManager(); 139e5dd7070Spatrick 140e5dd7070Spatrick /// Installs the provided FileSystemStatCache object within 141e5dd7070Spatrick /// the FileManager. 142e5dd7070Spatrick /// 143e5dd7070Spatrick /// Ownership of this object is transferred to the FileManager. 144e5dd7070Spatrick /// 145e5dd7070Spatrick /// \param statCache the new stat cache to install. Ownership of this 146e5dd7070Spatrick /// object is transferred to the FileManager. 147e5dd7070Spatrick void setStatCache(std::unique_ptr<FileSystemStatCache> statCache); 148e5dd7070Spatrick 149e5dd7070Spatrick /// Removes the FileSystemStatCache object from the manager. 150e5dd7070Spatrick void clearStatCache(); 151e5dd7070Spatrick 152e5dd7070Spatrick /// Returns the number of unique real file entries cached by the file manager. getNumUniqueRealFiles()153e5dd7070Spatrick size_t getNumUniqueRealFiles() const { return UniqueRealFiles.size(); } 154e5dd7070Spatrick 155e5dd7070Spatrick /// Lookup, cache, and verify the specified directory (real or 156e5dd7070Spatrick /// virtual). 157e5dd7070Spatrick /// 158e5dd7070Spatrick /// This returns a \c std::error_code if there was an error reading the 159e5dd7070Spatrick /// directory. On success, returns the reference to the directory entry 160e5dd7070Spatrick /// together with the exact path that was used to access a file by a 161e5dd7070Spatrick /// particular call to getDirectoryRef. 162e5dd7070Spatrick /// 163e5dd7070Spatrick /// \param CacheFailure If true and the file does not exist, we'll cache 164e5dd7070Spatrick /// the failure to find this file. 165e5dd7070Spatrick llvm::Expected<DirectoryEntryRef> getDirectoryRef(StringRef DirName, 166e5dd7070Spatrick bool CacheFailure = true); 167e5dd7070Spatrick 168e5dd7070Spatrick /// Get a \c DirectoryEntryRef if it exists, without doing anything on error. 169*12c85518Srobert OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, 170*12c85518Srobert bool CacheFailure = true) { 171e5dd7070Spatrick return llvm::expectedToOptional(getDirectoryRef(DirName, CacheFailure)); 172e5dd7070Spatrick } 173e5dd7070Spatrick 174e5dd7070Spatrick /// Lookup, cache, and verify the specified directory (real or 175e5dd7070Spatrick /// virtual). 176e5dd7070Spatrick /// 177e5dd7070Spatrick /// This function is deprecated and will be removed at some point in the 178e5dd7070Spatrick /// future, new clients should use 179e5dd7070Spatrick /// \c getDirectoryRef. 180e5dd7070Spatrick /// 181e5dd7070Spatrick /// This returns a \c std::error_code if there was an error reading the 182e5dd7070Spatrick /// directory. If there is no error, the DirectoryEntry is guaranteed to be 183e5dd7070Spatrick /// non-NULL. 184e5dd7070Spatrick /// 185e5dd7070Spatrick /// \param CacheFailure If true and the file does not exist, we'll cache 186e5dd7070Spatrick /// the failure to find this file. 187e5dd7070Spatrick llvm::ErrorOr<const DirectoryEntry *> 188e5dd7070Spatrick getDirectory(StringRef DirName, bool CacheFailure = true); 189e5dd7070Spatrick 190e5dd7070Spatrick /// Lookup, cache, and verify the specified file (real or 191e5dd7070Spatrick /// virtual). 192e5dd7070Spatrick /// 193e5dd7070Spatrick /// This function is deprecated and will be removed at some point in the 194e5dd7070Spatrick /// future, new clients should use 195e5dd7070Spatrick /// \c getFileRef. 196e5dd7070Spatrick /// 197e5dd7070Spatrick /// This returns a \c std::error_code if there was an error loading the file. 198e5dd7070Spatrick /// If there is no error, the FileEntry is guaranteed to be non-NULL. 199e5dd7070Spatrick /// 200e5dd7070Spatrick /// \param OpenFile if true and the file exists, it will be opened. 201e5dd7070Spatrick /// 202e5dd7070Spatrick /// \param CacheFailure If true and the file does not exist, we'll cache 203e5dd7070Spatrick /// the failure to find this file. 204e5dd7070Spatrick llvm::ErrorOr<const FileEntry *> 205e5dd7070Spatrick getFile(StringRef Filename, bool OpenFile = false, bool CacheFailure = true); 206e5dd7070Spatrick 207e5dd7070Spatrick /// Lookup, cache, and verify the specified file (real or virtual). Return the 208e5dd7070Spatrick /// reference to the file entry together with the exact path that was used to 209e5dd7070Spatrick /// access a file by a particular call to getFileRef. If the underlying VFS is 210e5dd7070Spatrick /// a redirecting VFS that uses external file names, the returned FileEntryRef 211e5dd7070Spatrick /// will use the external name instead of the filename that was passed to this 212e5dd7070Spatrick /// method. 213e5dd7070Spatrick /// 214e5dd7070Spatrick /// This returns a \c std::error_code if there was an error loading the file, 215e5dd7070Spatrick /// or a \c FileEntryRef otherwise. 216e5dd7070Spatrick /// 217e5dd7070Spatrick /// \param OpenFile if true and the file exists, it will be opened. 218e5dd7070Spatrick /// 219e5dd7070Spatrick /// \param CacheFailure If true and the file does not exist, we'll cache 220e5dd7070Spatrick /// the failure to find this file. 221e5dd7070Spatrick llvm::Expected<FileEntryRef> getFileRef(StringRef Filename, 222e5dd7070Spatrick bool OpenFile = false, 223e5dd7070Spatrick bool CacheFailure = true); 224e5dd7070Spatrick 225a9ac8606Spatrick /// Get the FileEntryRef for stdin, returning an error if stdin cannot be 226a9ac8606Spatrick /// read. 227a9ac8606Spatrick /// 228a9ac8606Spatrick /// This reads and caches stdin before returning. Subsequent calls return the 229a9ac8606Spatrick /// same file entry, and a reference to the cached input is returned by calls 230a9ac8606Spatrick /// to getBufferForFile. 231a9ac8606Spatrick llvm::Expected<FileEntryRef> getSTDIN(); 232a9ac8606Spatrick 233e5dd7070Spatrick /// Get a FileEntryRef if it exists, without doing anything on error. 234*12c85518Srobert OptionalFileEntryRef getOptionalFileRef(StringRef Filename, 235e5dd7070Spatrick bool OpenFile = false, 236e5dd7070Spatrick bool CacheFailure = true) { 237e5dd7070Spatrick return llvm::expectedToOptional( 238e5dd7070Spatrick getFileRef(Filename, OpenFile, CacheFailure)); 239e5dd7070Spatrick } 240e5dd7070Spatrick 241e5dd7070Spatrick /// Returns the current file system options getFileSystemOpts()242e5dd7070Spatrick FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; } getFileSystemOpts()243e5dd7070Spatrick const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } 244e5dd7070Spatrick getVirtualFileSystem()245e5dd7070Spatrick llvm::vfs::FileSystem &getVirtualFileSystem() const { return *FS; } 246*12c85518Srobert llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystemPtr()247*12c85518Srobert getVirtualFileSystemPtr() const { 248*12c85518Srobert return FS; 249*12c85518Srobert } 250e5dd7070Spatrick setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)251e5dd7070Spatrick void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) { 252e5dd7070Spatrick this->FS = std::move(FS); 253e5dd7070Spatrick } 254e5dd7070Spatrick 255e5dd7070Spatrick /// Retrieve a file entry for a "virtual" file that acts as 256e5dd7070Spatrick /// if there were a file with the given name on disk. 257e5dd7070Spatrick /// 258e5dd7070Spatrick /// The file itself is not accessed. 259a9ac8606Spatrick FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size, 260a9ac8606Spatrick time_t ModificationTime); 261a9ac8606Spatrick 262e5dd7070Spatrick const FileEntry *getVirtualFile(StringRef Filename, off_t Size, 263e5dd7070Spatrick time_t ModificationTime); 264e5dd7070Spatrick 265e5dd7070Spatrick /// Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual 266e5dd7070Spatrick /// file entry, to access the real file. The returned FileEntry will have 267e5dd7070Spatrick /// the same filename as FE but a different identity and its own stat. 268e5dd7070Spatrick /// 269e5dd7070Spatrick /// This should be used only for rare error recovery paths because it 270e5dd7070Spatrick /// bypasses all mapping and uniquing, blindly creating a new FileEntry. 271e5dd7070Spatrick /// There is no attempt to deduplicate these; if you bypass the same file 272e5dd7070Spatrick /// twice, you get two new file entries. 273*12c85518Srobert OptionalFileEntryRef getBypassFile(FileEntryRef VFE); 274e5dd7070Spatrick 275e5dd7070Spatrick /// Open the specified file as a MemoryBuffer, returning a new 276e5dd7070Spatrick /// MemoryBuffer if successful, otherwise returning null. 277e5dd7070Spatrick llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 278ec727ea7Spatrick getBufferForFile(const FileEntry *Entry, bool isVolatile = false, 279ec727ea7Spatrick bool RequiresNullTerminator = true); 280e5dd7070Spatrick llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 281ec727ea7Spatrick getBufferForFile(StringRef Filename, bool isVolatile = false, 282ec727ea7Spatrick bool RequiresNullTerminator = true) { 283ec727ea7Spatrick return getBufferForFileImpl(Filename, /*FileSize=*/-1, isVolatile, 284ec727ea7Spatrick RequiresNullTerminator); 285e5dd7070Spatrick } 286e5dd7070Spatrick 287e5dd7070Spatrick private: 288e5dd7070Spatrick llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 289ec727ea7Spatrick getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile, 290ec727ea7Spatrick bool RequiresNullTerminator); 291e5dd7070Spatrick 292e5dd7070Spatrick public: 293e5dd7070Spatrick /// Get the 'stat' information for the given \p Path. 294e5dd7070Spatrick /// 295e5dd7070Spatrick /// If the path is relative, it will be resolved against the WorkingDir of the 296e5dd7070Spatrick /// FileManager's FileSystemOptions. 297e5dd7070Spatrick /// 298e5dd7070Spatrick /// \returns a \c std::error_code describing an error, if there was one 299e5dd7070Spatrick std::error_code getNoncachedStatValue(StringRef Path, 300e5dd7070Spatrick llvm::vfs::Status &Result); 301e5dd7070Spatrick 302e5dd7070Spatrick /// If path is not absolute and FileSystemOptions set the working 303e5dd7070Spatrick /// directory, the path is modified to be relative to the given 304e5dd7070Spatrick /// working directory. 305e5dd7070Spatrick /// \returns true if \c path changed. 306e5dd7070Spatrick bool FixupRelativePath(SmallVectorImpl<char> &path) const; 307e5dd7070Spatrick 308e5dd7070Spatrick /// Makes \c Path absolute taking into account FileSystemOptions and the 309e5dd7070Spatrick /// working directory option. 310e5dd7070Spatrick /// \returns true if \c Path changed to absolute. 311e5dd7070Spatrick bool makeAbsolutePath(SmallVectorImpl<char> &Path) const; 312e5dd7070Spatrick 313e5dd7070Spatrick /// Produce an array mapping from the unique IDs assigned to each 314e5dd7070Spatrick /// file to the corresponding FileEntry pointer. 315e5dd7070Spatrick void GetUniqueIDMapping( 316e5dd7070Spatrick SmallVectorImpl<const FileEntry *> &UIDToFiles) const; 317e5dd7070Spatrick 318e5dd7070Spatrick /// Retrieve the canonical name for a given directory. 319e5dd7070Spatrick /// 320e5dd7070Spatrick /// This is a very expensive operation, despite its results being cached, 321e5dd7070Spatrick /// and should only be used when the physical layout of the file system is 322e5dd7070Spatrick /// required, which is (almost) never. 323e5dd7070Spatrick StringRef getCanonicalName(const DirectoryEntry *Dir); 324e5dd7070Spatrick 325e5dd7070Spatrick /// Retrieve the canonical name for a given file. 326e5dd7070Spatrick /// 327e5dd7070Spatrick /// This is a very expensive operation, despite its results being cached, 328e5dd7070Spatrick /// and should only be used when the physical layout of the file system is 329e5dd7070Spatrick /// required, which is (almost) never. 330e5dd7070Spatrick StringRef getCanonicalName(const FileEntry *File); 331e5dd7070Spatrick 332e5dd7070Spatrick void PrintStats() const; 333e5dd7070Spatrick }; 334e5dd7070Spatrick 335e5dd7070Spatrick } // end namespace clang 336e5dd7070Spatrick 337e5dd7070Spatrick #endif // LLVM_CLANG_BASIC_FILEMANAGER_H 338