1 //===--- FileManager.cpp - File System Probing and Caching ----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the FileManager interface. 11 // 12 //===----------------------------------------------------------------------===// 13 // 14 // TODO: This should index all interesting directories with dirent calls. 15 // getdirentries ? 16 // opendir/readdir_r/closedir ? 17 // 18 //===----------------------------------------------------------------------===// 19 20 #include "clang/Basic/FileManager.h" 21 #include "clang/Basic/FileSystemStatCache.h" 22 #include "llvm/ADT/SmallString.h" 23 #include "llvm/Support/FileSystem.h" 24 #include "llvm/Support/MemoryBuffer.h" 25 #include "llvm/Support/raw_ostream.h" 26 #include "llvm/Support/Path.h" 27 #include "llvm/Support/system_error.h" 28 #include "llvm/Config/llvm-config.h" 29 #include <map> 30 #include <set> 31 #include <string> 32 33 // FIXME: This is terrible, we need this for ::close. 34 #if !defined(_MSC_VER) && !defined(__MINGW32__) 35 #include <unistd.h> 36 #include <sys/uio.h> 37 #else 38 #include <io.h> 39 #endif 40 using namespace clang; 41 42 // FIXME: Enhance libsystem to support inode and other fields. 43 #include <sys/stat.h> 44 45 /// NON_EXISTENT_DIR - A special value distinct from null that is used to 46 /// represent a dir name that doesn't exist on the disk. 47 #define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 48 49 /// NON_EXISTENT_FILE - A special value distinct from null that is used to 50 /// represent a filename that doesn't exist on the disk. 51 #define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 52 53 54 FileEntry::~FileEntry() { 55 // If this FileEntry owns an open file descriptor that never got used, close 56 // it. 57 if (FD != -1) ::close(FD); 58 } 59 60 bool FileEntry::isNamedPipe() const { 61 return FileMode & S_IFIFO; 62 } 63 64 //===----------------------------------------------------------------------===// 65 // Windows. 66 //===----------------------------------------------------------------------===// 67 68 #ifdef LLVM_ON_WIN32 69 70 namespace { 71 static std::string GetFullPath(const char *relPath) { 72 char *absPathStrPtr = _fullpath(NULL, relPath, 0); 73 assert(absPathStrPtr && "_fullpath() returned NULL!"); 74 75 std::string absPath(absPathStrPtr); 76 77 free(absPathStrPtr); 78 return absPath; 79 } 80 } 81 82 class FileManager::UniqueDirContainer { 83 /// UniqueDirs - Cache from full path to existing directories/files. 84 /// 85 llvm::StringMap<DirectoryEntry> UniqueDirs; 86 87 public: 88 /// getDirectory - Return an existing DirectoryEntry with the given 89 /// name if there is already one; otherwise create and return a 90 /// default-constructed DirectoryEntry. 91 DirectoryEntry &getDirectory(const char *Name, 92 const struct stat & /*StatBuf*/) { 93 std::string FullPath(GetFullPath(Name)); 94 return UniqueDirs.GetOrCreateValue(FullPath).getValue(); 95 } 96 97 size_t size() const { return UniqueDirs.size(); } 98 }; 99 100 class FileManager::UniqueFileContainer { 101 /// UniqueFiles - Cache from full path to existing directories/files. 102 /// 103 llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles; 104 105 public: 106 /// getFile - Return an existing FileEntry with the given name if 107 /// there is already one; otherwise create and return a 108 /// default-constructed FileEntry. 109 FileEntry &getFile(const char *Name, const struct stat & /*StatBuf*/) { 110 std::string FullPath(GetFullPath(Name)); 111 112 // Lowercase string because Windows filesystem is case insensitive. 113 FullPath = StringRef(FullPath).lower(); 114 return UniqueFiles.GetOrCreateValue(FullPath).getValue(); 115 } 116 117 size_t size() const { return UniqueFiles.size(); } 118 119 void erase(const FileEntry *Entry) { 120 std::string FullPath(GetFullPath(Entry->getName())); 121 122 // Lowercase string because Windows filesystem is case insensitive. 123 FullPath = StringRef(FullPath).lower(); 124 UniqueFiles.erase(FullPath); 125 } 126 }; 127 128 //===----------------------------------------------------------------------===// 129 // Unix-like Systems. 130 //===----------------------------------------------------------------------===// 131 132 #else 133 134 class FileManager::UniqueDirContainer { 135 /// UniqueDirs - Cache from ID's to existing directories/files. 136 std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 137 138 public: 139 /// getDirectory - Return an existing DirectoryEntry with the given 140 /// ID's if there is already one; otherwise create and return a 141 /// default-constructed DirectoryEntry. 142 DirectoryEntry &getDirectory(const char * /*Name*/, 143 const struct stat &StatBuf) { 144 return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 145 } 146 147 size_t size() const { return UniqueDirs.size(); } 148 }; 149 150 class FileManager::UniqueFileContainer { 151 /// UniqueFiles - Cache from ID's to existing directories/files. 152 std::set<FileEntry> UniqueFiles; 153 154 public: 155 /// getFile - Return an existing FileEntry with the given ID's if 156 /// there is already one; otherwise create and return a 157 /// default-constructed FileEntry. 158 FileEntry &getFile(const char * /*Name*/, const struct stat &StatBuf) { 159 return 160 const_cast<FileEntry&>( 161 *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 162 StatBuf.st_ino, 163 StatBuf.st_mode)).first); 164 } 165 166 size_t size() const { return UniqueFiles.size(); } 167 168 void erase(const FileEntry *Entry) { UniqueFiles.erase(*Entry); } 169 }; 170 171 #endif 172 173 //===----------------------------------------------------------------------===// 174 // Common logic. 175 //===----------------------------------------------------------------------===// 176 177 FileManager::FileManager(const FileSystemOptions &FSO) 178 : FileSystemOpts(FSO), 179 UniqueRealDirs(*new UniqueDirContainer()), 180 UniqueRealFiles(*new UniqueFileContainer()), 181 SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { 182 NumDirLookups = NumFileLookups = 0; 183 NumDirCacheMisses = NumFileCacheMisses = 0; 184 } 185 186 FileManager::~FileManager() { 187 delete &UniqueRealDirs; 188 delete &UniqueRealFiles; 189 for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i) 190 delete VirtualFileEntries[i]; 191 for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i) 192 delete VirtualDirectoryEntries[i]; 193 } 194 195 void FileManager::addStatCache(FileSystemStatCache *statCache, 196 bool AtBeginning) { 197 assert(statCache && "No stat cache provided?"); 198 if (AtBeginning || StatCache.get() == 0) { 199 statCache->setNextStatCache(StatCache.take()); 200 StatCache.reset(statCache); 201 return; 202 } 203 204 FileSystemStatCache *LastCache = StatCache.get(); 205 while (LastCache->getNextStatCache()) 206 LastCache = LastCache->getNextStatCache(); 207 208 LastCache->setNextStatCache(statCache); 209 } 210 211 void FileManager::removeStatCache(FileSystemStatCache *statCache) { 212 if (!statCache) 213 return; 214 215 if (StatCache.get() == statCache) { 216 // This is the first stat cache. 217 StatCache.reset(StatCache->takeNextStatCache()); 218 return; 219 } 220 221 // Find the stat cache in the list. 222 FileSystemStatCache *PrevCache = StatCache.get(); 223 while (PrevCache && PrevCache->getNextStatCache() != statCache) 224 PrevCache = PrevCache->getNextStatCache(); 225 226 assert(PrevCache && "Stat cache not found for removal"); 227 PrevCache->setNextStatCache(statCache->getNextStatCache()); 228 } 229 230 void FileManager::clearStatCaches() { 231 StatCache.reset(0); 232 } 233 234 /// \brief Retrieve the directory that the given file name resides in. 235 /// Filename can point to either a real file or a virtual file. 236 static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 237 StringRef Filename, 238 bool CacheFailure) { 239 if (Filename.empty()) 240 return NULL; 241 242 if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) 243 return NULL; // If Filename is a directory. 244 245 StringRef DirName = llvm::sys::path::parent_path(Filename); 246 // Use the current directory if file has no path component. 247 if (DirName.empty()) 248 DirName = "."; 249 250 return FileMgr.getDirectory(DirName, CacheFailure); 251 } 252 253 /// Add all ancestors of the given path (pointing to either a file or 254 /// a directory) as virtual directories. 255 void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { 256 StringRef DirName = llvm::sys::path::parent_path(Path); 257 if (DirName.empty()) 258 return; 259 260 llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 261 SeenDirEntries.GetOrCreateValue(DirName); 262 263 // When caching a virtual directory, we always cache its ancestors 264 // at the same time. Therefore, if DirName is already in the cache, 265 // we don't need to recurse as its ancestors must also already be in 266 // the cache. 267 if (NamedDirEnt.getValue()) 268 return; 269 270 // Add the virtual directory to the cache. 271 DirectoryEntry *UDE = new DirectoryEntry; 272 UDE->Name = NamedDirEnt.getKeyData(); 273 NamedDirEnt.setValue(UDE); 274 VirtualDirectoryEntries.push_back(UDE); 275 276 // Recursively add the other ancestors. 277 addAncestorsAsVirtualDirs(DirName); 278 } 279 280 const DirectoryEntry *FileManager::getDirectory(StringRef DirName, 281 bool CacheFailure) { 282 // stat doesn't like trailing separators except for root directory. 283 // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'. 284 // (though it can strip '\\') 285 if (DirName.size() > 1 && 286 DirName != llvm::sys::path::root_path(DirName) && 287 llvm::sys::path::is_separator(DirName.back())) 288 DirName = DirName.substr(0, DirName.size()-1); 289 290 ++NumDirLookups; 291 llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 292 SeenDirEntries.GetOrCreateValue(DirName); 293 294 // See if there was already an entry in the map. Note that the map 295 // contains both virtual and real directories. 296 if (NamedDirEnt.getValue()) 297 return NamedDirEnt.getValue() == NON_EXISTENT_DIR 298 ? 0 : NamedDirEnt.getValue(); 299 300 ++NumDirCacheMisses; 301 302 // By default, initialize it to invalid. 303 NamedDirEnt.setValue(NON_EXISTENT_DIR); 304 305 // Get the null-terminated directory name as stored as the key of the 306 // SeenDirEntries map. 307 const char *InterndDirName = NamedDirEnt.getKeyData(); 308 309 // Check to see if the directory exists. 310 struct stat StatBuf; 311 if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/)) { 312 // There's no real directory at the given path. 313 if (!CacheFailure) 314 SeenDirEntries.erase(DirName); 315 return 0; 316 } 317 318 // It exists. See if we have already opened a directory with the 319 // same inode (this occurs on Unix-like systems when one dir is 320 // symlinked to another, for example) or the same path (on 321 // Windows). 322 DirectoryEntry &UDE = UniqueRealDirs.getDirectory(InterndDirName, StatBuf); 323 324 NamedDirEnt.setValue(&UDE); 325 if (!UDE.getName()) { 326 // We don't have this directory yet, add it. We use the string 327 // key from the SeenDirEntries map as the string. 328 UDE.Name = InterndDirName; 329 } 330 331 return &UDE; 332 } 333 334 const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, 335 bool CacheFailure) { 336 ++NumFileLookups; 337 338 // See if there is already an entry in the map. 339 llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 340 SeenFileEntries.GetOrCreateValue(Filename); 341 342 // See if there is already an entry in the map. 343 if (NamedFileEnt.getValue()) 344 return NamedFileEnt.getValue() == NON_EXISTENT_FILE 345 ? 0 : NamedFileEnt.getValue(); 346 347 ++NumFileCacheMisses; 348 349 // By default, initialize it to invalid. 350 NamedFileEnt.setValue(NON_EXISTENT_FILE); 351 352 // Get the null-terminated file name as stored as the key of the 353 // SeenFileEntries map. 354 const char *InterndFileName = NamedFileEnt.getKeyData(); 355 356 // Look up the directory for the file. When looking up something like 357 // sys/foo.h we'll discover all of the search directories that have a 'sys' 358 // subdirectory. This will let us avoid having to waste time on known-to-fail 359 // searches when we go to find sys/bar.h, because all the search directories 360 // without a 'sys' subdir will get a cached failure result. 361 const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 362 CacheFailure); 363 if (DirInfo == 0) { // Directory doesn't exist, file can't exist. 364 if (!CacheFailure) 365 SeenFileEntries.erase(Filename); 366 367 return 0; 368 } 369 370 // FIXME: Use the directory info to prune this, before doing the stat syscall. 371 // FIXME: This will reduce the # syscalls. 372 373 // Nope, there isn't. Check to see if the file exists. 374 int FileDescriptor = -1; 375 struct stat StatBuf; 376 if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) { 377 // There's no real file at the given path. 378 if (!CacheFailure) 379 SeenFileEntries.erase(Filename); 380 381 return 0; 382 } 383 384 if (FileDescriptor != -1 && !openFile) { 385 close(FileDescriptor); 386 FileDescriptor = -1; 387 } 388 389 // It exists. See if we have already opened a file with the same inode. 390 // This occurs when one dir is symlinked to another, for example. 391 FileEntry &UFE = UniqueRealFiles.getFile(InterndFileName, StatBuf); 392 393 NamedFileEnt.setValue(&UFE); 394 if (UFE.getName()) { // Already have an entry with this inode, return it. 395 // If the stat process opened the file, close it to avoid a FD leak. 396 if (FileDescriptor != -1) 397 close(FileDescriptor); 398 399 return &UFE; 400 } 401 402 // Otherwise, we don't have this directory yet, add it. 403 // FIXME: Change the name to be a char* that points back to the 404 // 'SeenFileEntries' key. 405 UFE.Name = InterndFileName; 406 UFE.Size = StatBuf.st_size; 407 UFE.ModTime = StatBuf.st_mtime; 408 UFE.Dir = DirInfo; 409 UFE.UID = NextFileUID++; 410 UFE.FD = FileDescriptor; 411 return &UFE; 412 } 413 414 const FileEntry * 415 FileManager::getVirtualFile(StringRef Filename, off_t Size, 416 time_t ModificationTime) { 417 ++NumFileLookups; 418 419 // See if there is already an entry in the map. 420 llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 421 SeenFileEntries.GetOrCreateValue(Filename); 422 423 // See if there is already an entry in the map. 424 if (NamedFileEnt.getValue() && NamedFileEnt.getValue() != NON_EXISTENT_FILE) 425 return NamedFileEnt.getValue(); 426 427 ++NumFileCacheMisses; 428 429 // By default, initialize it to invalid. 430 NamedFileEnt.setValue(NON_EXISTENT_FILE); 431 432 addAncestorsAsVirtualDirs(Filename); 433 FileEntry *UFE = 0; 434 435 // Now that all ancestors of Filename are in the cache, the 436 // following call is guaranteed to find the DirectoryEntry from the 437 // cache. 438 const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 439 /*CacheFailure=*/true); 440 assert(DirInfo && 441 "The directory of a virtual file should already be in the cache."); 442 443 // Check to see if the file exists. If so, drop the virtual file 444 int FileDescriptor = -1; 445 struct stat StatBuf; 446 const char *InterndFileName = NamedFileEnt.getKeyData(); 447 if (getStatValue(InterndFileName, StatBuf, &FileDescriptor) == 0) { 448 // If the stat process opened the file, close it to avoid a FD leak. 449 if (FileDescriptor != -1) 450 close(FileDescriptor); 451 452 StatBuf.st_size = Size; 453 StatBuf.st_mtime = ModificationTime; 454 UFE = &UniqueRealFiles.getFile(InterndFileName, StatBuf); 455 456 NamedFileEnt.setValue(UFE); 457 458 // If we had already opened this file, close it now so we don't 459 // leak the descriptor. We're not going to use the file 460 // descriptor anyway, since this is a virtual file. 461 if (UFE->FD != -1) { 462 close(UFE->FD); 463 UFE->FD = -1; 464 } 465 466 // If we already have an entry with this inode, return it. 467 if (UFE->getName()) 468 return UFE; 469 } 470 471 if (!UFE) { 472 UFE = new FileEntry(); 473 VirtualFileEntries.push_back(UFE); 474 NamedFileEnt.setValue(UFE); 475 } 476 477 UFE->Name = InterndFileName; 478 UFE->Size = Size; 479 UFE->ModTime = ModificationTime; 480 UFE->Dir = DirInfo; 481 UFE->UID = NextFileUID++; 482 UFE->FD = -1; 483 return UFE; 484 } 485 486 void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { 487 StringRef pathRef(path.data(), path.size()); 488 489 if (FileSystemOpts.WorkingDir.empty() 490 || llvm::sys::path::is_absolute(pathRef)) 491 return; 492 493 SmallString<128> NewPath(FileSystemOpts.WorkingDir); 494 llvm::sys::path::append(NewPath, pathRef); 495 path = NewPath; 496 } 497 498 llvm::MemoryBuffer *FileManager:: 499 getBufferForFile(const FileEntry *Entry, std::string *ErrorStr, 500 bool isVolatile) { 501 OwningPtr<llvm::MemoryBuffer> Result; 502 llvm::error_code ec; 503 504 uint64_t FileSize = Entry->getSize(); 505 // If there's a high enough chance that the file have changed since we 506 // got its size, force a stat before opening it. 507 if (isVolatile) 508 FileSize = -1; 509 510 const char *Filename = Entry->getName(); 511 // If the file is already open, use the open file descriptor. 512 if (Entry->FD != -1) { 513 ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, FileSize); 514 if (ErrorStr) 515 *ErrorStr = ec.message(); 516 517 close(Entry->FD); 518 Entry->FD = -1; 519 return Result.take(); 520 } 521 522 // Otherwise, open the file. 523 524 if (FileSystemOpts.WorkingDir.empty()) { 525 ec = llvm::MemoryBuffer::getFile(Filename, Result, FileSize); 526 if (ec && ErrorStr) 527 *ErrorStr = ec.message(); 528 return Result.take(); 529 } 530 531 SmallString<128> FilePath(Entry->getName()); 532 FixupRelativePath(FilePath); 533 ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, FileSize); 534 if (ec && ErrorStr) 535 *ErrorStr = ec.message(); 536 return Result.take(); 537 } 538 539 llvm::MemoryBuffer *FileManager:: 540 getBufferForFile(StringRef Filename, std::string *ErrorStr) { 541 OwningPtr<llvm::MemoryBuffer> Result; 542 llvm::error_code ec; 543 if (FileSystemOpts.WorkingDir.empty()) { 544 ec = llvm::MemoryBuffer::getFile(Filename, Result); 545 if (ec && ErrorStr) 546 *ErrorStr = ec.message(); 547 return Result.take(); 548 } 549 550 SmallString<128> FilePath(Filename); 551 FixupRelativePath(FilePath); 552 ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result); 553 if (ec && ErrorStr) 554 *ErrorStr = ec.message(); 555 return Result.take(); 556 } 557 558 /// getStatValue - Get the 'stat' information for the specified path, 559 /// using the cache to accelerate it if possible. This returns true 560 /// if the path points to a virtual file or does not exist, or returns 561 /// false if it's an existent real file. If FileDescriptor is NULL, 562 /// do directory look-up instead of file look-up. 563 bool FileManager::getStatValue(const char *Path, struct stat &StatBuf, 564 int *FileDescriptor) { 565 // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be 566 // absolute! 567 if (FileSystemOpts.WorkingDir.empty()) 568 return FileSystemStatCache::get(Path, StatBuf, FileDescriptor, 569 StatCache.get()); 570 571 SmallString<128> FilePath(Path); 572 FixupRelativePath(FilePath); 573 574 return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor, 575 StatCache.get()); 576 } 577 578 bool FileManager::getNoncachedStatValue(StringRef Path, 579 struct stat &StatBuf) { 580 SmallString<128> FilePath(Path); 581 FixupRelativePath(FilePath); 582 583 return ::stat(FilePath.c_str(), &StatBuf) != 0; 584 } 585 586 void FileManager::invalidateCache(const FileEntry *Entry) { 587 assert(Entry && "Cannot invalidate a NULL FileEntry"); 588 589 SeenFileEntries.erase(Entry->getName()); 590 591 // FileEntry invalidation should not block future optimizations in the file 592 // caches. Possible alternatives are cache truncation (invalidate last N) or 593 // invalidation of the whole cache. 594 UniqueRealFiles.erase(Entry); 595 } 596 597 598 void FileManager::GetUniqueIDMapping( 599 SmallVectorImpl<const FileEntry *> &UIDToFiles) const { 600 UIDToFiles.clear(); 601 UIDToFiles.resize(NextFileUID); 602 603 // Map file entries 604 for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator 605 FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end(); 606 FE != FEEnd; ++FE) 607 if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE) 608 UIDToFiles[FE->getValue()->getUID()] = FE->getValue(); 609 610 // Map virtual file entries 611 for (SmallVector<FileEntry*, 4>::const_iterator 612 VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end(); 613 VFE != VFEEnd; ++VFE) 614 if (*VFE && *VFE != NON_EXISTENT_FILE) 615 UIDToFiles[(*VFE)->getUID()] = *VFE; 616 } 617 618 void FileManager::modifyFileEntry(FileEntry *File, 619 off_t Size, time_t ModificationTime) { 620 File->Size = Size; 621 File->ModTime = ModificationTime; 622 } 623 624 625 void FileManager::PrintStats() const { 626 llvm::errs() << "\n*** File Manager Stats:\n"; 627 llvm::errs() << UniqueRealFiles.size() << " real files found, " 628 << UniqueRealDirs.size() << " real dirs found.\n"; 629 llvm::errs() << VirtualFileEntries.size() << " virtual files found, " 630 << VirtualDirectoryEntries.size() << " virtual dirs found.\n"; 631 llvm::errs() << NumDirLookups << " dir lookups, " 632 << NumDirCacheMisses << " dir cache misses.\n"; 633 llvm::errs() << NumFileLookups << " file lookups, " 634 << NumFileCacheMisses << " file cache misses.\n"; 635 636 //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 637 } 638