FileManager.h revision f9f7766846a205bc900b578f944567e679b221aa
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===//
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 defines the FileManager interface.
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#ifndef LLVM_CLANG_FILEMANAGER_H
155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define LLVM_CLANG_FILEMANAGER_H
165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1739b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner#include "clang/Basic/FileSystemOptions.h"
18057e567f1b375190779e5341f42861896cdee442Douglas Gregor#include "llvm/ADT/SmallVector.h"
195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/StringMap.h"
20458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include "llvm/ADT/StringRef.h"
2196438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek#include "llvm/ADT/OwningPtr.h"
22f3eb9219cf4b4e80c377d37aed72d5d6d840b7bcTed Kremenek#include "llvm/Support/Allocator.h"
23ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#include "llvm/Config/config.h" // for mode_t
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields in stat.
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/types.h>
2610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner
2710e286aa8d39fb51a21412850265d9dae74613eeChris Lattnerstruct stat;
285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
29389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidisnamespace llvm {
30389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidisclass MemoryBuffer;
3110e286aa8d39fb51a21412850265d9dae74613eeChris Lattnernamespace sys { class Path; }
32389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis}
33389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencernamespace clang {
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass FileManager;
3610e286aa8d39fb51a21412850265d9dae74613eeChris Lattnerclass FileSystemStatCache;
3710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner
385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// DirectoryEntry - Cached information about one directory on the disk.
395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass DirectoryEntry {
415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *Name;   // Name of the directory.
425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  friend class FileManager;
435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerpublic:
445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  DirectoryEntry() : Name(0) {}
451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const char *getName() const { return Name; }
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
48f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// FileEntry - Cached information about one file on the disk.  If the 'FD'
49f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// member is valid, then this FileEntry has an open file descriptor for the
50f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// file.
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass FileEntry {
53f17765d202d1ec34ada7ff3f18d18731588143c2Chris Lattner  const char *Name;           // Name of the file.
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  off_t Size;                 // File size in bytes.
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  time_t ModTime;             // Modification time of file.
565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const DirectoryEntry *Dir;  // Directory file lives in.
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned UID;               // A unique (small) ID for the file.
58bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek  dev_t Device;               // ID for the device containing the file.
59bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek  ino_t Inode;                // Inode number for the file.
6096438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek  mode_t FileMode;            // The file mode as returned by 'stat'.
61f9f7766846a205bc900b578f944567e679b221aaChris Lattner
62f9f7766846a205bc900b578f944567e679b221aaChris Lattner  /// FD - The file descriptor for the file entry if it is opened and owned
63f9f7766846a205bc900b578f944567e679b221aaChris Lattner  /// by the FileEntry.  If not, this is set to -1.
64f9f7766846a205bc900b578f944567e679b221aaChris Lattner  int FD;
655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  friend class FileManager;
66f9f7766846a205bc900b578f944567e679b221aaChris Lattner
67f9f7766846a205bc900b578f944567e679b221aaChris Lattner  void operator=(const FileEntry&); // DO NOT IMPLEMENT.
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerpublic:
6996438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek  FileEntry(dev_t device, ino_t inode, mode_t m)
70f9f7766846a205bc900b578f944567e679b221aaChris Lattner    : Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {}
716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  // Add a default constructor for use with llvm::StringMap
72f9f7766846a205bc900b578f944567e679b221aaChris Lattner  FileEntry() : Name(0), Device(0), Inode(0), FileMode(0), FD(-1) {}
73f9f7766846a205bc900b578f944567e679b221aaChris Lattner
74f9f7766846a205bc900b578f944567e679b221aaChris Lattner  FileEntry(const FileEntry &FE) {
75f9f7766846a205bc900b578f944567e679b221aaChris Lattner    memcpy(this, &FE, sizeof(FE));
76f9f7766846a205bc900b578f944567e679b221aaChris Lattner    assert(FD == -1 && "Cannot copy an file-owning FileEntry");
77f9f7766846a205bc900b578f944567e679b221aaChris Lattner  }
78f9f7766846a205bc900b578f944567e679b221aaChris Lattner
79f9f7766846a205bc900b578f944567e679b221aaChris Lattner  ~FileEntry();
801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *getName() const { return Name; }
825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  off_t getSize() const { return Size; }
835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned getUID() const { return UID; }
84bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek  ino_t getInode() const { return Inode; }
857f1752797d4a4344b539ad9452471871c0eec64bTed Kremenek  dev_t getDevice() const { return Device; }
865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  time_t getModificationTime() const { return ModTime; }
8796438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek  mode_t getFileMode() const { return FileMode; }
881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getDir - Return the directory the file lives in.
905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const DirectoryEntry *getDir() const { return Dir; }
921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
93f9f7766846a205bc900b578f944567e679b221aaChris Lattner  bool operator<(const FileEntry &RHS) const {
94bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek    return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode);
95bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek  }
965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// FileManager - Implements support for file system lookup, file system
995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// caching, and directory search management.  This also handles more advanced
1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// properties, such as uniquing files based on "inode", so that a file with two
1015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// names (e.g. symlinked) will be treated as a single file.
1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass FileManager {
10439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner  FileSystemOptions FileSystemOpts;
1057ad97ffa631af6ad678c79b38341ac995f347ce9Chris Lattner
1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  class UniqueDirContainer;
1076bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  class UniqueFileContainer;
1086bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1096bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  /// UniqueDirs/UniqueFiles - Cache for existing directories/files.
1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
1116bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  UniqueDirContainer &UniqueDirs;
1126bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  UniqueFileContainer &UniqueFiles;
1136bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek
1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// DirEntries/FileEntries - This is a cache of directory/file entries we have
1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// looked up.  The actual Entry is owned by UniqueFiles/UniqueDirs above.
1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
117f3eb9219cf4b4e80c377d37aed72d5d6d840b7bcTed Kremenek  llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> DirEntries;
118f3eb9219cf4b4e80c377d37aed72d5d6d840b7bcTed Kremenek  llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> FileEntries;
1191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// NextFileUID - Each FileEntry we create is assigned a unique ID #.
1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned NextFileUID;
1231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
124057e567f1b375190779e5341f42861896cdee442Douglas Gregor  /// \brief The virtual files that we have allocated.
12510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  llvm::SmallVector<FileEntry*, 4> VirtualFileEntries;
126057e567f1b375190779e5341f42861896cdee442Douglas Gregor
1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Statistics.
1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned NumDirLookups, NumFileLookups;
1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned NumDirCacheMisses, NumFileCacheMisses;
1301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
131fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek  // Caching.
13210e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  llvm::OwningPtr<FileSystemStatCache> StatCache;
1331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
134f9f7766846a205bc900b578f944567e679b221aaChris Lattner  bool getStatValue(const char *Path, struct stat &StatBuf, bool isForDir);
1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerpublic:
1367ad97ffa631af6ad678c79b38341ac995f347ce9Chris Lattner  FileManager(const FileSystemOptions &FileSystemOpts);
1376bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek  ~FileManager();
1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
13910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  /// \brief Installs the provided FileSystemStatCache object within
14052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  /// the FileManager.
14152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  ///
14252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  /// Ownership of this object is transferred to the FileManager.
14352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  ///
14452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  /// \param statCache the new stat cache to install. Ownership of this
14552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  /// object is transferred to the FileManager.
14652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  ///
14752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  /// \param AtBeginning whether this new stat cache must be installed at the
14852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  /// beginning of the chain of stat caches. Otherwise, it will be added to
14952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor  /// the end of the chain.
15010e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  void addStatCache(FileSystemStatCache *statCache, bool AtBeginning = false);
15152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
15210e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  /// \brief Removes the specified FileSystemStatCache object from the manager.
15310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner  void removeStatCache(FileSystemStatCache *statCache);
15452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor
1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getDirectory - Lookup, cache, and verify the specified directory.  This
1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// returns null if the directory doesn't exist.
1571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ///
15839b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner  const DirectoryEntry *getDirectory(llvm::StringRef Filename);
1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getFile - Lookup, cache, and verify the specified file.  This returns null
1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// if the file doesn't exist.
1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ///
16339b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner  const FileEntry *getFile(llvm::StringRef Filename);
1641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
165057e567f1b375190779e5341f42861896cdee442Douglas Gregor  /// \brief Retrieve a file entry for a "virtual" file that acts as
166057e567f1b375190779e5341f42861896cdee442Douglas Gregor  /// if there were a file with the given name on disk. The file
167057e567f1b375190779e5341f42861896cdee442Douglas Gregor  /// itself is not accessed.
168ec1b1cc006cef19e0a95d0ea6fbfd37d0d615066Benjamin Kramer  const FileEntry *getVirtualFile(llvm::StringRef Filename, off_t Size,
16939b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner                                  time_t ModificationTime);
170389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis
171389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  /// \brief Open the specified file as a MemoryBuffer, returning a new
172389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  /// MemoryBuffer if successful, otherwise returning null.
173389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry,
17475dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner                                       std::string *ErrorStr = 0);
175389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename,
17675dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner                                       std::string *ErrorStr = 0);
177389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis
178389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  /// \brief If path is not absolute and FileSystemOptions set the working
179389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  /// directory, the path is modified to be relative to the given
180389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  /// working directory.
181389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis  static void FixupRelativePath(llvm::sys::Path &path,
182389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis                                const FileSystemOptions &FSOpts);
18367452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner
1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void PrintStats() const;
1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}  // end namespace clang
1885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif
190