FileManager.cpp revision 96438f319bb07d9a40564b5e01333f82c0c8a61e
18fbc88e5faee291e2e5039ec4c1dac3cfd219704Ted Kremenek///===--- 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" 215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/SmallString.h" 229551a2cbe5fdf316c126a39ec310208c2121321fTed Kremenek#include "llvm/Bitcode/Serialize.h" 239551a2cbe5fdf316c126a39ec310208c2121321fTed Kremenek#include "llvm/Bitcode/Deserialize.h" 243d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#include "llvm/Support/Streams.h" 256bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#include "llvm/Config/config.h" 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields. 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h> 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 31a8c11c6a7831df37f2f40b34072360b04f6d19a8Chris Lattner#if defined(_MSC_VER) 323102c83f6eac0cbbd698471173672c3e47a6914cChris Lattner#define S_ISDIR(s) (_S_IFDIR & s) 33a8c11c6a7831df37f2f40b34072360b04f6d19a8Chris Lattner#endif 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 39cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 40cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows. 41cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 42cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 436bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32 446bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 456bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\') 466bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 476bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremeneknamespace { 486bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek static std::string GetFullPath(const char *relPath) 496bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek { 506bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek char *absPathStrPtr = _fullpath(NULL, relPath, 0); 516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek assert(absPathStrPtr && "_fullpath() returned NULL!"); 526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 536bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string absPath(absPathStrPtr); 546bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 556bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek free(absPathStrPtr); 566bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return absPath; 576bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 616bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from full path to existing directories/files. 626bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek llvm::StringMap<DirectoryEntry> UniqueDirs; 646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 666bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 686bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs.GetOrCreateValue( 696bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str(), 706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str() + FullPath.size() 716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek ).getValue(); 726bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 736bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 746bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueDirs.size(); } 756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 776bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from full path to existing directories/files. 796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 8075368893339d89f6523c312b0a0eb23d438b6dffTed Kremenek llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles; 816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 836bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 846bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 856bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueFiles.GetOrCreateValue( 866bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str(), 876bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str() + FullPath.size() 886bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek ).getValue(); 896bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 906bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 916bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueFiles.size(); } 926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 936bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 94cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 95cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems. 96cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 97cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 986bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else 996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1006bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/') 1016bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1026bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 1036bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from ID's to existing directories/files. 1046bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 1056bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1076bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1086bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 1096bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 1106bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1116bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1126bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueDirs.size(); } 1136bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1146bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1156bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1166bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from ID's to existing directories/files. 1176bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 1186bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::set<FileEntry> UniqueFiles; 1196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1206bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1216bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return 1236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek const_cast<FileEntry&>( 1246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 12596438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_ino, 12696438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_mode)).first); 1276bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1286bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1296bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueFiles.size(); } 1306bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1316bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1326bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#endif 1336bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 134cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 135cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic. 136cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 1376bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 13896438f319bb07d9a40564b5e01333f82c0c8a61eTed KremenekFileManager::FileManager() 139fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek : UniqueDirs(*new UniqueDirContainer), 140fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek UniqueFiles(*new UniqueFileContainer), 14196438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek DirEntries(64), FileEntries(64), NextFileUID(0) { 1426bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirLookups = NumFileLookups = 0; 1436bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirCacheMisses = NumFileCacheMisses = 0; 1446bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1456bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1466bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() { 1476bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueDirs; 1486bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueFiles; 1496bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1506bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDirectory - Lookup, cache, and verify the specified directory. This 1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// returns null if the directory doesn't exist. 1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst DirectoryEntry *FileManager::getDirectory(const char *NameStart, 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *NameEnd) { 1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DirEntries.GetOrCreateValue(NameStart, NameEnd); 1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 1623d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedDirEnt.getValue() == NON_EXISTENT_DIR 1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedDirEnt.getValue(); 1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 1683d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // DirEntries map. 1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 176fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek if (stat_cached(InterndDirName, &StatBuf) || // Error stat'ing. 1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer !S_ISDIR(StatBuf.st_mode)) // Not a directory? 1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // It exists. See if we have already opened a directory with the same inode. 181da9954400aab56bc3df60eb1b7be2489121c6166Ted Kremenek // This occurs when one dir is symlinked to another, for example. 1826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf); 1835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UDE.getName()) // Already have an entry with this inode, return it. 1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. We use the string 1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key from the DirEntries map as the string. 1905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UDE.Name = InterndDirName; 1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 1925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1943d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_FILE - A special value distinct from null that is used to 1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a filename that doesn't exist on the disk. 1963d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 1975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFile - Lookup, cache, and verify the specified file. This returns null 1995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if the file doesn't exist. 2005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 2015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst FileEntry *FileManager::getFile(const char *NameStart, 2025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *NameEnd) { 2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 2045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileEntries.GetOrCreateValue(NameStart, NameEnd); 2085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 2113d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 2125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedFileEnt.getValue(); 2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2173d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Figure out what directory it is in. If the string contains a / in it, 2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // strip off everything after it. 2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: this logic should be in sys::Path. 2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *SlashPos = NameEnd-1; 2236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0])) 2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer --SlashPos; 2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const DirectoryEntry *DirInfo; 2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (SlashPos < NameStart) { 2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Use the current directory if file has no path component. 2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *Name = "."; 2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DirInfo = getDirectory(Name, Name+1); 2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } else if (SlashPos == NameEnd-1) 2325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; // If filename ends with a /, it's a directory. 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer else 2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DirInfo = getDirectory(NameStart, SlashPos); 2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (DirInfo == 0) // Directory doesn't exist, file can't exist. 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FileEntries map. 2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 2483d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << "STATING: " << Filename; 249fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek if (stat_cached(InterndFileName, &StatBuf) || // Error stat'ing. 250fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek S_ISDIR(StatBuf.st_mode)) { // A directory? 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this file doesn't exist, we leave a null in FileEntries for this path. 2523d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << ": Not existing\n"; 2535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2553d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << ": exists\n"; 2565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 257bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 2596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf); 2605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 2625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UFE.getName()) // Already have an entry with this inode, return it. 2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Change the name to be a char* that points back to the 'FileEntries' 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key. 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Name = InterndFileName; 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Size = StatBuf.st_size; 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.ModTime = StatBuf.st_mtime; 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 2773d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << "\n*** File Manager Stats:\n"; 2783d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << UniqueFiles.size() << " files found, " 2793d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek << UniqueDirs.size() << " dirs found.\n"; 2803d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << NumDirLookups << " dir lookups, " 2813d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek << NumDirCacheMisses << " dir cache misses.\n"; 2823d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << NumFileLookups << " file lookups, " 2833d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek << NumFileCacheMisses << " file cache misses.\n"; 2843d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek 2853d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << PagesMapped << BytesOfPagesMapped << FSLookups; 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 287