Home | History | Annotate | Download | only in Basic
      1 //===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Defines the clang::FileManager interface and associated types.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_BASIC_FILEMANAGER_H
     16 #define LLVM_CLANG_BASIC_FILEMANAGER_H
     17 
     18 #include "clang/Basic/FileSystemOptions.h"
     19 #include "clang/Basic/VirtualFileSystem.h"
     20 #include "llvm/ADT/DenseMap.h"
     21 #include "llvm/ADT/IntrusiveRefCntPtr.h"
     22 #include "llvm/ADT/SmallVector.h"
     23 #include "llvm/ADT/StringMap.h"
     24 #include "llvm/ADT/StringRef.h"
     25 #include "llvm/Support/Allocator.h"
     26 #include "llvm/Support/ErrorOr.h"
     27 #include "llvm/Support/FileSystem.h"
     28 #include <ctime>
     29 #include <memory>
     30 #include <map>
     31 #include <string>
     32 
     33 namespace llvm {
     34 
     35 class MemoryBuffer;
     36 
     37 } // end namespace llvm
     38 
     39 namespace clang {
     40 
     41 class FileSystemStatCache;
     42 
     43 /// \brief Cached information about one directory (either on disk or in
     44 /// the virtual file system).
     45 class DirectoryEntry {
     46   friend class FileManager;
     47 
     48   StringRef Name; // Name of the directory.
     49 
     50 public:
     51   StringRef getName() const { return Name; }
     52 };
     53 
     54 /// \brief Cached information about one file (either on disk
     55 /// or in the virtual file system).
     56 ///
     57 /// If the 'File' member is valid, then this FileEntry has an open file
     58 /// descriptor for the file.
     59 class FileEntry {
     60   friend class FileManager;
     61 
     62   StringRef Name;             // Name of the file.
     63   std::string RealPathName;   // Real path to the file; could be empty.
     64   off_t Size;                 // File size in bytes.
     65   time_t ModTime;             // Modification time of file.
     66   const DirectoryEntry *Dir;  // Directory file lives in.
     67   unsigned UID;               // A unique (small) ID for the file.
     68   llvm::sys::fs::UniqueID UniqueID;
     69   bool IsNamedPipe;
     70   bool InPCH;
     71   bool IsValid;               // Is this \c FileEntry initialized and valid?
     72 
     73   /// \brief The open file, if it is owned by the \p FileEntry.
     74   mutable std::unique_ptr<vfs::File> File;
     75 
     76 public:
     77   FileEntry()
     78       : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
     79   {}
     80 
     81   FileEntry(const FileEntry &) = delete;
     82   FileEntry &operator=(const FileEntry &) = delete;
     83 
     84   StringRef getName() const { return Name; }
     85   StringRef tryGetRealPathName() const { return RealPathName; }
     86   bool isValid() const { return IsValid; }
     87   off_t getSize() const { return Size; }
     88   unsigned getUID() const { return UID; }
     89   const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
     90   bool isInPCH() const { return InPCH; }
     91   time_t getModificationTime() const { return ModTime; }
     92 
     93   /// \brief Return the directory the file lives in.
     94   const DirectoryEntry *getDir() const { return Dir; }
     95 
     96   bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; }
     97 
     98   /// \brief Check whether the file is a named pipe (and thus can't be opened by
     99   /// the native FileManager methods).
    100   bool isNamedPipe() const { return IsNamedPipe; }
    101 
    102   void closeFile() const {
    103     File.reset(); // rely on destructor to close File
    104   }
    105 };
    106 
    107 struct FileData;
    108 
    109 /// \brief Implements support for file system lookup, file system caching,
    110 /// and directory search management.
    111 ///
    112 /// This also handles more advanced properties, such as uniquing files based
    113 /// on "inode", so that a file with two names (e.g. symlinked) will be treated
    114 /// as a single file.
    115 ///
    116 class FileManager : public RefCountedBase<FileManager> {
    117   IntrusiveRefCntPtr<vfs::FileSystem> FS;
    118   FileSystemOptions FileSystemOpts;
    119 
    120   /// \brief Cache for existing real directories.
    121   std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
    122 
    123   /// \brief Cache for existing real files.
    124   std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles;
    125 
    126   /// \brief The virtual directories that we have allocated.
    127   ///
    128   /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
    129   /// directories (foo/ and foo/bar/) here.
    130   SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
    131   /// \brief The virtual files that we have allocated.
    132   SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
    133 
    134   /// \brief A cache that maps paths to directory entries (either real or
    135   /// virtual) we have looked up
    136   ///
    137   /// The actual Entries for real directories/files are
    138   /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
    139   /// for virtual directories/files are owned by
    140   /// VirtualDirectoryEntries/VirtualFileEntries above.
    141   ///
    142   llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
    143 
    144   /// \brief A cache that maps paths to file entries (either real or
    145   /// virtual) we have looked up.
    146   ///
    147   /// \see SeenDirEntries
    148   llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
    149 
    150   /// \brief The canonical names of directories.
    151   llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
    152 
    153   /// \brief Storage for canonical names that we have computed.
    154   llvm::BumpPtrAllocator CanonicalNameStorage;
    155 
    156   /// \brief Each FileEntry we create is assigned a unique ID #.
    157   ///
    158   unsigned NextFileUID;
    159 
    160   // Statistics.
    161   unsigned NumDirLookups, NumFileLookups;
    162   unsigned NumDirCacheMisses, NumFileCacheMisses;
    163 
    164   // Caching.
    165   std::unique_ptr<FileSystemStatCache> StatCache;
    166 
    167   bool getStatValue(StringRef Path, FileData &Data, bool isFile,
    168                     std::unique_ptr<vfs::File> *F);
    169 
    170   /// Add all ancestors of the given path (pointing to either a file
    171   /// or a directory) as virtual directories.
    172   void addAncestorsAsVirtualDirs(StringRef Path);
    173 
    174 public:
    175   FileManager(const FileSystemOptions &FileSystemOpts,
    176               IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr);
    177   ~FileManager();
    178 
    179   /// \brief Installs the provided FileSystemStatCache object within
    180   /// the FileManager.
    181   ///
    182   /// Ownership of this object is transferred to the FileManager.
    183   ///
    184   /// \param statCache the new stat cache to install. Ownership of this
    185   /// object is transferred to the FileManager.
    186   ///
    187   /// \param AtBeginning whether this new stat cache must be installed at the
    188   /// beginning of the chain of stat caches. Otherwise, it will be added to
    189   /// the end of the chain.
    190   void addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
    191                     bool AtBeginning = false);
    192 
    193   /// \brief Removes the specified FileSystemStatCache object from the manager.
    194   void removeStatCache(FileSystemStatCache *statCache);
    195 
    196   /// \brief Removes all FileSystemStatCache objects from the manager.
    197   void clearStatCaches();
    198 
    199   /// \brief Lookup, cache, and verify the specified directory (real or
    200   /// virtual).
    201   ///
    202   /// This returns NULL if the directory doesn't exist.
    203   ///
    204   /// \param CacheFailure If true and the file does not exist, we'll cache
    205   /// the failure to find this file.
    206   const DirectoryEntry *getDirectory(StringRef DirName,
    207                                      bool CacheFailure = true);
    208 
    209   /// \brief Lookup, cache, and verify the specified file (real or
    210   /// virtual).
    211   ///
    212   /// This returns NULL if the file doesn't exist.
    213   ///
    214   /// \param OpenFile if true and the file exists, it will be opened.
    215   ///
    216   /// \param CacheFailure If true and the file does not exist, we'll cache
    217   /// the failure to find this file.
    218   const FileEntry *getFile(StringRef Filename, bool OpenFile = false,
    219                            bool CacheFailure = true);
    220 
    221   /// \brief Returns the current file system options
    222   FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
    223   const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
    224 
    225   IntrusiveRefCntPtr<vfs::FileSystem> getVirtualFileSystem() const {
    226     return FS;
    227   }
    228 
    229   /// \brief Retrieve a file entry for a "virtual" file that acts as
    230   /// if there were a file with the given name on disk.
    231   ///
    232   /// The file itself is not accessed.
    233   const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
    234                                   time_t ModificationTime);
    235 
    236   /// \brief Open the specified file as a MemoryBuffer, returning a new
    237   /// MemoryBuffer if successful, otherwise returning null.
    238   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
    239   getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
    240                    bool ShouldCloseOpenFile = true);
    241   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
    242   getBufferForFile(StringRef Filename);
    243 
    244   /// \brief Get the 'stat' information for the given \p Path.
    245   ///
    246   /// If the path is relative, it will be resolved against the WorkingDir of the
    247   /// FileManager's FileSystemOptions.
    248   ///
    249   /// \returns false on success, true on error.
    250   bool getNoncachedStatValue(StringRef Path,
    251                              vfs::Status &Result);
    252 
    253   /// \brief Remove the real file \p Entry from the cache.
    254   void invalidateCache(const FileEntry *Entry);
    255 
    256   /// \brief If path is not absolute and FileSystemOptions set the working
    257   /// directory, the path is modified to be relative to the given
    258   /// working directory.
    259   /// \returns true if \c path changed.
    260   bool FixupRelativePath(SmallVectorImpl<char> &path) const;
    261 
    262   /// Makes \c Path absolute taking into account FileSystemOptions and the
    263   /// working directory option.
    264   /// \returns true if \c Path changed to absolute.
    265   bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
    266 
    267   /// \brief Produce an array mapping from the unique IDs assigned to each
    268   /// file to the corresponding FileEntry pointer.
    269   void GetUniqueIDMapping(
    270                     SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
    271 
    272   /// \brief Modifies the size and modification time of a previously created
    273   /// FileEntry. Use with caution.
    274   static void modifyFileEntry(FileEntry *File, off_t Size,
    275                               time_t ModificationTime);
    276 
    277   /// \brief Retrieve the canonical name for a given directory.
    278   ///
    279   /// This is a very expensive operation, despite its results being cached,
    280   /// and should only be used when the physical layout of the file system is
    281   /// required, which is (almost) never.
    282   StringRef getCanonicalName(const DirectoryEntry *Dir);
    283 
    284   void PrintStats() const;
    285 };
    286 
    287 } // end namespace clang
    288 
    289 #endif // LLVM_CLANG_BASIC_FILEMANAGER_H
    290