FileManager.cpp revision cb8d58b82859d2c56b679b901de38f416e2b6f48
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" 25cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek#include "llvm/Support/Allocator.h" 266bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#include "llvm/Config/config.h" 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields. 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h> 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 32a8c11c6a7831df37f2f40b34072360b04f6d19a8Chris Lattner#if defined(_MSC_VER) 33a8c11c6a7831df37f2f40b34072360b04f6d19a8Chris Lattner#define S_ISDIR(s) (_S_IFDIR & s) 34a8c11c6a7831df37f2f40b34072360b04f6d19a8Chris Lattner#endif 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 363d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk. 383d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 40cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 41cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows. 42cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 43cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 446bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32 456bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 466bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\') 476bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 486bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremeneknamespace { 496bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek static std::string GetFullPath(const char *relPath) 506bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek { 516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek char *absPathStrPtr = _fullpath(NULL, relPath, 0); 526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek assert(absPathStrPtr && "_fullpath() returned NULL!"); 536bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 546bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string absPath(absPathStrPtr); 556bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 566bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek free(absPathStrPtr); 576bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return absPath; 586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 616bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 626bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from full path to existing directories/files. 636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek llvm::StringMap<DirectoryEntry> UniqueDirs; 656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 666bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 686bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 696bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs.GetOrCreateValue( 706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str(), 716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str() + FullPath.size() 726bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek ).getValue(); 736bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 746bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueDirs.size(); } 766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 776bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from full path to existing directories/files. 806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek llvm::StringMap<FileEntry> UniqueFiles; 826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 836bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 846bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 856bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 866bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueFiles.GetOrCreateValue( 876bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str(), 886bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str() + FullPath.size() 896bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek ).getValue(); 906bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 916bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueFiles.size(); } 936bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 946bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 95cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 96cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems. 97cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 98cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else 1006bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1016bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/') 1026bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1036bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 1046bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from ID's to existing directories/files. 1056bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 1076bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1086bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1096bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 1106bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 1116bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1126bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1136bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueDirs.size(); } 1146bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1156bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1166bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1176bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from ID's to existing directories/files. 1186bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 1196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::set<FileEntry> UniqueFiles; 1206bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1216bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 1236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return 1246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek const_cast<FileEntry&>( 1256bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 1266bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek StatBuf.st_ino)).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 1386bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::FileManager() : UniqueDirs(*new UniqueDirContainer), 1396bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek UniqueFiles(*new UniqueFileContainer), 1406bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirEntries(64), FileEntries(64), NextFileUID(0) 1416bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek{ 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 1516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDirectory - Lookup, cache, and verify the specified directory. This 1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// returns null if the directory doesn't exist. 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst DirectoryEntry *FileManager::getDirectory(const char *NameStart, 1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *NameEnd) { 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DirEntries.GetOrCreateValue(NameStart, NameEnd); 1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 1625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 1633d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedDirEnt.getValue() == NON_EXISTENT_DIR 1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedDirEnt.getValue(); 1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 1693d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // DirEntries map. 1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 1745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (stat(InterndDirName, &StatBuf) || // Error stat'ing. 1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer !S_ISDIR(StatBuf.st_mode)) // Not a directory? 1795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // It exists. See if we have already opened a directory with the same inode. 182da9954400aab56bc3df60eb1b7be2489121c6166Ted Kremenek // This occurs when one dir is symlinked to another, for example. 1836bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf); 1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UDE.getName()) // Already have an entry with this inode, return it. 1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 1885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. We use the string 1905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key from the DirEntries map as the string. 1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UDE.Name = InterndDirName; 1925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 1935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1953d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_FILE - A special value distinct from null that is used to 1965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a filename that doesn't exist on the disk. 1973d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 1985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFile - Lookup, cache, and verify the specified file. This returns null 2005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if the file doesn't exist. 2015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 2025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst FileEntry *FileManager::getFile(const char *NameStart, 2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *NameEnd) { 2045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 2055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 2085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileEntries.GetOrCreateValue(NameStart, NameEnd); 2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 2123d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedFileEnt.getValue(); 2145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2183d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Figure out what directory it is in. If the string contains a / in it, 2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // strip off everything after it. 2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: this logic should be in sys::Path. 2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *SlashPos = NameEnd-1; 2246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0])) 2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer --SlashPos; 2265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const DirectoryEntry *DirInfo; 2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (SlashPos < NameStart) { 2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Use the current directory if file has no path component. 2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *Name = "."; 2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DirInfo = getDirectory(Name, Name+1); 2325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } else if (SlashPos == NameEnd-1) 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; // If filename ends with a /, it's a directory. 2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer else 2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DirInfo = getDirectory(NameStart, SlashPos); 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (DirInfo == 0) // Directory doesn't exist, file can't exist. 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FileEntries map. 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 2485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 2493d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << "STATING: " << Filename; 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (stat(InterndFileName, &StatBuf) || // Error stat'ing. 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer S_ISDIR(StatBuf.st_mode)) { // A directory? 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this file doesn't exist, we leave a null in FileEntries for this path. 2533d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << ": Not existing\n"; 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2563d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << ": exists\n"; 2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 258bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 2606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf); 2615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UFE.getName()) // Already have an entry with this inode, return it. 2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Change the name to be a char* that points back to the 'FileEntries' 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key. 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Name = InterndFileName; 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Size = StatBuf.st_size; 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.ModTime = StatBuf.st_mtime; 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 2783d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << "\n*** File Manager Stats:\n"; 2793d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << UniqueFiles.size() << " files found, " 2803d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek << UniqueDirs.size() << " dirs found.\n"; 2813d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << NumDirLookups << " dir lookups, " 2823d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek << NumDirCacheMisses << " dir cache misses.\n"; 2833d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek llvm::cerr << NumFileLookups << " file lookups, " 2843d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek << NumFileCacheMisses << " file cache misses.\n"; 2853d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek 2863d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek //llvm::cerr << PagesMapped << BytesOfPagesMapped << FSLookups; 2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 288