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