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 // This file defines the FileManager interface. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_FILEMANAGER_H 15 #define LLVM_CLANG_FILEMANAGER_H 16 17 #include "clang/Basic/FileSystemOptions.h" 18 #include "llvm/ADT/IntrusiveRefCntPtr.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/ADT/StringMap.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/ADT/OwningPtr.h" 23 #include "llvm/Support/Allocator.h" 24 // FIXME: Enhance libsystem to support inode and other fields in stat. 25 #include <sys/types.h> 26 27 #ifdef _MSC_VER 28 typedef unsigned short mode_t; 29 #endif 30 31 struct stat; 32 33 namespace llvm { 34 class MemoryBuffer; 35 namespace sys { class Path; } 36 } 37 38 namespace clang { 39 class FileManager; 40 class FileSystemStatCache; 41 42 /// DirectoryEntry - Cached information about one directory (either on 43 /// the disk or in the virtual file system). 44 /// 45 class DirectoryEntry { 46 const char *Name; // Name of the directory. 47 friend class FileManager; 48 public: DirectoryEntry()49 DirectoryEntry() : Name(0) {} getName()50 const char *getName() const { return Name; } 51 }; 52 53 /// FileEntry - Cached information about one file (either on the disk 54 /// or in the virtual file system). If the 'FD' member is valid, then 55 /// this FileEntry has an open file descriptor for the file. 56 /// 57 class FileEntry { 58 const char *Name; // Name of the file. 59 off_t Size; // File size in bytes. 60 time_t ModTime; // Modification time of file. 61 const DirectoryEntry *Dir; // Directory file lives in. 62 unsigned UID; // A unique (small) ID for the file. 63 dev_t Device; // ID for the device containing the file. 64 ino_t Inode; // Inode number for the file. 65 mode_t FileMode; // The file mode as returned by 'stat'. 66 67 /// FD - The file descriptor for the file entry if it is opened and owned 68 /// by the FileEntry. If not, this is set to -1. 69 mutable int FD; 70 friend class FileManager; 71 72 public: FileEntry(dev_t device,ino_t inode,mode_t m)73 FileEntry(dev_t device, ino_t inode, mode_t m) 74 : Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {} 75 // Add a default constructor for use with llvm::StringMap FileEntry()76 FileEntry() : Name(0), Device(0), Inode(0), FileMode(0), FD(-1) {} 77 FileEntry(const FileEntry & FE)78 FileEntry(const FileEntry &FE) { 79 memcpy(this, &FE, sizeof(FE)); 80 assert(FD == -1 && "Cannot copy a file-owning FileEntry"); 81 } 82 83 void operator=(const FileEntry &FE) { 84 memcpy(this, &FE, sizeof(FE)); 85 assert(FD == -1 && "Cannot assign a file-owning FileEntry"); 86 } 87 88 ~FileEntry(); 89 getName()90 const char *getName() const { return Name; } getSize()91 off_t getSize() const { return Size; } getUID()92 unsigned getUID() const { return UID; } getInode()93 ino_t getInode() const { return Inode; } getDevice()94 dev_t getDevice() const { return Device; } getModificationTime()95 time_t getModificationTime() const { return ModTime; } getFileMode()96 mode_t getFileMode() const { return FileMode; } 97 98 /// getDir - Return the directory the file lives in. 99 /// getDir()100 const DirectoryEntry *getDir() const { return Dir; } 101 102 bool operator<(const FileEntry &RHS) const { 103 return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode); 104 } 105 }; 106 107 /// FileManager - Implements support for file system lookup, file system 108 /// caching, and directory search management. This also handles more advanced 109 /// properties, such as uniquing files based on "inode", so that a file with two 110 /// names (e.g. symlinked) will be treated as a single file. 111 /// 112 class FileManager : public llvm::RefCountedBase<FileManager> { 113 FileSystemOptions FileSystemOpts; 114 115 class UniqueDirContainer; 116 class UniqueFileContainer; 117 118 /// UniqueRealDirs/UniqueRealFiles - Cache for existing real directories/files. 119 /// 120 UniqueDirContainer &UniqueRealDirs; 121 UniqueFileContainer &UniqueRealFiles; 122 123 /// \brief The virtual directories that we have allocated. For each 124 /// virtual file (e.g. foo/bar/baz.cpp), we add all of its parent 125 /// directories (foo/ and foo/bar/) here. 126 llvm::SmallVector<DirectoryEntry*, 4> VirtualDirectoryEntries; 127 /// \brief The virtual files that we have allocated. 128 llvm::SmallVector<FileEntry*, 4> VirtualFileEntries; 129 130 /// SeenDirEntries/SeenFileEntries - This is a cache that maps paths 131 /// to directory/file entries (either real or virtual) we have 132 /// looked up. The actual Entries for real directories/files are 133 /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries 134 /// for virtual directories/files are owned by 135 /// VirtualDirectoryEntries/VirtualFileEntries above. 136 /// 137 llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries; 138 llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries; 139 140 /// NextFileUID - Each FileEntry we create is assigned a unique ID #. 141 /// 142 unsigned NextFileUID; 143 144 // Statistics. 145 unsigned NumDirLookups, NumFileLookups; 146 unsigned NumDirCacheMisses, NumFileCacheMisses; 147 148 // Caching. 149 llvm::OwningPtr<FileSystemStatCache> StatCache; 150 151 bool getStatValue(const char *Path, struct stat &StatBuf, 152 int *FileDescriptor); 153 154 /// Add all ancestors of the given path (pointing to either a file 155 /// or a directory) as virtual directories. 156 void addAncestorsAsVirtualDirs(llvm::StringRef Path); 157 158 public: 159 FileManager(const FileSystemOptions &FileSystemOpts); 160 ~FileManager(); 161 162 /// \brief Installs the provided FileSystemStatCache object within 163 /// the FileManager. 164 /// 165 /// Ownership of this object is transferred to the FileManager. 166 /// 167 /// \param statCache the new stat cache to install. Ownership of this 168 /// object is transferred to the FileManager. 169 /// 170 /// \param AtBeginning whether this new stat cache must be installed at the 171 /// beginning of the chain of stat caches. Otherwise, it will be added to 172 /// the end of the chain. 173 void addStatCache(FileSystemStatCache *statCache, bool AtBeginning = false); 174 175 /// \brief Removes the specified FileSystemStatCache object from the manager. 176 void removeStatCache(FileSystemStatCache *statCache); 177 178 /// getDirectory - Lookup, cache, and verify the specified directory 179 /// (real or virtual). This returns NULL if the directory doesn't exist. 180 /// 181 const DirectoryEntry *getDirectory(llvm::StringRef DirName); 182 183 /// \brief Lookup, cache, and verify the specified file (real or 184 /// virtual). This returns NULL if the file doesn't exist. 185 /// 186 /// \param openFile if true and the file exists, it will be opened. 187 const FileEntry *getFile(llvm::StringRef Filename, bool openFile = false); 188 189 /// \brief Retrieve a file entry for a "virtual" file that acts as 190 /// if there were a file with the given name on disk. The file 191 /// itself is not accessed. 192 const FileEntry *getVirtualFile(llvm::StringRef Filename, off_t Size, 193 time_t ModificationTime); 194 195 /// \brief Open the specified file as a MemoryBuffer, returning a new 196 /// MemoryBuffer if successful, otherwise returning null. 197 llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry, 198 std::string *ErrorStr = 0); 199 llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename, 200 std::string *ErrorStr = 0); 201 202 // getNoncachedStatValue - Will get the 'stat' information for the given path. 203 // If the path is relative, it will be resolved against the WorkingDir of the 204 // FileManager's FileSystemOptions. 205 bool getNoncachedStatValue(llvm::StringRef Path, struct stat &StatBuf); 206 207 /// \brief If path is not absolute and FileSystemOptions set the working 208 /// directory, the path is modified to be relative to the given 209 /// working directory. 210 void FixupRelativePath(llvm::SmallVectorImpl<char> &path) const; 211 212 /// \brief Produce an array mapping from the unique IDs assigned to each 213 /// file to the corresponding FileEntry pointer. 214 void GetUniqueIDMapping( 215 llvm::SmallVectorImpl<const FileEntry *> &UIDToFiles) const; 216 217 void PrintStats() const; 218 }; 219 220 } // end namespace clang 221 222 #endif 223