110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner//===--- FileManager.cpp - File System Probing and Caching ----------------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the FileManager interface. 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// TODO: This should index all interesting directories with dirent calls. 155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// getdirentries ? 165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// opendir/readdir_r/closedir ? 175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/FileManager.h" 2110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "clang/Basic/FileSystemStatCache.h" 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/SmallString.h" 2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Config/llvm-config.h" 24fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer#include "llvm/Support/FileSystem.h" 25389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#include "llvm/Support/MemoryBuffer.h" 2603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 2755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 28458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <map> 29458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <set> 30458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <string> 31ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include <system_error> 32291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 353d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to 365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk. 373d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 39f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// NON_EXISTENT_FILE - A special value distinct from null that is used to 40f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// represent a filename that doesn't exist on the disk. 41f9f7766846a205bc900b578f944567e679b221aaChris Lattner#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 42f9f7766846a205bc900b578f944567e679b221aaChris Lattner 43cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 44cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic. 45cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 466bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 47651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesFileManager::FileManager(const FileSystemOptions &FSO, 48651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IntrusiveRefCntPtr<vfs::FileSystem> FS) 49651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : FS(FS), FileSystemOpts(FSO), 509b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { 516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirLookups = NumFileLookups = 0; 526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirCacheMisses = NumFileCacheMisses = 0; 53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 54651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the caller doesn't provide a virtual file system, just grab the real 55651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // file system. 56651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!FS) 57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines this->FS = vfs::getRealFileSystem(); 586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 606bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() { 61f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i) 62f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner delete VirtualFileEntries[i]; 639b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i) 649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan delete VirtualDirectoryEntries[i]; 656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 666bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 6710e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::addStatCache(FileSystemStatCache *statCache, 6810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner bool AtBeginning) { 6952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor assert(statCache && "No stat cache provided?"); 706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (AtBeginning || !StatCache.get()) { 71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines statCache->setNextStatCache(StatCache.release()); 7252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(statCache); 7352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 7452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 7552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 7610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *LastCache = StatCache.get(); 7752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (LastCache->getNextStatCache()) 7852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache = LastCache->getNextStatCache(); 7952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 8052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache->setNextStatCache(statCache); 8152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 8252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 8310e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::removeStatCache(FileSystemStatCache *statCache) { 8452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (!statCache) 8552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 8652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 8752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (StatCache.get() == statCache) { 8852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // This is the first stat cache. 8952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(StatCache->takeNextStatCache()); 9052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 9152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 9252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 9352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // Find the stat cache in the list. 9410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *PrevCache = StatCache.get(); 9552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (PrevCache && PrevCache->getNextStatCache() != statCache) 9652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PrevCache = PrevCache->getNextStatCache(); 97f9f7766846a205bc900b578f944567e679b221aaChris Lattner 98f9f7766846a205bc900b578f944567e679b221aaChris Lattner assert(PrevCache && "Stat cache not found for removal"); 99f9f7766846a205bc900b578f944567e679b221aaChris Lattner PrevCache->setNextStatCache(statCache->getNextStatCache()); 10052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 10152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 10298be86038b1e891a05583061c55dfa974150eb2cManuel Klimekvoid FileManager::clearStatCaches() { 1036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines StatCache.reset(nullptr); 10498be86038b1e891a05583061c55dfa974150eb2cManuel Klimek} 10598be86038b1e891a05583061c55dfa974150eb2cManuel Klimek 106057e567f1b375190779e5341f42861896cdee442Douglas Gregor/// \brief Retrieve the directory that the given file name resides in. 1079b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// Filename can point to either a real file or a virtual file. 108057e567f1b375190779e5341f42861896cdee442Douglas Gregorstatic const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 1096e975c4517958bcc11c834336d340797356058dbDouglas Gregor StringRef Filename, 1106e975c4517958bcc11c834336d340797356058dbDouglas Gregor bool CacheFailure) { 11121af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (Filename.empty()) 1126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1139b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 11421af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) 1156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; // If Filename is a directory. 116aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 1175f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef DirName = llvm::sys::path::parent_path(Filename); 118f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Use the current directory if file has no path component. 11921af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (DirName.empty()) 12021af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan DirName = "."; 121aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 1226e975c4517958bcc11c834336d340797356058dbDouglas Gregor return FileMgr.getDirectory(DirName, CacheFailure); 123057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 124057e567f1b375190779e5341f42861896cdee442Douglas Gregor 1259b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// Add all ancestors of the given path (pointing to either a file or 1269b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// a directory) as virtual directories. 1275f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid FileManager::addAncestorsAsVirtualDirs(StringRef Path) { 1285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef DirName = llvm::sys::path::parent_path(Path); 12921af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (DirName.empty()) 1309b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return; 1319b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 1329b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 1339b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries.GetOrCreateValue(DirName); 1349b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 1359b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // When caching a virtual directory, we always cache its ancestors 1369b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // at the same time. Therefore, if DirName is already in the cache, 1379b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // we don't need to recurse as its ancestors must also already be in 1389b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // the cache. 1399b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (NamedDirEnt.getValue()) 1409b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return; 1419b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 1429b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Add the virtual directory to the cache. 1439b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry *UDE = new DirectoryEntry; 1449b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UDE->Name = NamedDirEnt.getKeyData(); 1459b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan NamedDirEnt.setValue(UDE); 1469b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan VirtualDirectoryEntries.push_back(UDE); 1479b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 1489b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Recursively add the other ancestors. 1499b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan addAncestorsAsVirtualDirs(DirName); 1509b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan} 1519b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 1526e975c4517958bcc11c834336d340797356058dbDouglas Gregorconst DirectoryEntry *FileManager::getDirectory(StringRef DirName, 1536e975c4517958bcc11c834336d340797356058dbDouglas Gregor bool CacheFailure) { 154759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi // stat doesn't like trailing separators except for root directory. 155678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'. 156678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi // (though it can strip '\\') 157759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi if (DirName.size() > 1 && 158759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi DirName != llvm::sys::path::root_path(DirName) && 159759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi llvm::sys::path::is_separator(DirName.back())) 160678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi DirName = DirName.substr(0, DirName.size()-1); 161146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola#ifdef LLVM_ON_WIN32 162146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola // Fixing a problem with "clang C:test.c" on Windows. 163146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola // Stat("C:") does not recognize "C:" as a valid directory 164146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola std::string DirNameStr; 165146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola if (DirName.size() > 1 && DirName.back() == ':' && 166146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola DirName.equals_lower(llvm::sys::path::root_name(DirName))) { 167146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola DirNameStr = DirName.str() + '.'; 168146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola DirName = DirNameStr; 169146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola } 170146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola#endif 171678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi 1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 1749b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries.GetOrCreateValue(DirName); 1751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1769b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // See if there was already an entry in the map. Note that the map 1779b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // contains both virtual and real directories. 1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 1796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return NamedDirEnt.getValue() == NON_EXISTENT_DIR ? nullptr 1806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : NamedDirEnt.getValue(); 1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 1831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 1853d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 1861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 1889b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // SeenDirEntries map. 1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 1901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 1920fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola FileData Data; 1936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) { 1949b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // There's no real directory at the given path. 1956e975c4517958bcc11c834336d340797356058dbDouglas Gregor if (!CacheFailure) 1966e975c4517958bcc11c834336d340797356058dbDouglas Gregor SeenDirEntries.erase(DirName); 1976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1989b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 1996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 2009b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // It exists. See if we have already opened a directory with the 2019b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // same inode (this occurs on Unix-like systems when one dir is 2029b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // symlinked to another, for example) or the same path (on 2039b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Windows). 204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID]; 2051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 2079b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (!UDE.getName()) { 2089b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // We don't have this directory yet, add it. We use the string 2099b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // key from the SeenDirEntries map as the string. 2109b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UDE.Name = InterndDirName; 2119b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 2121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 2145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2166e975c4517958bcc11c834336d340797356058dbDouglas Gregorconst FileEntry *FileManager::getFile(StringRef Filename, bool openFile, 2176e975c4517958bcc11c834336d340797356058dbDouglas Gregor bool CacheFailure) { 2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 2229b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenFileEntries.GetOrCreateValue(Filename); 2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 2263d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 2276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ? nullptr : NamedFileEnt.getValue(); 2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2323d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 2359b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // SeenFileEntries map. 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 2371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 238f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // Look up the directory for the file. When looking up something like 239f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // sys/foo.h we'll discover all of the search directories that have a 'sys' 240f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // subdirectory. This will let us avoid having to waste time on known-to-fail 241f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // searches when we go to find sys/bar.h, because all the search directories 242f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // without a 'sys' subdir will get a cached failure result. 2436e975c4517958bcc11c834336d340797356058dbDouglas Gregor const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 2446e975c4517958bcc11c834336d340797356058dbDouglas Gregor CacheFailure); 2456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist. 2466e975c4517958bcc11c834336d340797356058dbDouglas Gregor if (!CacheFailure) 2476e975c4517958bcc11c834336d340797356058dbDouglas Gregor SeenFileEntries.erase(Filename); 2486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2506e975c4517958bcc11c834336d340797356058dbDouglas Gregor } 2516e975c4517958bcc11c834336d340797356058dbDouglas Gregor 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 2535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 2541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 256ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::unique_ptr<vfs::File> F; 2570fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola FileData Data; 2586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) { 2599b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // There's no real file at the given path. 2606e975c4517958bcc11c834336d340797356058dbDouglas Gregor if (!CacheFailure) 2616e975c4517958bcc11c834336d340797356058dbDouglas Gregor SeenFileEntries.erase(Filename); 2626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert((openFile || !F) && "undesired open file"); 2673cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis 268bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileEntry &UFE = UniqueRealFiles[Data.UniqueID]; 2711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (UFE.isValid()) { // Already have an entry with this inode, return it. 2746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // FIXME: this hack ensures that if we look up a file by a virtual path in 2766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // the VFS that the getDir() will have the virtual path, even if we found 2776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // the file by a 'real' path first. This is required in order to find a 2786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // module's structure when its headers/module map are mapped in the VFS. 2796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // We should remove this as soon as we can properly support a file having 2806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // multiple names. 2816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (DirInfo != UFE.Dir && Data.IsVFSMapped) 2826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines UFE.Dir = DirInfo; 2836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 285898a061f69e1145bf89a987c08203132b9922a3cChris Lattner } 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Otherwise, we don't have this file yet, add it. 288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE.Name = Data.Name; 2890fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola UFE.Size = Data.Size; 2900fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola UFE.ModTime = Data.ModTime; 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE.UniqueID = Data.UniqueID; 294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE.IsNamedPipe = Data.IsNamedPipe; 295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE.InPCH = Data.InPCH; 296ef8225444452a1486bd721f3285301fe84643b00Stephen Hines UFE.File = std::move(F); 297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE.IsValid = true; 2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 301057e567f1b375190779e5341f42861896cdee442Douglas Gregorconst FileEntry * 3025f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerFileManager::getVirtualFile(StringRef Filename, off_t Size, 30339b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner time_t ModificationTime) { 304057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileLookups; 305057e567f1b375190779e5341f42861896cdee442Douglas Gregor 306057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 307057e567f1b375190779e5341f42861896cdee442Douglas Gregor llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 3089b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenFileEntries.GetOrCreateValue(Filename); 309057e567f1b375190779e5341f42861896cdee442Douglas Gregor 310057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 31104331169f04198eb769925fa17696a21989c9d8bAxel Naumann if (NamedFileEnt.getValue() && NamedFileEnt.getValue() != NON_EXISTENT_FILE) 31204331169f04198eb769925fa17696a21989c9d8bAxel Naumann return NamedFileEnt.getValue(); 313057e567f1b375190779e5341f42861896cdee442Douglas Gregor 314057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileCacheMisses; 315057e567f1b375190779e5341f42861896cdee442Douglas Gregor 316057e567f1b375190779e5341f42861896cdee442Douglas Gregor // By default, initialize it to invalid. 317057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(NON_EXISTENT_FILE); 318057e567f1b375190779e5341f42861896cdee442Douglas Gregor 3199b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan addAncestorsAsVirtualDirs(Filename); 3206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines FileEntry *UFE = nullptr; 3219b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 3229b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Now that all ancestors of Filename are in the cache, the 3239b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // following call is guaranteed to find the DirectoryEntry from the 3249b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // cache. 3256e975c4517958bcc11c834336d340797356058dbDouglas Gregor const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 3266e975c4517958bcc11c834336d340797356058dbDouglas Gregor /*CacheFailure=*/true); 3279b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan assert(DirInfo && 3289b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan "The directory of a virtual file should already be in the cache."); 3299b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 3309b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Check to see if the file exists. If so, drop the virtual file 3310fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola FileData Data; 3329b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan const char *InterndFileName = NamedFileEnt.getKeyData(); 3336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (getStatValue(InterndFileName, Data, true, nullptr) == 0) { 3340fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola Data.Size = Size; 3350fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola Data.ModTime = ModificationTime; 336651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE = &UniqueRealFiles[Data.UniqueID]; 3379b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 3389b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan NamedFileEnt.setValue(UFE); 3399b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 3409b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // If we had already opened this file, close it now so we don't 3419b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // leak the descriptor. We're not going to use the file 3429b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // descriptor anyway, since this is a virtual file. 343651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (UFE->File) 344651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE->closeFile(); 3459b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 3469b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // If we already have an entry with this inode, return it. 347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (UFE->isValid()) 3489b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return UFE; 349651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE->UniqueID = Data.UniqueID; 351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE->IsNamedPipe = Data.IsNamedPipe; 352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE->InPCH = Data.InPCH; 3538ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 354057e567f1b375190779e5341f42861896cdee442Douglas Gregor 3558ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor if (!UFE) { 3568ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor UFE = new FileEntry(); 3578ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor VirtualFileEntries.push_back(UFE); 3588ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor NamedFileEnt.setValue(UFE); 3598ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 360057e567f1b375190779e5341f42861896cdee442Douglas Gregor 361f9f7766846a205bc900b578f944567e679b221aaChris Lattner UFE->Name = InterndFileName; 362057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Size = Size; 363057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->ModTime = ModificationTime; 364057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Dir = DirInfo; 365057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->UID = NextFileUID++; 366651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UFE->File.reset(); 367057e567f1b375190779e5341f42861896cdee442Douglas Gregor return UFE; 368057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 369057e567f1b375190779e5341f42861896cdee442Douglas Gregor 3705f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { 3715f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef pathRef(path.data(), path.size()); 372af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson 3732e2468e2d2ccbb9a38fe3b6b754009af7e5d39a9Anders Carlsson if (FileSystemOpts.WorkingDir.empty() 3742e2468e2d2ccbb9a38fe3b6b754009af7e5d39a9Anders Carlsson || llvm::sys::path::is_absolute(pathRef)) 375256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer return; 376256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer 377f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> NewPath(FileSystemOpts.WorkingDir); 378af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson llvm::sys::path::append(NewPath, pathRef); 37967452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner path = NewPath; 38067452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner} 38167452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 38275dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattnerllvm::MemoryBuffer *FileManager:: 383ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios KyrtzidisgetBufferForFile(const FileEntry *Entry, std::string *ErrorStr, 384ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool isVolatile, bool ShouldCloseOpenFile) { 385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<llvm::MemoryBuffer> Result; 386ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::error_code ec; 3875cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner 388ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis uint64_t FileSize = Entry->getSize(); 389ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis // If there's a high enough chance that the file have changed since we 390ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis // got its size, force a stat before opening it. 391ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis if (isVolatile) 392ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis FileSize = -1; 393ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis 394a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis const char *Filename = Entry->getName(); 395a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis // If the file is already open, use the open file descriptor. 396651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Entry->File) { 3976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ec = Entry->File->getBuffer(Filename, Result, FileSize, 3986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /*RequiresNullTerminator=*/true, isVolatile); 399a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis if (ErrorStr) 400a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis *ErrorStr = ec.message(); 401ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // FIXME: we need a set of APIs that can make guarantees about whether a 402ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // FileEntry is open or not. 403ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (ShouldCloseOpenFile) 404ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Entry->closeFile(); 405651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Result.release(); 406a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis } 407a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis 408a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis // Otherwise, open the file. 409a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis 410a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis if (FileSystemOpts.WorkingDir.empty()) { 4116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ec = FS->getBufferForFile(Filename, Result, FileSize, 4126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /*RequiresNullTerminator=*/true, isVolatile); 4134eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4143a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 415651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Result.release(); 4165cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner } 417af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson 418f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Entry->getName()); 41903fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 4206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ec = FS->getBufferForFile(FilePath.str(), Result, FileSize, 4216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /*RequiresNullTerminator=*/true, isVolatile); 4224eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4233a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Result.release(); 42575dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner} 42667452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 427f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerllvm::MemoryBuffer *FileManager:: 4285f9e272e632e951b1efe824cd16acb4d96077930Chris LattnergetBufferForFile(StringRef Filename, std::string *ErrorStr) { 429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<llvm::MemoryBuffer> Result; 430ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::error_code ec; 4313a321e23f66128dbb986343927456ff6702af617Michael J. Spencer if (FileSystemOpts.WorkingDir.empty()) { 432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ec = FS->getBufferForFile(Filename, Result); 4334eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4343a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Result.release(); 4363a321e23f66128dbb986343927456ff6702af617Michael J. Spencer } 4373a321e23f66128dbb986343927456ff6702af617Michael J. Spencer 438f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Filename); 43903fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 440651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ec = FS->getBufferForFile(FilePath.c_str(), Result); 4414eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4423a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 443651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Result.release(); 444389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 445389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 4469b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// getStatValue - Get the 'stat' information for the specified path, 4479b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// using the cache to accelerate it if possible. This returns true 4489b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// if the path points to a virtual file or does not exist, or returns 4499b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// false if it's an existent real file. If FileDescriptor is NULL, 4509b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// do directory look-up instead of file look-up. 4510fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindolabool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile, 452ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::unique_ptr<vfs::File> *F) { 45310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be 45410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // absolute! 45511aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner if (FileSystemOpts.WorkingDir.empty()) 456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS); 4579b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 458f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Path); 45903fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 46011aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner 461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F, 462651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StatCache.get(), *FS); 463389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 464389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 465aefb1d3312a63ac8d289a2e84747fe61a7f61823Rafael Espindolabool FileManager::getNoncachedStatValue(StringRef Path, 466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines vfs::Status &Result) { 467f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Path); 4687dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson FixupRelativePath(FilePath); 4697dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson 470651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str()); 471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!S) 472651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 473651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Result = *S; 474651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 4757dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson} 4767dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson 4775ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumannvoid FileManager::invalidateCache(const FileEntry *Entry) { 4785ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann assert(Entry && "Cannot invalidate a NULL FileEntry"); 4793ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 4803ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann SeenFileEntries.erase(Entry->getName()); 4815ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann 4825ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann // FileEntry invalidation should not block future optimizations in the file 4835ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann // caches. Possible alternatives are cache truncation (invalidate last N) or 4845ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann // invalidation of the whole cache. 485651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UniqueRealFiles.erase(Entry->getUniqueID()); 4863ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann} 4873ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 4883ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 489cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregorvoid FileManager::GetUniqueIDMapping( 4905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<const FileEntry *> &UIDToFiles) const { 491cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles.clear(); 492cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles.resize(NextFileUID); 493cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 494cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor // Map file entries 495cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator 4969b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end(); 497cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor FE != FEEnd; ++FE) 498cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE) 499cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles[FE->getValue()->getUID()] = FE->getValue(); 500cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 501cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor // Map virtual file entries 50209d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper for (SmallVectorImpl<FileEntry *>::const_iterator 503cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end(); 504cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor VFE != VFEEnd; ++VFE) 505cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor if (*VFE && *VFE != NON_EXISTENT_FILE) 506cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles[(*VFE)->getUID()] = *VFE; 507cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor} 50810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 509d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidisvoid FileManager::modifyFileEntry(FileEntry *File, 510d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis off_t Size, time_t ModificationTime) { 511d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis File->Size = Size; 512d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis File->ModTime = ModificationTime; 513d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis} 514d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis 515713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas GregorStringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { 516713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor // FIXME: use llvm::sys::fs::canonical() when it gets implemented 517713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#ifdef LLVM_ON_UNIX 518713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known 519713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor = CanonicalDirNames.find(Dir); 520713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor if (Known != CanonicalDirNames.end()) 521713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor return Known->second; 522713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor 523713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor StringRef CanonicalName(Dir->getName()); 524713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor char CanonicalNameBuf[PATH_MAX]; 525713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor if (realpath(Dir->getName(), CanonicalNameBuf)) { 526713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor unsigned Len = strlen(CanonicalNameBuf); 527713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor char *Mem = static_cast<char *>(CanonicalNameStorage.Allocate(Len, 1)); 528713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor memcpy(Mem, CanonicalNameBuf, Len); 529713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor CanonicalName = StringRef(Mem, Len); 530713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor } 531713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor 532713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName)); 533713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor return CanonicalName; 534713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#else 535713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor return StringRef(Dir->getName()); 536713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#endif 537713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor} 53810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 5395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 5406cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "\n*** File Manager Stats:\n"; 5419b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::errs() << UniqueRealFiles.size() << " real files found, " 5429b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan << UniqueRealDirs.size() << " real dirs found.\n"; 5439b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::errs() << VirtualFileEntries.size() << " virtual files found, " 5449b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan << VirtualDirectoryEntries.size() << " virtual dirs found.\n"; 5456cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumDirLookups << " dir lookups, " 5466cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumDirCacheMisses << " dir cache misses.\n"; 5476cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumFileLookups << " file lookups, " 5486cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumFileCacheMisses << " file cache misses.\n"; 5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5506cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 5515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 552