LCOV - code coverage report
Current view: top level - include/llvm/Support - FileSystem.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 91 97 93.8 %
Date: 2018-07-13 00:08:38 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===//
       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 declares the llvm::sys::fs namespace. It is designed after
      11             : // TR2/boost filesystem (v3), but modified to remove exception handling and the
      12             : // path class.
      13             : //
      14             : // All functions return an error_code and their actual work via the last out
      15             : // argument. The out argument is defined if and only if errc::success is
      16             : // returned. A function may return any error code in the generic or system
      17             : // category. However, they shall be equivalent to any error conditions listed
      18             : // in each functions respective documentation if the condition applies. [ note:
      19             : // this does not guarantee that error_code will be in the set of explicitly
      20             : // listed codes, but it does guarantee that if any of the explicitly listed
      21             : // errors occur, the correct error_code will be used ]. All functions may
      22             : // return errc::not_enough_memory if there is not enough memory to complete the
      23             : // operation.
      24             : //
      25             : //===----------------------------------------------------------------------===//
      26             : 
      27             : #ifndef LLVM_SUPPORT_FILESYSTEM_H
      28             : #define LLVM_SUPPORT_FILESYSTEM_H
      29             : 
      30             : #include "llvm/ADT/SmallString.h"
      31             : #include "llvm/ADT/StringRef.h"
      32             : #include "llvm/ADT/Twine.h"
      33             : #include "llvm/Config/llvm-config.h"
      34             : #include "llvm/Support/Chrono.h"
      35             : #include "llvm/Support/Error.h"
      36             : #include "llvm/Support/ErrorHandling.h"
      37             : #include "llvm/Support/ErrorOr.h"
      38             : #include "llvm/Support/MD5.h"
      39             : #include <cassert>
      40             : #include <cstdint>
      41             : #include <ctime>
      42             : #include <memory>
      43             : #include <stack>
      44             : #include <string>
      45             : #include <system_error>
      46             : #include <tuple>
      47             : #include <vector>
      48             : 
      49             : #ifdef HAVE_SYS_STAT_H
      50             : #include <sys/stat.h>
      51             : #endif
      52             : 
      53             : namespace llvm {
      54             : namespace sys {
      55             : namespace fs {
      56             : 
      57             : #if defined(_WIN32)
      58             : // A Win32 HANDLE is a typedef of void*
      59             : using file_t = void *;
      60             : #else
      61             : using file_t = int;
      62             : #endif
      63             : 
      64             : extern const file_t kInvalidFile;
      65             : 
      66             : /// An enumeration for the file system's view of the type.
      67             : enum class file_type {
      68             :   status_error,
      69             :   file_not_found,
      70             :   regular_file,
      71             :   directory_file,
      72             :   symlink_file,
      73             :   block_file,
      74             :   character_file,
      75             :   fifo_file,
      76             :   socket_file,
      77             :   type_unknown
      78             : };
      79             : 
      80             : /// space_info - Self explanatory.
      81             : struct space_info {
      82             :   uint64_t capacity;
      83             :   uint64_t free;
      84             :   uint64_t available;
      85             : };
      86             : 
      87             : enum perms {
      88             :   no_perms = 0,
      89             :   owner_read = 0400,
      90             :   owner_write = 0200,
      91             :   owner_exe = 0100,
      92             :   owner_all = owner_read | owner_write | owner_exe,
      93             :   group_read = 040,
      94             :   group_write = 020,
      95             :   group_exe = 010,
      96             :   group_all = group_read | group_write | group_exe,
      97             :   others_read = 04,
      98             :   others_write = 02,
      99             :   others_exe = 01,
     100             :   others_all = others_read | others_write | others_exe,
     101             :   all_read = owner_read | group_read | others_read,
     102             :   all_write = owner_write | group_write | others_write,
     103             :   all_exe = owner_exe | group_exe | others_exe,
     104             :   all_all = owner_all | group_all | others_all,
     105             :   set_uid_on_exe = 04000,
     106             :   set_gid_on_exe = 02000,
     107             :   sticky_bit = 01000,
     108             :   all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,
     109             :   perms_not_known = 0xFFFF
     110             : };
     111             : 
     112             : // Helper functions so that you can use & and | to manipulate perms bits:
     113             : inline perms operator|(perms l, perms r) {
     114       61513 :   return static_cast<perms>(static_cast<unsigned short>(l) |
     115       61513 :                             static_cast<unsigned short>(r));
     116             : }
     117             : inline perms operator&(perms l, perms r) {
     118     1646447 :   return static_cast<perms>(static_cast<unsigned short>(l) &
     119     1646132 :                             static_cast<unsigned short>(r));
     120             : }
     121             : inline perms &operator|=(perms &l, perms r) {
     122             :   l = l | r;
     123             :   return l;
     124             : }
     125             : inline perms &operator&=(perms &l, perms r) {
     126             :   l = l & r;
     127             :   return l;
     128             : }
     129             : inline perms operator~(perms x) {
     130             :   // Avoid UB by explicitly truncating the (unsigned) ~ result.
     131             :   return static_cast<perms>(
     132             :       static_cast<unsigned short>(~static_cast<unsigned short>(x)));
     133             : }
     134             : 
     135             : class UniqueID {
     136             :   uint64_t Device;
     137             :   uint64_t File;
     138             : 
     139             : public:
     140             :   UniqueID() = default;
     141      369623 :   UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
     142             : 
     143             :   bool operator==(const UniqueID &Other) const {
     144       35284 :     return Device == Other.Device && File == Other.File;
     145             :   }
     146             :   bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
     147             :   bool operator<(const UniqueID &Other) const {
     148             :     return std::tie(Device, File) < std::tie(Other.Device, Other.File);
     149             :   }
     150             : 
     151             :   uint64_t getDevice() const { return Device; }
     152             :   uint64_t getFile() const { return File; }
     153             : };
     154             : 
     155             : /// Represents the result of a call to directory_iterator::status(). This is a
     156             : /// subset of the information returned by a regular sys::fs::status() call, and
     157             : /// represents the information provided by Windows FileFirstFile/FindNextFile.
     158             : class basic_file_status {
     159             : protected:
     160             :   #if defined(LLVM_ON_UNIX)
     161             :   time_t fs_st_atime = 0;
     162             :   time_t fs_st_mtime = 0;
     163             :   uid_t fs_st_uid = 0;
     164             :   gid_t fs_st_gid = 0;
     165             :   off_t fs_st_size = 0;
     166             :   #elif defined (_WIN32)
     167             :   uint32_t LastAccessedTimeHigh = 0;
     168             :   uint32_t LastAccessedTimeLow = 0;
     169             :   uint32_t LastWriteTimeHigh = 0;
     170             :   uint32_t LastWriteTimeLow = 0;
     171             :   uint32_t FileSizeHigh = 0;
     172             :   uint32_t FileSizeLow = 0;
     173             :   #endif
     174             :   file_type Type = file_type::status_error;
     175             :   perms Perms = perms_not_known;
     176             : 
     177             : public:
     178     8260065 :   basic_file_status() = default;
     179             : 
     180             :   explicit basic_file_status(file_type Type) : Type(Type) {}
     181             : 
     182             :   #if defined(LLVM_ON_UNIX)
     183             :   basic_file_status(file_type Type, perms Perms, time_t ATime, time_t MTime,
     184             :                     uid_t UID, gid_t GID, off_t Size)
     185             :       : fs_st_atime(ATime), fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID),
     186             :         fs_st_size(Size), Type(Type), Perms(Perms) {}
     187             : #elif defined(_WIN32)
     188             :   basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh,
     189             :                     uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
     190             :                     uint32_t LastWriteTimeLow, uint32_t FileSizeHigh,
     191             :                     uint32_t FileSizeLow)
     192             :       : LastAccessedTimeHigh(LastAccessTimeHigh),
     193             :         LastAccessedTimeLow(LastAccessTimeLow),
     194             :         LastWriteTimeHigh(LastWriteTimeHigh),
     195             :         LastWriteTimeLow(LastWriteTimeLow), FileSizeHigh(FileSizeHigh),
     196             :         FileSizeLow(FileSizeLow), Type(Type), Perms(Perms) {}
     197             :   #endif
     198             : 
     199             :   // getters
     200             :   file_type type() const { return Type; }
     201             :   perms permissions() const { return Perms; }
     202             :   TimePoint<> getLastAccessedTime() const;
     203             :   TimePoint<> getLastModificationTime() const;
     204             : 
     205             :   #if defined(LLVM_ON_UNIX)
     206             :   uint32_t getUser() const { return fs_st_uid; }
     207             :   uint32_t getGroup() const { return fs_st_gid; }
     208     1264635 :   uint64_t getSize() const { return fs_st_size; }
     209             :   #elif defined (_WIN32)
     210             :   uint32_t getUser() const {
     211             :     return 9999; // Not applicable to Windows, so...
     212             :   }
     213             : 
     214             :   uint32_t getGroup() const {
     215             :     return 9999; // Not applicable to Windows, so...
     216             :   }
     217             : 
     218             :   uint64_t getSize() const {
     219             :     return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
     220             :   }
     221             :   #endif
     222             : 
     223             :   // setters
     224             :   void type(file_type v) { Type = v; }
     225             :   void permissions(perms p) { Perms = p; }
     226             : };
     227             : 
     228             : /// Represents the result of a call to sys::fs::status().
     229             : class file_status : public basic_file_status {
     230             :   friend bool equivalent(file_status A, file_status B);
     231             : 
     232             :   #if defined(LLVM_ON_UNIX)
     233             :   dev_t fs_st_dev = 0;
     234             :   nlink_t fs_st_nlinks = 0;
     235             :   ino_t fs_st_ino = 0;
     236             :   #elif defined (_WIN32)
     237             :   uint32_t NumLinks = 0;
     238             :   uint32_t VolumeSerialNumber = 0;
     239             :   uint32_t FileIndexHigh = 0;
     240             :   uint32_t FileIndexLow = 0;
     241             :   #endif
     242             : 
     243             : public:
     244             :   file_status() = default;
     245             : 
     246             :   explicit file_status(file_type Type) : basic_file_status(Type) {}
     247             : 
     248             :   #if defined(LLVM_ON_UNIX)
     249             :   file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino,
     250             :               time_t ATime, time_t MTime, uid_t UID, gid_t GID, off_t Size)
     251             :       : basic_file_status(Type, Perms, ATime, MTime, UID, GID, Size),
     252             :         fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {}
     253             :   #elif defined(_WIN32)
     254             :   file_status(file_type Type, perms Perms, uint32_t LinkCount,
     255             :               uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow,
     256             :               uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow,
     257             :               uint32_t VolumeSerialNumber, uint32_t FileSizeHigh,
     258             :               uint32_t FileSizeLow, uint32_t FileIndexHigh,
     259             :               uint32_t FileIndexLow)
     260             :       : basic_file_status(Type, Perms, LastAccessTimeHigh, LastAccessTimeLow,
     261             :                           LastWriteTimeHigh, LastWriteTimeLow, FileSizeHigh,
     262             :                           FileSizeLow),
     263             :         NumLinks(LinkCount), VolumeSerialNumber(VolumeSerialNumber),
     264             :         FileIndexHigh(FileIndexHigh), FileIndexLow(FileIndexLow) {}
     265             :   #endif
     266             : 
     267             :   UniqueID getUniqueID() const;
     268             :   uint32_t getLinkCount() const;
     269             : };
     270             : 
     271             : /// @}
     272             : /// @name Physical Operators
     273             : /// @{
     274             : 
     275             : /// Make \a path an absolute path.
     276             : ///
     277             : /// Makes \a path absolute using the \a current_directory if it is not already.
     278             : /// An empty \a path will result in the \a current_directory.
     279             : ///
     280             : /// /absolute/path   => /absolute/path
     281             : /// relative/../path => <current-directory>/relative/../path
     282             : ///
     283             : /// @param path A path that is modified to be an absolute path.
     284             : /// @returns errc::success if \a path has been made absolute, otherwise a
     285             : ///          platform-specific error_code.
     286             : std::error_code make_absolute(const Twine &current_directory,
     287             :                               SmallVectorImpl<char> &path);
     288             : 
     289             : /// Make \a path an absolute path.
     290             : ///
     291             : /// Makes \a path absolute using the current directory if it is not already. An
     292             : /// empty \a path will result in the current directory.
     293             : ///
     294             : /// /absolute/path   => /absolute/path
     295             : /// relative/../path => <current-directory>/relative/../path
     296             : ///
     297             : /// @param path A path that is modified to be an absolute path.
     298             : /// @returns errc::success if \a path has been made absolute, otherwise a
     299             : ///          platform-specific error_code.
     300             : std::error_code make_absolute(SmallVectorImpl<char> &path);
     301             : 
     302             : /// Create all the non-existent directories in path.
     303             : ///
     304             : /// @param path Directories to create.
     305             : /// @returns errc::success if is_directory(path), otherwise a platform
     306             : ///          specific error_code. If IgnoreExisting is false, also returns
     307             : ///          error if the directory already existed.
     308             : std::error_code create_directories(const Twine &path,
     309             :                                    bool IgnoreExisting = true,
     310             :                                    perms Perms = owner_all | group_all);
     311             : 
     312             : /// Create the directory in path.
     313             : ///
     314             : /// @param path Directory to create.
     315             : /// @returns errc::success if is_directory(path), otherwise a platform
     316             : ///          specific error_code. If IgnoreExisting is false, also returns
     317             : ///          error if the directory already existed.
     318             : std::error_code create_directory(const Twine &path, bool IgnoreExisting = true,
     319             :                                  perms Perms = owner_all | group_all);
     320             : 
     321             : /// Create a link from \a from to \a to.
     322             : ///
     323             : /// The link may be a soft or a hard link, depending on the platform. The caller
     324             : /// may not assume which one. Currently on windows it creates a hard link since
     325             : /// soft links require extra privileges. On unix, it creates a soft link since
     326             : /// hard links don't work on SMB file systems.
     327             : ///
     328             : /// @param to The path to hard link to.
     329             : /// @param from The path to hard link from. This is created.
     330             : /// @returns errc::success if the link was created, otherwise a platform
     331             : /// specific error_code.
     332             : std::error_code create_link(const Twine &to, const Twine &from);
     333             : 
     334             : /// Create a hard link from \a from to \a to, or return an error.
     335             : ///
     336             : /// @param to The path to hard link to.
     337             : /// @param from The path to hard link from. This is created.
     338             : /// @returns errc::success if the link was created, otherwise a platform
     339             : /// specific error_code.
     340             : std::error_code create_hard_link(const Twine &to, const Twine &from);
     341             : 
     342             : /// Collapse all . and .. patterns, resolve all symlinks, and optionally
     343             : ///        expand ~ expressions to the user's home directory.
     344             : ///
     345             : /// @param path The path to resolve.
     346             : /// @param output The location to store the resolved path.
     347             : /// @param expand_tilde If true, resolves ~ expressions to the user's home
     348             : ///                     directory.
     349             : std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output,
     350             :                           bool expand_tilde = false);
     351             : 
     352             : /// Get the current path.
     353             : ///
     354             : /// @param result Holds the current path on return.
     355             : /// @returns errc::success if the current path has been stored in result,
     356             : ///          otherwise a platform-specific error_code.
     357             : std::error_code current_path(SmallVectorImpl<char> &result);
     358             : 
     359             : /// Set the current path.
     360             : ///
     361             : /// @param path The path to set.
     362             : /// @returns errc::success if the current path was successfully set,
     363             : ///          otherwise a platform-specific error_code.
     364             : std::error_code set_current_path(const Twine &path);
     365             : 
     366             : /// Remove path. Equivalent to POSIX remove().
     367             : ///
     368             : /// @param path Input path.
     369             : /// @returns errc::success if path has been removed or didn't exist, otherwise a
     370             : ///          platform-specific error code. If IgnoreNonExisting is false, also
     371             : ///          returns error if the file didn't exist.
     372             : std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
     373             : 
     374             : /// Recursively delete a directory.
     375             : ///
     376             : /// @param path Input path.
     377             : /// @returns errc::success if path has been removed or didn't exist, otherwise a
     378             : ///          platform-specific error code.
     379             : std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true);
     380             : 
     381             : /// Rename \a from to \a to.
     382             : ///
     383             : /// Files are renamed as if by POSIX rename(), except that on Windows there may
     384             : /// be a short interval of time during which the destination file does not
     385             : /// exist.
     386             : ///
     387             : /// @param from The path to rename from.
     388             : /// @param to The path to rename to. This is created.
     389             : std::error_code rename(const Twine &from, const Twine &to);
     390             : 
     391             : /// Copy the contents of \a From to \a To.
     392             : ///
     393             : /// @param From The path to copy from.
     394             : /// @param To The path to copy to. This is created.
     395             : std::error_code copy_file(const Twine &From, const Twine &To);
     396             : 
     397             : /// Copy the contents of \a From to \a To.
     398             : ///
     399             : /// @param From The path to copy from.
     400             : /// @param ToFD The open file descriptor of the destination file.
     401             : std::error_code copy_file(const Twine &From, int ToFD);
     402             : 
     403             : /// Resize path to size. File is resized as if by POSIX truncate().
     404             : ///
     405             : /// @param FD Input file descriptor.
     406             : /// @param Size Size to resize to.
     407             : /// @returns errc::success if \a path has been resized to \a size, otherwise a
     408             : ///          platform-specific error_code.
     409             : std::error_code resize_file(int FD, uint64_t Size);
     410             : 
     411             : /// Compute an MD5 hash of a file's contents.
     412             : ///
     413             : /// @param FD Input file descriptor.
     414             : /// @returns An MD5Result with the hash computed, if successful, otherwise a
     415             : ///          std::error_code.
     416             : ErrorOr<MD5::MD5Result> md5_contents(int FD);
     417             : 
     418             : /// Version of compute_md5 that doesn't require an open file descriptor.
     419             : ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path);
     420             : 
     421             : /// @}
     422             : /// @name Physical Observers
     423             : /// @{
     424             : 
     425             : /// Does file exist?
     426             : ///
     427             : /// @param status A basic_file_status previously returned from stat.
     428             : /// @returns True if the file represented by status exists, false if it does
     429             : ///          not.
     430             : bool exists(const basic_file_status &status);
     431             : 
     432             : enum class AccessMode { Exist, Write, Execute };
     433             : 
     434             : /// Can the file be accessed?
     435             : ///
     436             : /// @param Path Input path.
     437             : /// @returns errc::success if the path can be accessed, otherwise a
     438             : ///          platform-specific error_code.
     439             : std::error_code access(const Twine &Path, AccessMode Mode);
     440             : 
     441             : /// Does file exist?
     442             : ///
     443             : /// @param Path Input path.
     444             : /// @returns True if it exists, false otherwise.
     445             : inline bool exists(const Twine &Path) {
     446      209074 :   return !access(Path, AccessMode::Exist);
     447             : }
     448             : 
     449             : /// Can we execute this file?
     450             : ///
     451             : /// @param Path Input path.
     452             : /// @returns True if we can execute it, false otherwise.
     453             : bool can_execute(const Twine &Path);
     454             : 
     455             : /// Can we write this file?
     456             : ///
     457             : /// @param Path Input path.
     458             : /// @returns True if we can write to it, false otherwise.
     459             : inline bool can_write(const Twine &Path) {
     460        5921 :   return !access(Path, AccessMode::Write);
     461             : }
     462             : 
     463             : /// Do file_status's represent the same thing?
     464             : ///
     465             : /// @param A Input file_status.
     466             : /// @param B Input file_status.
     467             : ///
     468             : /// assert(status_known(A) || status_known(B));
     469             : ///
     470             : /// @returns True if A and B both represent the same file system entity, false
     471             : ///          otherwise.
     472             : bool equivalent(file_status A, file_status B);
     473             : 
     474             : /// Do paths represent the same thing?
     475             : ///
     476             : /// assert(status_known(A) || status_known(B));
     477             : ///
     478             : /// @param A Input path A.
     479             : /// @param B Input path B.
     480             : /// @param result Set to true if stat(A) and stat(B) have the same device and
     481             : ///               inode (or equivalent).
     482             : /// @returns errc::success if result has been successfully set, otherwise a
     483             : ///          platform-specific error_code.
     484             : std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
     485             : 
     486             : /// Simpler version of equivalent for clients that don't need to
     487             : ///        differentiate between an error and false.
     488             : inline bool equivalent(const Twine &A, const Twine &B) {
     489             :   bool result;
     490        3827 :   return !equivalent(A, B, result) && result;
     491             : }
     492             : 
     493             : /// Is the file mounted on a local filesystem?
     494             : ///
     495             : /// @param path Input path.
     496             : /// @param result Set to true if \a path is on fixed media such as a hard disk,
     497             : ///               false if it is not.
     498             : /// @returns errc::success if result has been successfully set, otherwise a
     499             : ///          platform specific error_code.
     500             : std::error_code is_local(const Twine &path, bool &result);
     501             : 
     502             : /// Version of is_local accepting an open file descriptor.
     503             : std::error_code is_local(int FD, bool &result);
     504             : 
     505             : /// Simpler version of is_local for clients that don't need to
     506             : ///        differentiate between an error and false.
     507             : inline bool is_local(const Twine &Path) {
     508             :   bool Result;
     509       18500 :   return !is_local(Path, Result) && Result;
     510             : }
     511             : 
     512             : /// Simpler version of is_local accepting an open file descriptor for
     513             : ///        clients that don't need to differentiate between an error and false.
     514             : inline bool is_local(int FD) {
     515             :   bool Result;
     516             :   return !is_local(FD, Result) && Result;
     517             : }
     518             : 
     519             : /// Does status represent a directory?
     520             : ///
     521             : /// @param Path The path to get the type of.
     522             : /// @param Follow For symbolic links, indicates whether to return the file type
     523             : ///               of the link itself, or of the target.
     524             : /// @returns A value from the file_type enumeration indicating the type of file.
     525             : file_type get_file_type(const Twine &Path, bool Follow = true);
     526             : 
     527             : /// Does status represent a directory?
     528             : ///
     529             : /// @param status A basic_file_status previously returned from status.
     530             : /// @returns status.type() == file_type::directory_file.
     531             : bool is_directory(const basic_file_status &status);
     532             : 
     533             : /// Is path a directory?
     534             : ///
     535             : /// @param path Input path.
     536             : /// @param result Set to true if \a path is a directory (after following
     537             : ///               symlinks, false if it is not. Undefined otherwise.
     538             : /// @returns errc::success if result has been successfully set, otherwise a
     539             : ///          platform-specific error_code.
     540             : std::error_code is_directory(const Twine &path, bool &result);
     541             : 
     542             : /// Simpler version of is_directory for clients that don't need to
     543             : ///        differentiate between an error and false.
     544             : inline bool is_directory(const Twine &Path) {
     545             :   bool Result;
     546        7272 :   return !is_directory(Path, Result) && Result;
     547             : }
     548             : 
     549             : /// Does status represent a regular file?
     550             : ///
     551             : /// @param status A basic_file_status previously returned from status.
     552             : /// @returns status_known(status) && status.type() == file_type::regular_file.
     553             : bool is_regular_file(const basic_file_status &status);
     554             : 
     555             : /// Is path a regular file?
     556             : ///
     557             : /// @param path Input path.
     558             : /// @param result Set to true if \a path is a regular file (after following
     559             : ///               symlinks), false if it is not. Undefined otherwise.
     560             : /// @returns errc::success if result has been successfully set, otherwise a
     561             : ///          platform-specific error_code.
     562             : std::error_code is_regular_file(const Twine &path, bool &result);
     563             : 
     564             : /// Simpler version of is_regular_file for clients that don't need to
     565             : ///        differentiate between an error and false.
     566             : inline bool is_regular_file(const Twine &Path) {
     567             :   bool Result;
     568        4390 :   if (is_regular_file(Path, Result))
     569             :     return false;
     570        4342 :   return Result;
     571             : }
     572             : 
     573             : /// Does status represent a symlink file?
     574             : ///
     575             : /// @param status A basic_file_status previously returned from status.
     576             : /// @returns status_known(status) && status.type() == file_type::symlink_file.
     577             : bool is_symlink_file(const basic_file_status &status);
     578             : 
     579             : /// Is path a symlink file?
     580             : ///
     581             : /// @param path Input path.
     582             : /// @param result Set to true if \a path is a symlink file, false if it is not.
     583             : ///               Undefined otherwise.
     584             : /// @returns errc::success if result has been successfully set, otherwise a
     585             : ///          platform-specific error_code.
     586             : std::error_code is_symlink_file(const Twine &path, bool &result);
     587             : 
     588             : /// Simpler version of is_symlink_file for clients that don't need to
     589             : ///        differentiate between an error and false.
     590             : inline bool is_symlink_file(const Twine &Path) {
     591             :   bool Result;
     592           0 :   if (is_symlink_file(Path, Result))
     593             :     return false;
     594           0 :   return Result;
     595             : }
     596             : 
     597             : /// Does this status represent something that exists but is not a
     598             : ///        directory or regular file?
     599             : ///
     600             : /// @param status A basic_file_status previously returned from status.
     601             : /// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
     602             : bool is_other(const basic_file_status &status);
     603             : 
     604             : /// Is path something that exists but is not a directory,
     605             : ///        regular file, or symlink?
     606             : ///
     607             : /// @param path Input path.
     608             : /// @param result Set to true if \a path exists, but is not a directory, regular
     609             : ///               file, or a symlink, false if it does not. Undefined otherwise.
     610             : /// @returns errc::success if result has been successfully set, otherwise a
     611             : ///          platform-specific error_code.
     612             : std::error_code is_other(const Twine &path, bool &result);
     613             : 
     614             : /// Get file status as if by POSIX stat().
     615             : ///
     616             : /// @param path Input path.
     617             : /// @param result Set to the file status.
     618             : /// @param follow When true, follows symlinks.  Otherwise, the symlink itself is
     619             : ///               statted.
     620             : /// @returns errc::success if result has been successfully set, otherwise a
     621             : ///          platform-specific error_code.
     622             : std::error_code status(const Twine &path, file_status &result,
     623             :                        bool follow = true);
     624             : 
     625             : /// A version for when a file descriptor is already available.
     626             : std::error_code status(int FD, file_status &Result);
     627             : 
     628             : /// Set file permissions.
     629             : ///
     630             : /// @param Path File to set permissions on.
     631             : /// @param Permissions New file permissions.
     632             : /// @returns errc::success if the permissions were successfully set, otherwise
     633             : ///          a platform-specific error_code.
     634             : /// @note On Windows, all permissions except *_write are ignored. Using any of
     635             : ///       owner_write, group_write, or all_write will make the file writable.
     636             : ///       Otherwise, the file will be marked as read-only.
     637             : std::error_code setPermissions(const Twine &Path, perms Permissions);
     638             : 
     639             : /// Get file permissions.
     640             : ///
     641             : /// @param Path File to get permissions from.
     642             : /// @returns the permissions if they were successfully retrieved, otherwise a
     643             : ///          platform-specific error_code.
     644             : /// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY
     645             : ///       attribute, all_all will be returned. Otherwise, all_read | all_exe
     646             : ///       will be returned.
     647             : ErrorOr<perms> getPermissions(const Twine &Path);
     648             : 
     649             : /// Get file size.
     650             : ///
     651             : /// @param Path Input path.
     652             : /// @param Result Set to the size of the file in \a Path.
     653             : /// @returns errc::success if result has been successfully set, otherwise a
     654             : ///          platform-specific error_code.
     655       20861 : inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
     656       20861 :   file_status Status;
     657       20861 :   std::error_code EC = status(Path, Status);
     658       20861 :   if (EC)
     659        9281 :     return EC;
     660       23160 :   Result = Status.getSize();
     661       11580 :   return std::error_code();
     662             : }
     663             : 
     664             : /// Set the file modification and access time.
     665             : ///
     666             : /// @returns errc::success if the file times were successfully set, otherwise a
     667             : ///          platform-specific error_code or errc::function_not_supported on
     668             : ///          platforms where the functionality isn't available.
     669             : std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time);
     670             : 
     671             : /// Is status available?
     672             : ///
     673             : /// @param s Input file status.
     674             : /// @returns True if status() != status_error.
     675             : bool status_known(const basic_file_status &s);
     676             : 
     677             : /// Is status available?
     678             : ///
     679             : /// @param path Input path.
     680             : /// @param result Set to true if status() != status_error.
     681             : /// @returns errc::success if result has been successfully set, otherwise a
     682             : ///          platform-specific error_code.
     683             : std::error_code status_known(const Twine &path, bool &result);
     684             : 
     685             : enum CreationDisposition : unsigned {
     686             :   /// CD_CreateAlways - When opening a file:
     687             :   ///   * If it already exists, truncate it.
     688             :   ///   * If it does not already exist, create a new file.
     689             :   CD_CreateAlways = 0,
     690             : 
     691             :   /// CD_CreateNew - When opening a file:
     692             :   ///   * If it already exists, fail.
     693             :   ///   * If it does not already exist, create a new file.
     694             :   CD_CreateNew = 1,
     695             : 
     696             :   /// CD_OpenAlways - When opening a file:
     697             :   ///   * If it already exists, open the file with the offset set to 0.
     698             :   ///   * If it does not already exist, fail.
     699             :   CD_OpenExisting = 2,
     700             : 
     701             :   /// CD_OpenAlways - When opening a file:
     702             :   ///   * If it already exists, open the file with the offset set to 0.
     703             :   ///   * If it does not already exist, create a new file.
     704             :   CD_OpenAlways = 3,
     705             : };
     706             : 
     707             : enum FileAccess : unsigned {
     708             :   FA_Read = 1,
     709             :   FA_Write = 2,
     710             : };
     711             : 
     712             : enum OpenFlags : unsigned {
     713             :   OF_None = 0,
     714             :   F_None = 0, // For compatibility
     715             : 
     716             :   /// The file should be opened in text mode on platforms that make this
     717             :   /// distinction.
     718             :   OF_Text = 1,
     719             :   F_Text = 1, // For compatibility
     720             : 
     721             :   /// The file should be opened in append mode.
     722             :   OF_Append = 2,
     723             :   F_Append = 2, // For compatibility
     724             : 
     725             :   /// Delete the file on close. Only makes a difference on windows.
     726             :   OF_Delete = 4,
     727             : 
     728             :   /// When a child process is launched, this file should remain open in the
     729             :   /// child process.
     730             :   OF_ChildInherit = 8,
     731             : 
     732             :   /// Force files Atime to be updated on access. Only makes a difference on windows.
     733             :   OF_UpdateAtime = 16,
     734             : };
     735             : 
     736             : /// Create a uniquely named file.
     737             : ///
     738             : /// Generates a unique path suitable for a temporary file and then opens it as a
     739             : /// file. The name is based on \a model with '%' replaced by a random char in
     740             : /// [0-9a-f]. If \a model is not an absolute path, the temporary file will be
     741             : /// created in the current directory.
     742             : ///
     743             : /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
     744             : ///
     745             : /// This is an atomic operation. Either the file is created and opened, or the
     746             : /// file system is left untouched.
     747             : ///
     748             : /// The intended use is for files that are to be kept, possibly after
     749             : /// renaming them. For example, when running 'clang -c foo.o', the file can
     750             : /// be first created as foo-abc123.o and then renamed.
     751             : ///
     752             : /// @param Model Name to base unique path off of.
     753             : /// @param ResultFD Set to the opened file's file descriptor.
     754             : /// @param ResultPath Set to the opened file's absolute path.
     755             : /// @returns errc::success if Result{FD,Path} have been successfully set,
     756             : ///          otherwise a platform-specific error_code.
     757             : std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
     758             :                                  SmallVectorImpl<char> &ResultPath,
     759             :                                  unsigned Mode = all_read | all_write);
     760             : 
     761             : /// Simpler version for clients that don't want an open file. An empty
     762             : /// file will still be created.
     763             : std::error_code createUniqueFile(const Twine &Model,
     764             :                                  SmallVectorImpl<char> &ResultPath,
     765             :                                  unsigned Mode = all_read | all_write);
     766             : 
     767             : /// Represents a temporary file.
     768             : ///
     769             : /// The temporary file must be eventually discarded or given a final name and
     770             : /// kept.
     771             : ///
     772             : /// The destructor doesn't implicitly discard because there is no way to
     773             : /// properly handle errors in a destructor.
     774             : class TempFile {
     775             :   bool Done = false;
     776             :   TempFile(StringRef Name, int FD);
     777             : 
     778             : public:
     779             :   /// This creates a temporary file with createUniqueFile and schedules it for
     780             :   /// deletion with sys::RemoveFileOnSignal.
     781             :   static Expected<TempFile> create(const Twine &Model,
     782             :                                    unsigned Mode = all_read | all_write);
     783             :   TempFile(TempFile &&Other);
     784             :   TempFile &operator=(TempFile &&Other);
     785             : 
     786             :   // Name of the temporary file.
     787             :   std::string TmpName;
     788             : 
     789             :   // The open file descriptor.
     790             :   int FD = -1;
     791             : 
     792             :   // Keep this with the given name.
     793             :   Error keep(const Twine &Name);
     794             : 
     795             :   // Keep this with the temporary name.
     796             :   Error keep();
     797             : 
     798             :   // Delete the file.
     799             :   Error discard();
     800             : 
     801             :   // This checks that keep or delete was called.
     802             :   ~TempFile();
     803             : };
     804             : 
     805             : /// Create a file in the system temporary directory.
     806             : ///
     807             : /// The filename is of the form prefix-random_chars.suffix. Since the directory
     808             : /// is not know to the caller, Prefix and Suffix cannot have path separators.
     809             : /// The files are created with mode 0600.
     810             : ///
     811             : /// This should be used for things like a temporary .s that is removed after
     812             : /// running the assembler.
     813             : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     814             :                                     int &ResultFD,
     815             :                                     SmallVectorImpl<char> &ResultPath);
     816             : 
     817             : /// Simpler version for clients that don't want an open file. An empty
     818             : /// file will still be created.
     819             : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     820             :                                     SmallVectorImpl<char> &ResultPath);
     821             : 
     822             : std::error_code createUniqueDirectory(const Twine &Prefix,
     823             :                                       SmallVectorImpl<char> &ResultPath);
     824             : 
     825             : /// Get a unique name, not currently exisiting in the filesystem. Subject
     826             : /// to race conditions, prefer to use createUniqueFile instead.
     827             : ///
     828             : /// Similar to createUniqueFile, but instead of creating a file only
     829             : /// checks if it exists. This function is subject to race conditions, if you
     830             : /// want to use the returned name to actually create a file, use
     831             : /// createUniqueFile instead.
     832             : std::error_code getPotentiallyUniqueFileName(const Twine &Model,
     833             :                                              SmallVectorImpl<char> &ResultPath);
     834             : 
     835             : /// Get a unique temporary file name, not currently exisiting in the
     836             : /// filesystem. Subject to race conditions, prefer to use createTemporaryFile
     837             : /// instead.
     838             : ///
     839             : /// Similar to createTemporaryFile, but instead of creating a file only
     840             : /// checks if it exists. This function is subject to race conditions, if you
     841             : /// want to use the returned name to actually create a file, use
     842             : /// createTemporaryFile instead.
     843             : std::error_code
     844             : getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
     845             :                                  SmallVectorImpl<char> &ResultPath);
     846             : 
     847             : inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
     848             :   return OpenFlags(unsigned(A) | unsigned(B));
     849             : }
     850             : 
     851             : inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
     852             :   A = A | B;
     853             :   return A;
     854             : }
     855             : 
     856             : inline FileAccess operator|(FileAccess A, FileAccess B) {
     857             :   return FileAccess(unsigned(A) | unsigned(B));
     858             : }
     859             : 
     860             : inline FileAccess &operator|=(FileAccess &A, FileAccess B) {
     861             :   A = A | B;
     862             :   return A;
     863             : }
     864             : 
     865             : /// @brief Opens a file with the specified creation disposition, access mode,
     866             : /// and flags and returns a file descriptor.
     867             : ///
     868             : /// The caller is responsible for closing the file descriptor once they are
     869             : /// finished with it.
     870             : ///
     871             : /// @param Name The path of the file to open, relative or absolute.
     872             : /// @param ResultFD If the file could be opened successfully, its descriptor
     873             : ///                 is stored in this location. Otherwise, this is set to -1.
     874             : /// @param Disp Value specifying the existing-file behavior.
     875             : /// @param Access Value specifying whether to open the file in read, write, or
     876             : ///               read-write mode.
     877             : /// @param Flags Additional flags.
     878             : /// @param Mode The access permissions of the file, represented in octal.
     879             : /// @returns errc::success if \a Name has been opened, otherwise a
     880             : ///          platform-specific error_code.
     881             : std::error_code openFile(const Twine &Name, int &ResultFD,
     882             :                          CreationDisposition Disp, FileAccess Access,
     883             :                          OpenFlags Flags, unsigned Mode = 0666);
     884             : 
     885             : /// @brief Opens a file with the specified creation disposition, access mode,
     886             : /// and flags and returns a platform-specific file object.
     887             : ///
     888             : /// The caller is responsible for closing the file object once they are
     889             : /// finished with it.
     890             : ///
     891             : /// @param Name The path of the file to open, relative or absolute.
     892             : /// @param Disp Value specifying the existing-file behavior.
     893             : /// @param Access Value specifying whether to open the file in read, write, or
     894             : ///               read-write mode.
     895             : /// @param Flags Additional flags.
     896             : /// @param Mode The access permissions of the file, represented in octal.
     897             : /// @returns errc::success if \a Name has been opened, otherwise a
     898             : ///          platform-specific error_code.
     899             : Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
     900             :                                 FileAccess Access, OpenFlags Flags,
     901             :                                 unsigned Mode = 0666);
     902             : 
     903             : /// @brief Opens the file with the given name in a write-only or read-write
     904             : /// mode, returning its open file descriptor. If the file does not exist, it
     905             : /// is created.
     906             : ///
     907             : /// The caller is responsible for closing the file descriptor once they are
     908             : /// finished with it.
     909             : ///
     910             : /// @param Name The path of the file to open, relative or absolute.
     911             : /// @param ResultFD If the file could be opened successfully, its descriptor
     912             : ///                 is stored in this location. Otherwise, this is set to -1.
     913             : /// @param Flags Additional flags used to determine whether the file should be
     914             : ///              opened in, for example, read-write or in write-only mode.
     915             : /// @param Mode The access permissions of the file, represented in octal.
     916             : /// @returns errc::success if \a Name has been opened, otherwise a
     917             : ///          platform-specific error_code.
     918             : inline std::error_code
     919             : openFileForWrite(const Twine &Name, int &ResultFD,
     920             :                  CreationDisposition Disp = CD_CreateAlways,
     921             :                  OpenFlags Flags = OF_None, unsigned Mode = 0666) {
     922       10622 :   return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
     923             : }
     924             : 
     925             : /// @brief Opens the file with the given name in a write-only or read-write
     926             : /// mode, returning its open file descriptor. If the file does not exist, it
     927             : /// is created.
     928             : ///
     929             : /// The caller is responsible for closing the freeing the file once they are
     930             : /// finished with it.
     931             : ///
     932             : /// @param Name The path of the file to open, relative or absolute.
     933             : /// @param Flags Additional flags used to determine whether the file should be
     934             : ///              opened in, for example, read-write or in write-only mode.
     935             : /// @param Mode The access permissions of the file, represented in octal.
     936             : /// @returns a platform-specific file descriptor if \a Name has been opened,
     937             : ///          otherwise an error object.
     938             : inline Expected<file_t> openNativeFileForWrite(const Twine &Name,
     939             :                                                CreationDisposition Disp,
     940             :                                                OpenFlags Flags,
     941             :                                                unsigned Mode = 0666) {
     942             :   return openNativeFile(Name, Disp, FA_Write, Flags, Mode);
     943             : }
     944             : 
     945             : /// @brief Opens the file with the given name in a write-only or read-write
     946             : /// mode, returning its open file descriptor. If the file does not exist, it
     947             : /// is created.
     948             : ///
     949             : /// The caller is responsible for closing the file descriptor once they are
     950             : /// finished with it.
     951             : ///
     952             : /// @param Name The path of the file to open, relative or absolute.
     953             : /// @param ResultFD If the file could be opened successfully, its descriptor
     954             : ///                 is stored in this location. Otherwise, this is set to -1.
     955             : /// @param Flags Additional flags used to determine whether the file should be
     956             : ///              opened in, for example, read-write or in write-only mode.
     957             : /// @param Mode The access permissions of the file, represented in octal.
     958             : /// @returns errc::success if \a Name has been opened, otherwise a
     959             : ///          platform-specific error_code.
     960             : inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
     961             :                                             CreationDisposition Disp,
     962             :                                             OpenFlags Flags,
     963             :                                             unsigned Mode = 0666) {
     964       20157 :   return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode);
     965             : }
     966             : 
     967             : /// @brief Opens the file with the given name in a write-only or read-write
     968             : /// mode, returning its open file descriptor. If the file does not exist, it
     969             : /// is created.
     970             : ///
     971             : /// The caller is responsible for closing the freeing the file once they are
     972             : /// finished with it.
     973             : ///
     974             : /// @param Name The path of the file to open, relative or absolute.
     975             : /// @param Flags Additional flags used to determine whether the file should be
     976             : ///              opened in, for example, read-write or in write-only mode.
     977             : /// @param Mode The access permissions of the file, represented in octal.
     978             : /// @returns a platform-specific file descriptor if \a Name has been opened,
     979             : ///          otherwise an error object.
     980             : inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name,
     981             :                                                    CreationDisposition Disp,
     982             :                                                    OpenFlags Flags,
     983             :                                                    unsigned Mode = 0666) {
     984             :   return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode);
     985             : }
     986             : 
     987             : /// @brief Opens the file with the given name in a read-only mode, returning
     988             : /// its open file descriptor.
     989             : ///
     990             : /// The caller is responsible for closing the file descriptor once they are
     991             : /// finished with it.
     992             : ///
     993             : /// @param Name The path of the file to open, relative or absolute.
     994             : /// @param ResultFD If the file could be opened successfully, its descriptor
     995             : ///                 is stored in this location. Otherwise, this is set to -1.
     996             : /// @param RealPath If nonnull, extra work is done to determine the real path
     997             : ///                 of the opened file, and that path is stored in this
     998             : ///                 location.
     999             : /// @returns errc::success if \a Name has been opened, otherwise a
    1000             : ///          platform-specific error_code.
    1001             : std::error_code openFileForRead(const Twine &Name, int &ResultFD,
    1002             :                                 OpenFlags Flags = OF_None,
    1003             :                                 SmallVectorImpl<char> *RealPath = nullptr);
    1004             : 
    1005             : /// @brief Opens the file with the given name in a read-only mode, returning
    1006             : /// its open file descriptor.
    1007             : ///
    1008             : /// The caller is responsible for closing the freeing the file once they are
    1009             : /// finished with it.
    1010             : ///
    1011             : /// @param Name The path of the file to open, relative or absolute.
    1012             : /// @param RealPath If nonnull, extra work is done to determine the real path
    1013             : ///                 of the opened file, and that path is stored in this
    1014             : ///                 location.
    1015             : /// @returns a platform-specific file descriptor if \a Name has been opened,
    1016             : ///          otherwise an error object.
    1017             : Expected<file_t>
    1018             : openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None,
    1019             :                       SmallVectorImpl<char> *RealPath = nullptr);
    1020             : 
    1021             : /// @brief Close the file object.  This should be used instead of ::close for
    1022             : /// portability.
    1023             : ///
    1024             : /// @param F On input, this is the file to close.  On output, the file is
    1025             : /// set to kInvalidFile.
    1026             : void closeFile(file_t &F);
    1027             : 
    1028             : std::error_code getUniqueID(const Twine Path, UniqueID &Result);
    1029             : 
    1030             : /// Get disk space usage information.
    1031             : ///
    1032             : /// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
    1033             : /// Note: Windows reports results according to the quota allocated to the user.
    1034             : ///
    1035             : /// @param Path Input path.
    1036             : /// @returns a space_info structure filled with the capacity, free, and
    1037             : /// available space on the device \a Path is on. A platform specific error_code
    1038             : /// is returned on error.
    1039             : ErrorOr<space_info> disk_space(const Twine &Path);
    1040             : 
    1041             : /// This class represents a memory mapped file. It is based on
    1042             : /// boost::iostreams::mapped_file.
    1043             : class mapped_file_region {
    1044             : public:
    1045             :   enum mapmode {
    1046             :     readonly, ///< May only access map via const_data as read only.
    1047             :     readwrite, ///< May access map via data and modify it. Written to path.
    1048             :     priv ///< May modify via data, but changes are lost on destruction.
    1049             :   };
    1050             : 
    1051             : private:
    1052             :   /// Platform-specific mapping state.
    1053             :   size_t Size;
    1054             :   void *Mapping;
    1055             : #ifdef _WIN32
    1056             :   void *FileHandle;
    1057             : #endif
    1058             :   mapmode Mode;
    1059             : 
    1060             :   std::error_code init(int FD, uint64_t Offset, mapmode Mode);
    1061             : 
    1062             : public:
    1063             :   mapped_file_region() = delete;
    1064             :   mapped_file_region(mapped_file_region&) = delete;
    1065             :   mapped_file_region &operator =(mapped_file_region&) = delete;
    1066             : 
    1067             :   /// \param fd An open file descriptor to map. mapped_file_region takes
    1068             :   ///   ownership if closefd is true. It must have been opended in the correct
    1069             :   ///   mode.
    1070             :   mapped_file_region(int fd, mapmode mode, size_t length, uint64_t offset,
    1071             :                      std::error_code &ec);
    1072             : 
    1073             :   ~mapped_file_region();
    1074             : 
    1075             :   size_t size() const;
    1076             :   char *data() const;
    1077             : 
    1078             :   /// Get a const view of the data. Modifying this memory has undefined
    1079             :   /// behavior.
    1080             :   const char *const_data() const;
    1081             : 
    1082             :   /// \returns The minimum alignment offset must be.
    1083             :   static int alignment();
    1084             : };
    1085             : 
    1086             : /// Return the path to the main executable, given the value of argv[0] from
    1087             : /// program startup and the address of main itself. In extremis, this function
    1088             : /// may fail and return an empty path.
    1089             : std::string getMainExecutable(const char *argv0, void *MainExecAddr);
    1090             : 
    1091             : /// @}
    1092             : /// @name Iterators
    1093             : /// @{
    1094             : 
    1095             : /// directory_entry - A single entry in a directory. Caches the status either
    1096             : /// from the result of the iteration syscall, or the first time status is
    1097             : /// called.
    1098     2500028 : class directory_entry {
    1099             :   std::string Path;
    1100             :   bool FollowSymlinks;
    1101             :   basic_file_status Status;
    1102             : 
    1103             : public:
    1104             :   explicit directory_entry(const Twine &path, bool follow_symlinks = true,
    1105             :                            basic_file_status st = basic_file_status())
    1106       23644 :       : Path(path.str()), FollowSymlinks(follow_symlinks), Status(st) {}
    1107             : 
    1108             :   directory_entry() = default;
    1109             : 
    1110             :   void assign(const Twine &path, basic_file_status st = basic_file_status()) {
    1111             :     Path = path.str();
    1112             :     Status = st;
    1113             :   }
    1114             : 
    1115             :   void replace_filename(const Twine &filename,
    1116             :                         basic_file_status st = basic_file_status());
    1117             : 
    1118      281915 :   const std::string &path() const { return Path; }
    1119             :   ErrorOr<basic_file_status> status() const;
    1120             : 
    1121     3045871 :   bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; }
    1122             :   bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); }
    1123             :   bool operator< (const directory_entry& rhs) const;
    1124             :   bool operator<=(const directory_entry& rhs) const;
    1125             :   bool operator> (const directory_entry& rhs) const;
    1126             :   bool operator>=(const directory_entry& rhs) const;
    1127             : };
    1128             : 
    1129             : namespace detail {
    1130             : 
    1131             :   struct DirIterState;
    1132             : 
    1133             :   std::error_code directory_iterator_construct(DirIterState &, StringRef, bool);
    1134             :   std::error_code directory_iterator_increment(DirIterState &);
    1135             :   std::error_code directory_iterator_destruct(DirIterState &);
    1136             : 
    1137             :   /// Keeps state for the directory_iterator.
    1138             :   struct DirIterState {
    1139     4905519 :     ~DirIterState() {
    1140     2452762 :       directory_iterator_destruct(*this);
    1141     2452757 :     }
    1142             : 
    1143             :     intptr_t IterationHandle = 0;
    1144             :     directory_entry CurrentEntry;
    1145             :   };
    1146             : 
    1147             : } // end namespace detail
    1148             : 
    1149             : /// directory_iterator - Iterates through the entries in path. There is no
    1150             : /// operator++ because we need an error_code. If it's really needed we can make
    1151             : /// it call report_fatal_error on error.
    1152     2453107 : class directory_iterator {
    1153             :   std::shared_ptr<detail::DirIterState> State;
    1154             :   bool FollowSymlinks = true;
    1155             : 
    1156             : public:
    1157     2452726 :   explicit directory_iterator(const Twine &path, std::error_code &ec,
    1158             :                               bool follow_symlinks = true)
    1159     4905452 :       : FollowSymlinks(follow_symlinks) {
    1160     2452687 :     State = std::make_shared<detail::DirIterState>();
    1161             :     SmallString<128> path_storage;
    1162     2452685 :     ec = detail::directory_iterator_construct(
    1163     2452687 :         *State, path.toStringRef(path_storage), FollowSymlinks);
    1164     2452712 :     update_error_code_for_current_entry(ec);
    1165     2452706 :   }
    1166             : 
    1167          97 :   explicit directory_iterator(const directory_entry &de, std::error_code &ec,
    1168             :                               bool follow_symlinks = true)
    1169         194 :       : FollowSymlinks(follow_symlinks) {
    1170          97 :     State = std::make_shared<detail::DirIterState>();
    1171          97 :     ec = detail::directory_iterator_construct(
    1172         194 :         *State, de.path(), FollowSymlinks);
    1173          97 :     update_error_code_for_current_entry(ec);
    1174          97 :   }
    1175             : 
    1176             :   /// Construct end iterator.
    1177     2733563 :   directory_iterator() = default;
    1178             : 
    1179             :   // No operator++ because we need error_code.
    1180             :   directory_iterator &increment(std::error_code &ec) {
    1181      284965 :     ec = directory_iterator_increment(*State);
    1182      284965 :     update_error_code_for_current_entry(ec);
    1183             :     return *this;
    1184             :   }
    1185             : 
    1186         360 :   const directory_entry &operator*() const { return State->CurrentEntry; }
    1187         284 :   const directory_entry *operator->() const { return &State->CurrentEntry; }
    1188             : 
    1189     2737501 :   bool operator==(const directory_iterator &RHS) const {
    1190     2737501 :     if (State == RHS.State)
    1191             :       return true;
    1192     2737262 :     if (!RHS.State)
    1193     5474524 :       return State->CurrentEntry == directory_entry();
    1194           0 :     if (!State)
    1195           0 :       return RHS.State->CurrentEntry == directory_entry();
    1196           0 :     return State->CurrentEntry == RHS.State->CurrentEntry;
    1197             :   }
    1198             : 
    1199             :   bool operator!=(const directory_iterator &RHS) const {
    1200     2455582 :     return !(*this == RHS);
    1201             :   }
    1202             :   // Other members as required by
    1203             :   // C++ Std, 24.1.1 Input iterators [input.iterators]
    1204             : 
    1205             : private:
    1206             :   // Checks if current entry is valid and populates error code. For example,
    1207             :   // current entry may not exist due to broken symbol links.
    1208     2737773 :   void update_error_code_for_current_entry(std::error_code &ec) {
    1209             :     // Bail out if error has already occured earlier to avoid overwriting it.
    1210     2737773 :     if (ec)
    1211     2452792 :       return;
    1212             : 
    1213             :     // Empty directory entry is used to mark the end of an interation, it's not
    1214             :     // an error.
    1215      617218 :     if (State->CurrentEntry == directory_entry())
    1216             :       return;
    1217             : 
    1218      284981 :     ErrorOr<basic_file_status> status = State->CurrentEntry.status();
    1219      284982 :     if (!status)
    1220          15 :       ec = status.getError();
    1221             :   }
    1222             : };
    1223             : 
    1224             : namespace detail {
    1225             : 
    1226             :   /// Keeps state for the recursive_directory_iterator.
    1227          41 :   struct RecDirIterState {
    1228             :     std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
    1229             :     uint16_t Level = 0;
    1230             :     bool HasNoPushRequest = false;
    1231             :   };
    1232             : 
    1233             : } // end namespace detail
    1234             : 
    1235             : /// recursive_directory_iterator - Same as directory_iterator except for it
    1236             : /// recurses down into child directories.
    1237           2 : class recursive_directory_iterator {
    1238             :   std::shared_ptr<detail::RecDirIterState> State;
    1239             :   bool Follow;
    1240             : 
    1241             : public:
    1242             :   recursive_directory_iterator() = default;
    1243          41 :   explicit recursive_directory_iterator(const Twine &path, std::error_code &ec,
    1244             :                                         bool follow_symlinks = true)
    1245          41 :       : State(std::make_shared<detail::RecDirIterState>()),
    1246          41 :         Follow(follow_symlinks) {
    1247          82 :     State->Stack.push(directory_iterator(path, ec, Follow));
    1248          82 :     if (State->Stack.top() == directory_iterator())
    1249             :       State.reset();
    1250          41 :   }
    1251             : 
    1252             :   // No operator++ because we need error_code.
    1253         214 :   recursive_directory_iterator &increment(std::error_code &ec) {
    1254             :     const directory_iterator end_itr = {};
    1255             : 
    1256         214 :     if (State->HasNoPushRequest)
    1257           1 :       State->HasNoPushRequest = false;
    1258             :     else {
    1259         213 :       ErrorOr<basic_file_status> status = State->Stack.top()->status();
    1260         213 :       if (status && is_directory(*status)) {
    1261         132 :         State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
    1262          44 :         if (State->Stack.top() != end_itr) {
    1263          35 :           ++State->Level;
    1264             :           return *this;
    1265             :         }
    1266             :         State->Stack.pop();
    1267             :       }
    1268             :     }
    1269             : 
    1270          75 :     while (!State->Stack.empty()
    1271         467 :            && State->Stack.top().increment(ec) == end_itr) {
    1272             :       State->Stack.pop();
    1273          75 :       --State->Level;
    1274             :     }
    1275             : 
    1276             :     // Check if we are done. If so, create an end iterator.
    1277         179 :     if (State->Stack.empty())
    1278             :       State.reset();
    1279             : 
    1280             :     return *this;
    1281             :   }
    1282             : 
    1283             :   const directory_entry &operator*() const { return *State->Stack.top(); }
    1284             :   const directory_entry *operator->() const { return &*State->Stack.top(); }
    1285             : 
    1286             :   // observers
    1287             :   /// Gets the current level. Starting path is at level 0.
    1288           3 :   int level() const { return State->Level; }
    1289             : 
    1290             :   /// Returns true if no_push has been called for this directory_entry.
    1291             :   bool no_push_request() const { return State->HasNoPushRequest; }
    1292             : 
    1293             :   // modifiers
    1294             :   /// Goes up one level if Level > 0.
    1295           1 :   void pop() {
    1296             :     assert(State && "Cannot pop an end iterator!");
    1297             :     assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
    1298             : 
    1299             :     const directory_iterator end_itr = {};
    1300             :     std::error_code ec;
    1301             :     do {
    1302           1 :       if (ec)
    1303           0 :         report_fatal_error("Error incrementing directory iterator.");
    1304             :       State->Stack.pop();
    1305           1 :       --State->Level;
    1306             :     } while (!State->Stack.empty()
    1307           2 :              && State->Stack.top().increment(ec) == end_itr);
    1308             : 
    1309             :     // Check if we are done. If so, create an end iterator.
    1310           1 :     if (State->Stack.empty())
    1311             :       State.reset();
    1312           1 :   }
    1313             : 
    1314             :   /// Does not go down into the current directory_entry.
    1315           1 :   void no_push() { State->HasNoPushRequest = true; }
    1316             : 
    1317             :   bool operator==(const recursive_directory_iterator &RHS) const {
    1318             :     return State == RHS.State;
    1319             :   }
    1320             : 
    1321             :   bool operator!=(const recursive_directory_iterator &RHS) const {
    1322             :     return !(*this == RHS);
    1323             :   }
    1324             :   // Other members as required by
    1325             :   // C++ Std, 24.1.1 Input iterators [input.iterators]
    1326             : };
    1327             : 
    1328             : /// @}
    1329             : 
    1330             : } // end namespace fs
    1331             : } // end namespace sys
    1332             : } // end namespace llvm
    1333             : 
    1334             : #endif // LLVM_SUPPORT_FILESYSTEM_H

Generated by: LCOV version 1.13