FileManager.cpp revision 256053b31e697fdf0cc48f17d621c82fc3b8dff0
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"
23c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner#include "llvm/ADT/StringExtras.h"
24389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#include "llvm/Support/MemoryBuffer.h"
25d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner#include "llvm/Support/raw_ostream.h"
2603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h"
273a321e23f66128dbb986343927456ff6702af617Michael J. Spencer#include "llvm/Support/system_error.h"
286bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#include "llvm/Config/config.h"
29458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <map>
30458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <set>
31458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <string>
32291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner
33291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner// FIXME: This is terrible, we need this for ::close.
34291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#if !defined(_MSC_VER) && !defined(__MINGW32__)
35291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <unistd.h>
36291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <sys/uio.h>
37291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#else
38291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <io.h>
39291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#endif
405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang;
415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields.
435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h>
445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
453d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk.
473d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
49f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// NON_EXISTENT_FILE - A special value distinct from null that is used to
50f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// represent a filename that doesn't exist on the disk.
51f9f7766846a205bc900b578f944567e679b221aaChris Lattner#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
52f9f7766846a205bc900b578f944567e679b221aaChris Lattner
53f9f7766846a205bc900b578f944567e679b221aaChris Lattner
54f9f7766846a205bc900b578f944567e679b221aaChris LattnerFileEntry::~FileEntry() {
55f9f7766846a205bc900b578f944567e679b221aaChris Lattner  // If this FileEntry owns an open file descriptor that never got used, close
56f9f7766846a205bc900b578f944567e679b221aaChris Lattner  // it.
57f9f7766846a205bc900b578f944567e679b221aaChris Lattner  if (FD != -1) ::close(FD);
58f9f7766846a205bc900b578f944567e679b221aaChris Lattner}
59f9f7766846a205bc900b578f944567e679b221aaChris Lattner
60cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===//
61cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows.
62cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===//
63cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek
646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32
656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
66aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\')
676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
686bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremeneknamespace {
691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  static std::string GetFullPath(const char *relPath) {
706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    char *absPathStrPtr = _fullpath(NULL, relPath, 0);
716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    assert(absPathStrPtr && "_fullpath() returned NULL!");
726bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
736bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    std::string absPath(absPathStrPtr);
746bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    free(absPathStrPtr);
766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    return absPath;
776bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  }
786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}
796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer {
816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  /// UniqueDirs - Cache from full path to existing directories/files.
826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  ///
831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  llvm::StringMap<DirectoryEntry> UniqueDirs;
846bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
856bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic:
866bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
876bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    std::string FullPath(GetFullPath(Name));
88f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner    return UniqueDirs.GetOrCreateValue(FullPath).getValue();
896bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  }
901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
91f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  size_t size() const { return UniqueDirs.size(); }
926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek};
936bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
946bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer {
956bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  /// UniqueFiles - Cache from full path to existing directories/files.
966bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  ///
9775368893339d89f6523c312b0a0eb23d438b6dffTed Kremenek  llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles;
986bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic:
1006bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  FileEntry &getFile(const char *Name, struct stat &StatBuf) {
1016bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    std::string FullPath(GetFullPath(Name));
102c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner
103c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner    // LowercaseString because Windows filesystem is case insensitive.
104c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner    FullPath = llvm::LowercaseString(FullPath);
105f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner    return UniqueFiles.GetOrCreateValue(FullPath).getValue();
1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  }
1076bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
108f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  size_t size() const { return UniqueFiles.size(); }
1096bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek};
1106bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
111cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===//
112cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems.
113cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===//
114cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek
1156bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else
1166bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
117aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/')
1186bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer {
1206bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  /// UniqueDirs - Cache from ID's to existing directories/files.
1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic:
1246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
1256bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
1266bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  }
1276bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
128f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  size_t size() const { return UniqueDirs.size(); }
1296bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek};
1306bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1316bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer {
1326bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  /// UniqueFiles - Cache from ID's to existing directories/files.
1336bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  std::set<FileEntry> UniqueFiles;
1346bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1356bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic:
1366bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  FileEntry &getFile(const char *Name, struct stat &StatBuf) {
1376bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek    return
1386bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek      const_cast<FileEntry&>(
1396bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek                    *UniqueFiles.insert(FileEntry(StatBuf.st_dev,
14096438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek                                                  StatBuf.st_ino,
14196438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek                                                  StatBuf.st_mode)).first);
1426bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  }
1436bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
144f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  size_t size() const { return UniqueFiles.size(); }
1456bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek};
1466bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1476bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#endif
1486bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
149cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===//
150cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic.
151cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===//
1526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1537ad97ffa631af6ad678c79b38341ac995f347ce9Chris LattnerFileManager::FileManager(const FileSystemOptions &FSO)
1547ad97ffa631af6ad678c79b38341ac995f347ce9Chris Lattner  : FileSystemOpts(FSO),
155f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner    UniqueDirs(*new UniqueDirContainer()),
156f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner    UniqueFiles(*new UniqueFileContainer()),
15796438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek    DirEntries(64), FileEntries(64), NextFileUID(0) {
1586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  NumDirLookups = NumFileLookups = 0;
1596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  NumDirCacheMisses = NumFileCacheMisses = 0;
1606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}
1616bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1626bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() {
1636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  delete &UniqueDirs;
1646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  delete &UniqueFiles;
165f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i)
166f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner    delete VirtualFileEntries[i];
1676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}
1686bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
16910e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::addStatCache(FileSystemStatCache *statCache,
17010e286aa8d39fb51a21412850265d9dae74613eeChris Lattner                               bool AtBeginning) {
17152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  assert(statCache && "No stat cache provided?");
17252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  if (AtBeginning || StatCache.get() == 0) {
17352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    statCache->setNextStatCache(StatCache.take());
17452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    StatCache.reset(statCache);
17552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    return;
17652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  }
17752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
17810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  FileSystemStatCache *LastCache = StatCache.get();
17952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  while (LastCache->getNextStatCache())
18052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    LastCache = LastCache->getNextStatCache();
18152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
18252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  LastCache->setNextStatCache(statCache);
18352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor}
18452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
18510e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::removeStatCache(FileSystemStatCache *statCache) {
18652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  if (!statCache)
18752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    return;
18852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
18952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  if (StatCache.get() == statCache) {
19052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    // This is the first stat cache.
19152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    StatCache.reset(StatCache->takeNextStatCache());
19252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    return;
19352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  }
19452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
19552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  // Find the stat cache in the list.
19610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  FileSystemStatCache *PrevCache = StatCache.get();
19752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  while (PrevCache && PrevCache->getNextStatCache() != statCache)
19852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor    PrevCache = PrevCache->getNextStatCache();
199f9f7766846a205bc900b578f944567e679b221aaChris Lattner
200f9f7766846a205bc900b578f944567e679b221aaChris Lattner  assert(PrevCache && "Stat cache not found for removal");
201f9f7766846a205bc900b578f944567e679b221aaChris Lattner  PrevCache->setNextStatCache(statCache->getNextStatCache());
20252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor}
20352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
204057e567f1b375190779e5341f42861896cdee442Douglas Gregor/// \brief Retrieve the directory that the given file name resides in.
205057e567f1b375190779e5341f42861896cdee442Douglas Gregorstatic const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
20639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner                                                  llvm::StringRef Filename) {
207057e567f1b375190779e5341f42861896cdee442Douglas Gregor  // Figure out what directory it is in.   If the string contains a / in it,
208057e567f1b375190779e5341f42861896cdee442Douglas Gregor  // strip off everything after it.
209057e567f1b375190779e5341f42861896cdee442Douglas Gregor  // FIXME: this logic should be in sys::Path.
210aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer  size_t SlashPos = Filename.size();
211aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer  while (SlashPos != 0 && !IS_DIR_SEPARATOR_CHAR(Filename[SlashPos-1]))
212aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer    --SlashPos;
213aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer
214f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner  // Use the current directory if file has no path component.
215aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer  if (SlashPos == 0)
21639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner    return FileMgr.getDirectory(".");
217057e567f1b375190779e5341f42861896cdee442Douglas Gregor
218f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner  if (SlashPos == Filename.size()-1)
219057e567f1b375190779e5341f42861896cdee442Douglas Gregor    return 0;       // If filename ends with a /, it's a directory.
220aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer
221f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner  // Ignore repeated //'s.
222aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer  while (SlashPos != 0 && IS_DIR_SEPARATOR_CHAR(Filename[SlashPos-1]))
223f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner    --SlashPos;
224aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer
22539b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner  return FileMgr.getDirectory(Filename.substr(0, SlashPos));
226057e567f1b375190779e5341f42861896cdee442Douglas Gregor}
227057e567f1b375190779e5341f42861896cdee442Douglas Gregor
2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDirectory - Lookup, cache, and verify the specified directory.  This
2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// returns null if the directory doesn't exist.
2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///
23139b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattnerconst DirectoryEntry *FileManager::getDirectory(llvm::StringRef Filename) {
2329a6ac540bab63380a4a78d8fad87f23c50878685John Thompson  // stat doesn't like trailing separators (at least on Windows).
233aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer  if (Filename.size() > 1 && IS_DIR_SEPARATOR_CHAR(Filename.back()))
234f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner    Filename = Filename.substr(0, Filename.size()-1);
2359a6ac540bab63380a4a78d8fad87f23c50878685John Thompson
2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ++NumDirLookups;
2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
238f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner    DirEntries.GetOrCreateValue(Filename);
2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // See if there is already an entry in the map.
2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (NamedDirEnt.getValue())
2423d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek    return NamedDirEnt.getValue() == NON_EXISTENT_DIR
2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer              ? 0 : NamedDirEnt.getValue();
2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ++NumDirCacheMisses;
2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // By default, initialize it to invalid.
2483d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek  NamedDirEnt.setValue(NON_EXISTENT_DIR);
2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Get the null-terminated directory name as stored as the key of the
2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // DirEntries map.
2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *InterndDirName = NamedDirEnt.getKeyData();
2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Check to see if the directory exists.
2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  struct stat StatBuf;
256898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/))
2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return 0;
2586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // It exists.  See if we have already opened a directory with the same inode.
2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // This occurs when one dir is symlinked to another, for example.
2616bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf);
2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  NamedDirEnt.setValue(&UDE);
2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (UDE.getName()) // Already have an entry with this inode, return it.
2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return &UDE;
2661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Otherwise, we don't have this directory yet, add it.  We use the string
2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // key from the DirEntries map as the string.
2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  UDE.Name  = InterndDirName;
2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  return &UDE;
2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFile - Lookup, cache, and verify the specified file.  This returns null
2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if the file doesn't exist.
2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///
27639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattnerconst FileEntry *FileManager::getFile(llvm::StringRef Filename) {
2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ++NumFileLookups;
2781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // See if there is already an entry in the map.
2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
281f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner    FileEntries.GetOrCreateValue(Filename);
2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // See if there is already an entry in the map.
2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (NamedFileEnt.getValue())
2853d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek    return NamedFileEnt.getValue() == NON_EXISTENT_FILE
2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                 ? 0 : NamedFileEnt.getValue();
2871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ++NumFileCacheMisses;
2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // By default, initialize it to invalid.
2913d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek  NamedFileEnt.setValue(NON_EXISTENT_FILE);
2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Get the null-terminated file name as stored as the key of the
2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // FileEntries map.
2965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *InterndFileName = NamedFileEnt.getKeyData();
2971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
298f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner
299f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  // Look up the directory for the file.  When looking up something like
300f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  // sys/foo.h we'll discover all of the search directories that have a 'sys'
301f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  // subdirectory.  This will let us avoid having to waste time on known-to-fail
302f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  // searches when we go to find sys/bar.h, because all the search directories
303f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner  // without a 'sys' subdir will get a cached failure result.
30439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner  const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename);
305057e567f1b375190779e5341f42861896cdee442Douglas Gregor  if (DirInfo == 0)  // Directory doesn't exist, file can't exist.
306057e567f1b375190779e5341f42861896cdee442Douglas Gregor    return 0;
307057e567f1b375190779e5341f42861896cdee442Douglas Gregor
3085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // FIXME: Use the directory info to prune this, before doing the stat syscall.
3095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // FIXME: This will reduce the # syscalls.
3101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Nope, there isn't.  Check to see if the file exists.
312898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  int FileDescriptor = -1;
3135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  struct stat StatBuf;
314898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  if (getStatValue(InterndFileName, StatBuf, &FileDescriptor))
3155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return 0;
3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
317bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek  // It exists.  See if we have already opened a file with the same inode.
3185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // This occurs when one dir is symlinked to another, for example.
3196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf);
3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  NamedFileEnt.setValue(&UFE);
322898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  if (UFE.getName()) { // Already have an entry with this inode, return it.
323898a061f69e1145bf89a987c08203132b9922a3cChris Lattner    // If the stat process opened the file, close it to avoid a FD leak.
324898a061f69e1145bf89a987c08203132b9922a3cChris Lattner    if (FileDescriptor != -1)
325898a061f69e1145bf89a987c08203132b9922a3cChris Lattner      close(FileDescriptor);
326898a061f69e1145bf89a987c08203132b9922a3cChris Lattner
3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return &UFE;
328898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  }
3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Otherwise, we don't have this directory yet, add it.
3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // FIXME: Change the name to be a char* that points back to the 'FileEntries'
3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // key.
3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  UFE.Name    = InterndFileName;
3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  UFE.Size    = StatBuf.st_size;
3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  UFE.ModTime = StatBuf.st_mtime;
3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  UFE.Dir     = DirInfo;
3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  UFE.UID     = NextFileUID++;
338898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  UFE.FD      = FileDescriptor;
3395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  return &UFE;
3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
342057e567f1b375190779e5341f42861896cdee442Douglas Gregorconst FileEntry *
343ec1b1cc006cef19e0a95d0ea6fbfd37d0d615066Benjamin KramerFileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
34439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner                            time_t ModificationTime) {
345057e567f1b375190779e5341f42861896cdee442Douglas Gregor  ++NumFileLookups;
346057e567f1b375190779e5341f42861896cdee442Douglas Gregor
347057e567f1b375190779e5341f42861896cdee442Douglas Gregor  // See if there is already an entry in the map.
348057e567f1b375190779e5341f42861896cdee442Douglas Gregor  llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
349f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner    FileEntries.GetOrCreateValue(Filename);
350057e567f1b375190779e5341f42861896cdee442Douglas Gregor
351057e567f1b375190779e5341f42861896cdee442Douglas Gregor  // See if there is already an entry in the map.
352057e567f1b375190779e5341f42861896cdee442Douglas Gregor  if (NamedFileEnt.getValue())
353057e567f1b375190779e5341f42861896cdee442Douglas Gregor    return NamedFileEnt.getValue() == NON_EXISTENT_FILE
354057e567f1b375190779e5341f42861896cdee442Douglas Gregor                 ? 0 : NamedFileEnt.getValue();
355057e567f1b375190779e5341f42861896cdee442Douglas Gregor
356057e567f1b375190779e5341f42861896cdee442Douglas Gregor  ++NumFileCacheMisses;
357057e567f1b375190779e5341f42861896cdee442Douglas Gregor
358057e567f1b375190779e5341f42861896cdee442Douglas Gregor  // By default, initialize it to invalid.
359057e567f1b375190779e5341f42861896cdee442Douglas Gregor  NamedFileEnt.setValue(NON_EXISTENT_FILE);
360057e567f1b375190779e5341f42861896cdee442Douglas Gregor
36139b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner  const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename);
362057e567f1b375190779e5341f42861896cdee442Douglas Gregor  if (DirInfo == 0)  // Directory doesn't exist, file can't exist.
363057e567f1b375190779e5341f42861896cdee442Douglas Gregor    return 0;
364057e567f1b375190779e5341f42861896cdee442Douglas Gregor
365057e567f1b375190779e5341f42861896cdee442Douglas Gregor  FileEntry *UFE = new FileEntry();
366057e567f1b375190779e5341f42861896cdee442Douglas Gregor  VirtualFileEntries.push_back(UFE);
367057e567f1b375190779e5341f42861896cdee442Douglas Gregor  NamedFileEnt.setValue(UFE);
368057e567f1b375190779e5341f42861896cdee442Douglas Gregor
369f9f7766846a205bc900b578f944567e679b221aaChris Lattner  // Get the null-terminated file name as stored as the key of the
370f9f7766846a205bc900b578f944567e679b221aaChris Lattner  // FileEntries map.
371f9f7766846a205bc900b578f944567e679b221aaChris Lattner  const char *InterndFileName = NamedFileEnt.getKeyData();
372f9f7766846a205bc900b578f944567e679b221aaChris Lattner
373f9f7766846a205bc900b578f944567e679b221aaChris Lattner  UFE->Name    = InterndFileName;
374057e567f1b375190779e5341f42861896cdee442Douglas Gregor  UFE->Size    = Size;
375057e567f1b375190779e5341f42861896cdee442Douglas Gregor  UFE->ModTime = ModificationTime;
376057e567f1b375190779e5341f42861896cdee442Douglas Gregor  UFE->Dir     = DirInfo;
377057e567f1b375190779e5341f42861896cdee442Douglas Gregor  UFE->UID     = NextFileUID++;
3783e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor
3793e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor  // If this virtual file resolves to a file, also map that file to the
3803e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor  // newly-created file entry.
381898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  int FileDescriptor = -1;
3823e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor  struct stat StatBuf;
383898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  if (getStatValue(InterndFileName, StatBuf, &FileDescriptor))
384f9f7766846a205bc900b578f944567e679b221aaChris Lattner    return UFE;
385898a061f69e1145bf89a987c08203132b9922a3cChris Lattner
386898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  UFE->FD = FileDescriptor;
387f9f7766846a205bc900b578f944567e679b221aaChris Lattner  llvm::sys::Path FilePath(UFE->Name);
388f9f7766846a205bc900b578f944567e679b221aaChris Lattner  FilePath.makeAbsolute();
389f9f7766846a205bc900b578f944567e679b221aaChris Lattner  FileEntries[FilePath.str()] = UFE;
390057e567f1b375190779e5341f42861896cdee442Douglas Gregor  return UFE;
391057e567f1b375190779e5341f42861896cdee442Douglas Gregor}
392057e567f1b375190779e5341f42861896cdee442Douglas Gregor
39367452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattnervoid FileManager::FixupRelativePath(llvm::sys::Path &path,
39467452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner                                    const FileSystemOptions &FSOpts) {
395256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer  if (FSOpts.WorkingDir.empty() || llvm::sys::path::is_absolute(path.str()))
396256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer    return;
397256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer
398256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer  llvm::SmallString<128> NewPath(FSOpts.WorkingDir);
399256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer  llvm::sys::path::append(NewPath, path.str());
40067452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner  path = NewPath;
40167452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner}
40267452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner
40375dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattnerllvm::MemoryBuffer *FileManager::
40475dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(const FileEntry *Entry, std::string *ErrorStr) {
4054eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  llvm::OwningPtr<llvm::MemoryBuffer> Result;
4063a321e23f66128dbb986343927456ff6702af617Michael J. Spencer  llvm::error_code ec;
4075cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner  if (FileSystemOpts.WorkingDir.empty()) {
4085cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner    const char *Filename = Entry->getName();
4095cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner    // If the file is already open, use the open file descriptor.
4105cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner    if (Entry->FD != -1) {
4114eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer      ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result,
4124eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer                                           Entry->getSize());
4134eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer      if (ErrorStr)
4143a321e23f66128dbb986343927456ff6702af617Michael J. Spencer        *ErrorStr = ec.message();
4155cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner      // getOpenFile will have closed the file descriptor, don't reuse or
4165cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner      // reclose it.
4175cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner      Entry->FD = -1;
4184eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer      return Result.take();
4195cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner    }
4205cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner
4215cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner    // Otherwise, open the file.
4224eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer    ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize());
4234eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer    if (ec && ErrorStr)
4243a321e23f66128dbb986343927456ff6702af617Michael J. Spencer      *ErrorStr = ec.message();
4254eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer    return Result.take();
4265cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner  }
42775dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner
4285cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner  llvm::sys::Path FilePath(Entry->getName());
42975dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner  FixupRelativePath(FilePath, FileSystemOpts);
4304eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result, Entry->getSize());
4314eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  if (ec && ErrorStr)
4323a321e23f66128dbb986343927456ff6702af617Michael J. Spencer    *ErrorStr = ec.message();
4334eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  return Result.take();
43475dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner}
43567452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner
436f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerllvm::MemoryBuffer *FileManager::
43775dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) {
4384eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  llvm::OwningPtr<llvm::MemoryBuffer> Result;
4393a321e23f66128dbb986343927456ff6702af617Michael J. Spencer  llvm::error_code ec;
4403a321e23f66128dbb986343927456ff6702af617Michael J. Spencer  if (FileSystemOpts.WorkingDir.empty()) {
4414eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer    ec = llvm::MemoryBuffer::getFile(Filename, Result);
4424eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer    if (ec && ErrorStr)
4433a321e23f66128dbb986343927456ff6702af617Michael J. Spencer      *ErrorStr = ec.message();
4444eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer    return Result.take();
4453a321e23f66128dbb986343927456ff6702af617Michael J. Spencer  }
4463a321e23f66128dbb986343927456ff6702af617Michael J. Spencer
44767452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner  llvm::sys::Path FilePath(Filename);
448389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  FixupRelativePath(FilePath, FileSystemOpts);
4494eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result);
4504eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  if (ec && ErrorStr)
4513a321e23f66128dbb986343927456ff6702af617Michael J. Spencer    *ErrorStr = ec.message();
4524eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer  return Result.take();
453389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis}
454389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis
45510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner/// getStatValue - Get the 'stat' information for the specified path, using the
456c0f31fd08537b65ad92db8ce860747e3402a07e6Chris Lattner/// cache to accelerate it if possible.  This returns true if the path does not
45710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner/// exist or false if it exists.
458f9f7766846a205bc900b578f944567e679b221aaChris Lattner///
459f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// The isForDir member indicates whether this is a directory lookup or not.
460f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// This will return failure if the lookup isn't the expected kind.
461f9f7766846a205bc900b578f944567e679b221aaChris Lattnerbool FileManager::getStatValue(const char *Path, struct stat &StatBuf,
462898a061f69e1145bf89a987c08203132b9922a3cChris Lattner                               int *FileDescriptor) {
46310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
46410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  // absolute!
46511aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner  if (FileSystemOpts.WorkingDir.empty())
466898a061f69e1145bf89a987c08203132b9922a3cChris Lattner    return FileSystemStatCache::get(Path, StatBuf, FileDescriptor,
467898a061f69e1145bf89a987c08203132b9922a3cChris Lattner                                    StatCache.get());
46810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner
46910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  llvm::sys::Path FilePath(Path);
470389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  FixupRelativePath(FilePath, FileSystemOpts);
47111aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner
472898a061f69e1145bf89a987c08203132b9922a3cChris Lattner  return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor,
473898a061f69e1145bf89a987c08203132b9922a3cChris Lattner                                  StatCache.get());
474389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis}
475389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis
47610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner
47710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner
4785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const {
4796cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << "\n*** File Manager Stats:\n";
4806cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << UniqueFiles.size() << " files found, "
4816cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer               << UniqueDirs.size() << " dirs found.\n";
4826cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << NumDirLookups << " dir lookups, "
4836cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer               << NumDirCacheMisses << " dir cache misses.\n";
4846cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << NumFileLookups << " file lookups, "
4856cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer               << NumFileCacheMisses << " file cache misses.\n";
4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4876cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
4885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
4894fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor
490