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 "clang/Frontend/PCHContainerOperations.h" 23 #include "llvm/ADT/SmallString.h" 24 #include "llvm/Config/llvm-config.h" 25 #include "llvm/ADT/STLExtras.h" 26 #include "llvm/Support/FileSystem.h" 27 #include "llvm/Support/MemoryBuffer.h" 28 #include "llvm/Support/Path.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <map> 31 #include <set> 32 #include <string> 33 #include <system_error> 34 35 using namespace clang; 36 37 /// NON_EXISTENT_DIR - A special value distinct from null that is used to 38 /// represent a dir name that doesn't exist on the disk. 39 #define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 40 41 /// NON_EXISTENT_FILE - A special value distinct from null that is used to 42 /// represent a filename that doesn't exist on the disk. 43 #define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 44 45 //===----------------------------------------------------------------------===// 46 // Common logic. 47 //===----------------------------------------------------------------------===// 48 49 FileManager::FileManager(const FileSystemOptions &FSO, 50 IntrusiveRefCntPtr<vfs::FileSystem> FS) 51 : FS(FS), FileSystemOpts(FSO), 52 SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { 53 NumDirLookups = NumFileLookups = 0; 54 NumDirCacheMisses = NumFileCacheMisses = 0; 55 56 // If the caller doesn't provide a virtual file system, just grab the real 57 // file system. 58 if (!FS) 59 this->FS = vfs::getRealFileSystem(); 60 } 61 62 FileManager::~FileManager() = default; 63 64 void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache, 65 bool AtBeginning) { 66 assert(statCache && "No stat cache provided?"); 67 if (AtBeginning || !StatCache.get()) { 68 statCache->setNextStatCache(std::move(StatCache)); 69 StatCache = std::move(statCache); 70 return; 71 } 72 73 FileSystemStatCache *LastCache = StatCache.get(); 74 while (LastCache->getNextStatCache()) 75 LastCache = LastCache->getNextStatCache(); 76 77 LastCache->setNextStatCache(std::move(statCache)); 78 } 79 80 void FileManager::removeStatCache(FileSystemStatCache *statCache) { 81 if (!statCache) 82 return; 83 84 if (StatCache.get() == statCache) { 85 // This is the first stat cache. 86 StatCache = StatCache->takeNextStatCache(); 87 return; 88 } 89 90 // Find the stat cache in the list. 91 FileSystemStatCache *PrevCache = StatCache.get(); 92 while (PrevCache && PrevCache->getNextStatCache() != statCache) 93 PrevCache = PrevCache->getNextStatCache(); 94 95 assert(PrevCache && "Stat cache not found for removal"); 96 PrevCache->setNextStatCache(statCache->takeNextStatCache()); 97 } 98 99 void FileManager::clearStatCaches() { 100 StatCache.reset(); 101 } 102 103 /// \brief Retrieve the directory that the given file name resides in. 104 /// Filename can point to either a real file or a virtual file. 105 static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 106 StringRef Filename, 107 bool CacheFailure) { 108 if (Filename.empty()) 109 return nullptr; 110 111 if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) 112 return nullptr; // If Filename is a directory. 113 114 StringRef DirName = llvm::sys::path::parent_path(Filename); 115 // Use the current directory if file has no path component. 116 if (DirName.empty()) 117 DirName = "."; 118 119 return FileMgr.getDirectory(DirName, CacheFailure); 120 } 121 122 /// Add all ancestors of the given path (pointing to either a file or 123 /// a directory) as virtual directories. 124 void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { 125 StringRef DirName = llvm::sys::path::parent_path(Path); 126 if (DirName.empty()) 127 return; 128 129 auto &NamedDirEnt = 130 *SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first; 131 132 // When caching a virtual directory, we always cache its ancestors 133 // at the same time. Therefore, if DirName is already in the cache, 134 // we don't need to recurse as its ancestors must also already be in 135 // the cache. 136 if (NamedDirEnt.second && NamedDirEnt.second != NON_EXISTENT_DIR) 137 return; 138 139 // Add the virtual directory to the cache. 140 auto UDE = llvm::make_unique<DirectoryEntry>(); 141 UDE->Name = NamedDirEnt.first().data(); 142 NamedDirEnt.second = UDE.get(); 143 VirtualDirectoryEntries.push_back(std::move(UDE)); 144 145 // Recursively add the other ancestors. 146 addAncestorsAsVirtualDirs(DirName); 147 } 148 149 const DirectoryEntry *FileManager::getDirectory(StringRef DirName, 150 bool CacheFailure) { 151 // stat doesn't like trailing separators except for root directory. 152 // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'. 153 // (though it can strip '\\') 154 if (DirName.size() > 1 && 155 DirName != llvm::sys::path::root_path(DirName) && 156 llvm::sys::path::is_separator(DirName.back())) 157 DirName = DirName.substr(0, DirName.size()-1); 158 #ifdef LLVM_ON_WIN32 159 // Fixing a problem with "clang C:test.c" on Windows. 160 // Stat("C:") does not recognize "C:" as a valid directory 161 std::string DirNameStr; 162 if (DirName.size() > 1 && DirName.back() == ':' && 163 DirName.equals_lower(llvm::sys::path::root_name(DirName))) { 164 DirNameStr = DirName.str() + '.'; 165 DirName = DirNameStr; 166 } 167 #endif 168 169 ++NumDirLookups; 170 auto &NamedDirEnt = 171 *SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first; 172 173 // See if there was already an entry in the map. Note that the map 174 // contains both virtual and real directories. 175 if (NamedDirEnt.second) 176 return NamedDirEnt.second == NON_EXISTENT_DIR ? nullptr 177 : NamedDirEnt.second; 178 179 ++NumDirCacheMisses; 180 181 // By default, initialize it to invalid. 182 NamedDirEnt.second = NON_EXISTENT_DIR; 183 184 // Get the null-terminated directory name as stored as the key of the 185 // SeenDirEntries map. 186 const char *InterndDirName = NamedDirEnt.first().data(); 187 188 // Check to see if the directory exists. 189 FileData Data; 190 if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) { 191 // There's no real directory at the given path. 192 if (!CacheFailure) 193 SeenDirEntries.erase(DirName); 194 return nullptr; 195 } 196 197 // It exists. See if we have already opened a directory with the 198 // same inode (this occurs on Unix-like systems when one dir is 199 // symlinked to another, for example) or the same path (on 200 // Windows). 201 DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID]; 202 203 NamedDirEnt.second = &UDE; 204 if (!UDE.getName()) { 205 // We don't have this directory yet, add it. We use the string 206 // key from the SeenDirEntries map as the string. 207 UDE.Name = InterndDirName; 208 } 209 210 return &UDE; 211 } 212 213 const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, 214 bool CacheFailure) { 215 ++NumFileLookups; 216 217 // See if there is already an entry in the map. 218 auto &NamedFileEnt = 219 *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first; 220 221 // See if there is already an entry in the map. 222 if (NamedFileEnt.second) 223 return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr 224 : NamedFileEnt.second; 225 226 ++NumFileCacheMisses; 227 228 // By default, initialize it to invalid. 229 NamedFileEnt.second = NON_EXISTENT_FILE; 230 231 // Get the null-terminated file name as stored as the key of the 232 // SeenFileEntries map. 233 const char *InterndFileName = NamedFileEnt.first().data(); 234 235 // Look up the directory for the file. When looking up something like 236 // sys/foo.h we'll discover all of the search directories that have a 'sys' 237 // subdirectory. This will let us avoid having to waste time on known-to-fail 238 // searches when we go to find sys/bar.h, because all the search directories 239 // without a 'sys' subdir will get a cached failure result. 240 const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 241 CacheFailure); 242 if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist. 243 if (!CacheFailure) 244 SeenFileEntries.erase(Filename); 245 246 return nullptr; 247 } 248 249 // FIXME: Use the directory info to prune this, before doing the stat syscall. 250 // FIXME: This will reduce the # syscalls. 251 252 // Nope, there isn't. Check to see if the file exists. 253 std::unique_ptr<vfs::File> F; 254 FileData Data; 255 if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) { 256 // There's no real file at the given path. 257 if (!CacheFailure) 258 SeenFileEntries.erase(Filename); 259 260 return nullptr; 261 } 262 263 assert((openFile || !F) && "undesired open file"); 264 265 // It exists. See if we have already opened a file with the same inode. 266 // This occurs when one dir is symlinked to another, for example. 267 FileEntry &UFE = UniqueRealFiles[Data.UniqueID]; 268 269 NamedFileEnt.second = &UFE; 270 271 // If the name returned by getStatValue is different than Filename, re-intern 272 // the name. 273 if (Data.Name != Filename) { 274 auto &NamedFileEnt = 275 *SeenFileEntries.insert(std::make_pair(Data.Name, nullptr)).first; 276 if (!NamedFileEnt.second) 277 NamedFileEnt.second = &UFE; 278 else 279 assert(NamedFileEnt.second == &UFE && 280 "filename from getStatValue() refers to wrong file"); 281 InterndFileName = NamedFileEnt.first().data(); 282 } 283 284 if (UFE.isValid()) { // Already have an entry with this inode, return it. 285 286 // FIXME: this hack ensures that if we look up a file by a virtual path in 287 // the VFS that the getDir() will have the virtual path, even if we found 288 // the file by a 'real' path first. This is required in order to find a 289 // module's structure when its headers/module map are mapped in the VFS. 290 // We should remove this as soon as we can properly support a file having 291 // multiple names. 292 if (DirInfo != UFE.Dir && Data.IsVFSMapped) 293 UFE.Dir = DirInfo; 294 295 // Always update the name to use the last name by which a file was accessed. 296 // FIXME: Neither this nor always using the first name is correct; we want 297 // to switch towards a design where we return a FileName object that 298 // encapsulates both the name by which the file was accessed and the 299 // corresponding FileEntry. 300 UFE.Name = InterndFileName; 301 302 return &UFE; 303 } 304 305 // Otherwise, we don't have this file yet, add it. 306 UFE.Name = InterndFileName; 307 UFE.Size = Data.Size; 308 UFE.ModTime = Data.ModTime; 309 UFE.Dir = DirInfo; 310 UFE.UID = NextFileUID++; 311 UFE.UniqueID = Data.UniqueID; 312 UFE.IsNamedPipe = Data.IsNamedPipe; 313 UFE.InPCH = Data.InPCH; 314 UFE.File = std::move(F); 315 UFE.IsValid = true; 316 return &UFE; 317 } 318 319 const FileEntry * 320 FileManager::getVirtualFile(StringRef Filename, off_t Size, 321 time_t ModificationTime) { 322 ++NumFileLookups; 323 324 // See if there is already an entry in the map. 325 auto &NamedFileEnt = 326 *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first; 327 328 // See if there is already an entry in the map. 329 if (NamedFileEnt.second && NamedFileEnt.second != NON_EXISTENT_FILE) 330 return NamedFileEnt.second; 331 332 ++NumFileCacheMisses; 333 334 // By default, initialize it to invalid. 335 NamedFileEnt.second = NON_EXISTENT_FILE; 336 337 addAncestorsAsVirtualDirs(Filename); 338 FileEntry *UFE = nullptr; 339 340 // Now that all ancestors of Filename are in the cache, the 341 // following call is guaranteed to find the DirectoryEntry from the 342 // cache. 343 const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 344 /*CacheFailure=*/true); 345 assert(DirInfo && 346 "The directory of a virtual file should already be in the cache."); 347 348 // Check to see if the file exists. If so, drop the virtual file 349 FileData Data; 350 const char *InterndFileName = NamedFileEnt.first().data(); 351 if (getStatValue(InterndFileName, Data, true, nullptr) == 0) { 352 Data.Size = Size; 353 Data.ModTime = ModificationTime; 354 UFE = &UniqueRealFiles[Data.UniqueID]; 355 356 NamedFileEnt.second = UFE; 357 358 // If we had already opened this file, close it now so we don't 359 // leak the descriptor. We're not going to use the file 360 // descriptor anyway, since this is a virtual file. 361 if (UFE->File) 362 UFE->closeFile(); 363 364 // If we already have an entry with this inode, return it. 365 if (UFE->isValid()) 366 return UFE; 367 368 UFE->UniqueID = Data.UniqueID; 369 UFE->IsNamedPipe = Data.IsNamedPipe; 370 UFE->InPCH = Data.InPCH; 371 } 372 373 if (!UFE) { 374 VirtualFileEntries.push_back(llvm::make_unique<FileEntry>()); 375 UFE = VirtualFileEntries.back().get(); 376 NamedFileEnt.second = UFE; 377 } 378 379 UFE->Name = InterndFileName; 380 UFE->Size = Size; 381 UFE->ModTime = ModificationTime; 382 UFE->Dir = DirInfo; 383 UFE->UID = NextFileUID++; 384 UFE->File.reset(); 385 return UFE; 386 } 387 388 bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { 389 StringRef pathRef(path.data(), path.size()); 390 391 if (FileSystemOpts.WorkingDir.empty() 392 || llvm::sys::path::is_absolute(pathRef)) 393 return false; 394 395 SmallString<128> NewPath(FileSystemOpts.WorkingDir); 396 llvm::sys::path::append(NewPath, pathRef); 397 path = NewPath; 398 return true; 399 } 400 401 bool FileManager::makeAbsolutePath(SmallVectorImpl<char> &Path) const { 402 bool Changed = FixupRelativePath(Path); 403 404 if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) { 405 llvm::sys::fs::make_absolute(Path); 406 Changed = true; 407 } 408 409 return Changed; 410 } 411 412 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 413 FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile, 414 bool ShouldCloseOpenFile) { 415 uint64_t FileSize = Entry->getSize(); 416 // If there's a high enough chance that the file have changed since we 417 // got its size, force a stat before opening it. 418 if (isVolatile) 419 FileSize = -1; 420 421 const char *Filename = Entry->getName(); 422 // If the file is already open, use the open file descriptor. 423 if (Entry->File) { 424 auto Result = 425 Entry->File->getBuffer(Filename, FileSize, 426 /*RequiresNullTerminator=*/true, isVolatile); 427 // FIXME: we need a set of APIs that can make guarantees about whether a 428 // FileEntry is open or not. 429 if (ShouldCloseOpenFile) 430 Entry->closeFile(); 431 return Result; 432 } 433 434 // Otherwise, open the file. 435 436 if (FileSystemOpts.WorkingDir.empty()) 437 return FS->getBufferForFile(Filename, FileSize, 438 /*RequiresNullTerminator=*/true, isVolatile); 439 440 SmallString<128> FilePath(Entry->getName()); 441 FixupRelativePath(FilePath); 442 return FS->getBufferForFile(FilePath, FileSize, 443 /*RequiresNullTerminator=*/true, isVolatile); 444 } 445 446 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 447 FileManager::getBufferForFile(StringRef Filename) { 448 if (FileSystemOpts.WorkingDir.empty()) 449 return FS->getBufferForFile(Filename); 450 451 SmallString<128> FilePath(Filename); 452 FixupRelativePath(FilePath); 453 return FS->getBufferForFile(FilePath.c_str()); 454 } 455 456 /// getStatValue - Get the 'stat' information for the specified path, 457 /// using the cache to accelerate it if possible. This returns true 458 /// if the path points to a virtual file or does not exist, or returns 459 /// false if it's an existent real file. If FileDescriptor is NULL, 460 /// do directory look-up instead of file look-up. 461 bool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile, 462 std::unique_ptr<vfs::File> *F) { 463 // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be 464 // absolute! 465 if (FileSystemOpts.WorkingDir.empty()) 466 return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS); 467 468 SmallString<128> FilePath(Path); 469 FixupRelativePath(FilePath); 470 471 return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F, 472 StatCache.get(), *FS); 473 } 474 475 bool FileManager::getNoncachedStatValue(StringRef Path, 476 vfs::Status &Result) { 477 SmallString<128> FilePath(Path); 478 FixupRelativePath(FilePath); 479 480 llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str()); 481 if (!S) 482 return true; 483 Result = *S; 484 return false; 485 } 486 487 void FileManager::invalidateCache(const FileEntry *Entry) { 488 assert(Entry && "Cannot invalidate a NULL FileEntry"); 489 490 SeenFileEntries.erase(Entry->getName()); 491 492 // FileEntry invalidation should not block future optimizations in the file 493 // caches. Possible alternatives are cache truncation (invalidate last N) or 494 // invalidation of the whole cache. 495 UniqueRealFiles.erase(Entry->getUniqueID()); 496 } 497 498 499 void FileManager::GetUniqueIDMapping( 500 SmallVectorImpl<const FileEntry *> &UIDToFiles) const { 501 UIDToFiles.clear(); 502 UIDToFiles.resize(NextFileUID); 503 504 // Map file entries 505 for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator 506 FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end(); 507 FE != FEEnd; ++FE) 508 if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE) 509 UIDToFiles[FE->getValue()->getUID()] = FE->getValue(); 510 511 // Map virtual file entries 512 for (const auto &VFE : VirtualFileEntries) 513 if (VFE && VFE.get() != NON_EXISTENT_FILE) 514 UIDToFiles[VFE->getUID()] = VFE.get(); 515 } 516 517 void FileManager::modifyFileEntry(FileEntry *File, 518 off_t Size, time_t ModificationTime) { 519 File->Size = Size; 520 File->ModTime = ModificationTime; 521 } 522 523 StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { 524 // FIXME: use llvm::sys::fs::canonical() when it gets implemented 525 llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known 526 = CanonicalDirNames.find(Dir); 527 if (Known != CanonicalDirNames.end()) 528 return Known->second; 529 530 StringRef CanonicalName(Dir->getName()); 531 532 #ifdef LLVM_ON_UNIX 533 char CanonicalNameBuf[PATH_MAX]; 534 if (realpath(Dir->getName(), CanonicalNameBuf)) 535 CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage); 536 #else 537 SmallString<256> CanonicalNameBuf(CanonicalName); 538 llvm::sys::fs::make_absolute(CanonicalNameBuf); 539 llvm::sys::path::native(CanonicalNameBuf); 540 // We've run into needing to remove '..' here in the wild though, so 541 // remove it. 542 // On Windows, symlinks are significantly less prevalent, so removing 543 // '..' is pretty safe. 544 // Ideally we'd have an equivalent of `realpath` and could implement 545 // sys::fs::canonical across all the platforms. 546 llvm::sys::path::remove_dots(CanonicalNameBuf, /* remove_dot_dot */ true); 547 CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage); 548 #endif 549 550 CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName)); 551 return CanonicalName; 552 } 553 554 void FileManager::PrintStats() const { 555 llvm::errs() << "\n*** File Manager Stats:\n"; 556 llvm::errs() << UniqueRealFiles.size() << " real files found, " 557 << UniqueRealDirs.size() << " real dirs found.\n"; 558 llvm::errs() << VirtualFileEntries.size() << " virtual files found, " 559 << VirtualDirectoryEntries.size() << " virtual dirs found.\n"; 560 llvm::errs() << NumDirLookups << " dir lookups, " 561 << NumDirCacheMisses << " dir cache misses.\n"; 562 llvm::errs() << NumFileLookups << " file lookups, " 563 << NumFileCacheMisses << " file cache misses.\n"; 564 565 //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 566 } 567 568 // Virtual destructors for abstract base classes that need live in Basic. 569 PCHContainerWriter::~PCHContainerWriter() {} 570 PCHContainerReader::~PCHContainerReader() {} 571