LCOV - code coverage report
Current view: top level - include/llvm/Support - FileSystem.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 87 101 86.1 %
Date: 2018-10-20 13:21:21 Functions: 9 17 52.9 %
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       63035 :   return static_cast<perms>(static_cast<unsigned short>(l) |
     115       63035 :                             static_cast<unsigned short>(r));
     116             : }
     117             : inline perms operator&(perms l, perms r) {
     118     1742528 :   return static_cast<perms>(static_cast<unsigned short>(l) &
     119     1742213 :                             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         923 :   UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
     142             : 
     143           0 :   bool operator==(const UniqueID &Other) const {
     144       33404 :     return Device == Other.Device && File == Other.File;
     145             :   }
     146           2 :   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           0 :   uint64_t getDevice() const { return Device; }
     152           0 :   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     8741815 :   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           0 :   file_type type() const { return Type; }
     201           0 :   perms permissions() const { return Perms; }
     202             :   TimePoint<> getLastAccessedTime() const;
     203             :   TimePoint<> getLastModificationTime() const;
     204             : 
     205             :   #if defined(LLVM_ON_UNIX)
     206           0 :   uint32_t getUser() const { return fs_st_uid; }
     207           0 :   uint32_t getGroup() const { return fs_st_gid; }
     208     1651208 :   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      184102 :   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        6776 :   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         249 :   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             :   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        4395 :   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        4896 :   if (is_regular_file(Path, Result))
     569             :     return false;
     570        4848 :   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             :   if (is_symlink_file(Path, Result))
     593             :     return false;
     594             :   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         157 : inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
     656         157 :   file_status Status;
     657         157 :   std::error_code EC = status(Path, Status);
     658         157 :   if (EC)
     659           0 :     return EC;
     660         157 :   Result = Status.getSize();
     661         157 :   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 setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
     670             :                                                  TimePoint<> ModificationTime);
     671             : 
     672             : /// Simpler version that sets both file modification and access time to the same
     673             : /// time.
     674             : inline std::error_code setLastAccessAndModificationTime(int FD,
     675             :                                                         TimePoint<> Time) {
     676           1 :   return setLastAccessAndModificationTime(FD, Time, Time);
     677             : }
     678             : 
     679             : /// Is status available?
     680             : ///
     681             : /// @param s Input file status.
     682             : /// @returns True if status() != status_error.
     683             : bool status_known(const basic_file_status &s);
     684             : 
     685             : /// Is status available?
     686             : ///
     687             : /// @param path Input path.
     688             : /// @param result Set to true if status() != status_error.
     689             : /// @returns errc::success if result has been successfully set, otherwise a
     690             : ///          platform-specific error_code.
     691             : std::error_code status_known(const Twine &path, bool &result);
     692             : 
     693             : enum CreationDisposition : unsigned {
     694             :   /// CD_CreateAlways - When opening a file:
     695             :   ///   * If it already exists, truncate it.
     696             :   ///   * If it does not already exist, create a new file.
     697             :   CD_CreateAlways = 0,
     698             : 
     699             :   /// CD_CreateNew - When opening a file:
     700             :   ///   * If it already exists, fail.
     701             :   ///   * If it does not already exist, create a new file.
     702             :   CD_CreateNew = 1,
     703             : 
     704             :   /// CD_OpenExisting - When opening a file:
     705             :   ///   * If it already exists, open the file with the offset set to 0.
     706             :   ///   * If it does not already exist, fail.
     707             :   CD_OpenExisting = 2,
     708             : 
     709             :   /// CD_OpenAlways - When opening a file:
     710             :   ///   * If it already exists, open the file with the offset set to 0.
     711             :   ///   * If it does not already exist, create a new file.
     712             :   CD_OpenAlways = 3,
     713             : };
     714             : 
     715             : enum FileAccess : unsigned {
     716             :   FA_Read = 1,
     717             :   FA_Write = 2,
     718             : };
     719             : 
     720             : enum OpenFlags : unsigned {
     721             :   OF_None = 0,
     722             :   F_None = 0, // For compatibility
     723             : 
     724             :   /// The file should be opened in text mode on platforms that make this
     725             :   /// distinction.
     726             :   OF_Text = 1,
     727             :   F_Text = 1, // For compatibility
     728             : 
     729             :   /// The file should be opened in append mode.
     730             :   OF_Append = 2,
     731             :   F_Append = 2, // For compatibility
     732             : 
     733             :   /// Delete the file on close. Only makes a difference on windows.
     734             :   OF_Delete = 4,
     735             : 
     736             :   /// When a child process is launched, this file should remain open in the
     737             :   /// child process.
     738             :   OF_ChildInherit = 8,
     739             : 
     740             :   /// Force files Atime to be updated on access. Only makes a difference on windows.
     741             :   OF_UpdateAtime = 16,
     742             : };
     743             : 
     744             : /// Create a uniquely named file.
     745             : ///
     746             : /// Generates a unique path suitable for a temporary file and then opens it as a
     747             : /// file. The name is based on \a model with '%' replaced by a random char in
     748             : /// [0-9a-f]. If \a model is not an absolute path, the temporary file will be
     749             : /// created in the current directory.
     750             : ///
     751             : /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
     752             : ///
     753             : /// This is an atomic operation. Either the file is created and opened, or the
     754             : /// file system is left untouched.
     755             : ///
     756             : /// The intended use is for files that are to be kept, possibly after
     757             : /// renaming them. For example, when running 'clang -c foo.o', the file can
     758             : /// be first created as foo-abc123.o and then renamed.
     759             : ///
     760             : /// @param Model Name to base unique path off of.
     761             : /// @param ResultFD Set to the opened file's file descriptor.
     762             : /// @param ResultPath Set to the opened file's absolute path.
     763             : /// @returns errc::success if Result{FD,Path} have been successfully set,
     764             : ///          otherwise a platform-specific error_code.
     765             : std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
     766             :                                  SmallVectorImpl<char> &ResultPath,
     767             :                                  unsigned Mode = all_read | all_write);
     768             : 
     769             : /// Simpler version for clients that don't want an open file. An empty
     770             : /// file will still be created.
     771             : std::error_code createUniqueFile(const Twine &Model,
     772             :                                  SmallVectorImpl<char> &ResultPath,
     773             :                                  unsigned Mode = all_read | all_write);
     774             : 
     775             : /// Represents a temporary file.
     776             : ///
     777             : /// The temporary file must be eventually discarded or given a final name and
     778             : /// kept.
     779             : ///
     780             : /// The destructor doesn't implicitly discard because there is no way to
     781             : /// properly handle errors in a destructor.
     782             : class TempFile {
     783             :   bool Done = false;
     784             :   TempFile(StringRef Name, int FD);
     785             : 
     786             : public:
     787             :   /// This creates a temporary file with createUniqueFile and schedules it for
     788             :   /// deletion with sys::RemoveFileOnSignal.
     789             :   static Expected<TempFile> create(const Twine &Model,
     790             :                                    unsigned Mode = all_read | all_write);
     791             :   TempFile(TempFile &&Other);
     792             :   TempFile &operator=(TempFile &&Other);
     793             : 
     794             :   // Name of the temporary file.
     795             :   std::string TmpName;
     796             : 
     797             :   // The open file descriptor.
     798             :   int FD = -1;
     799             : 
     800             :   // Keep this with the given name.
     801             :   Error keep(const Twine &Name);
     802             : 
     803             :   // Keep this with the temporary name.
     804             :   Error keep();
     805             : 
     806             :   // Delete the file.
     807             :   Error discard();
     808             : 
     809             :   // This checks that keep or delete was called.
     810             :   ~TempFile();
     811             : };
     812             : 
     813             : /// Create a file in the system temporary directory.
     814             : ///
     815             : /// The filename is of the form prefix-random_chars.suffix. Since the directory
     816             : /// is not know to the caller, Prefix and Suffix cannot have path separators.
     817             : /// The files are created with mode 0600.
     818             : ///
     819             : /// This should be used for things like a temporary .s that is removed after
     820             : /// running the assembler.
     821             : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     822             :                                     int &ResultFD,
     823             :                                     SmallVectorImpl<char> &ResultPath);
     824             : 
     825             : /// Simpler version for clients that don't want an open file. An empty
     826             : /// file will still be created.
     827             : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     828             :                                     SmallVectorImpl<char> &ResultPath);
     829             : 
     830             : std::error_code createUniqueDirectory(const Twine &Prefix,
     831             :                                       SmallVectorImpl<char> &ResultPath);
     832             : 
     833             : /// Get a unique name, not currently exisiting in the filesystem. Subject
     834             : /// to race conditions, prefer to use createUniqueFile instead.
     835             : ///
     836             : /// Similar to createUniqueFile, but instead of creating a file only
     837             : /// checks if it exists. This function is subject to race conditions, if you
     838             : /// want to use the returned name to actually create a file, use
     839             : /// createUniqueFile instead.
     840             : std::error_code getPotentiallyUniqueFileName(const Twine &Model,
     841             :                                              SmallVectorImpl<char> &ResultPath);
     842             : 
     843             : /// Get a unique temporary file name, not currently exisiting in the
     844             : /// filesystem. Subject to race conditions, prefer to use createTemporaryFile
     845             : /// instead.
     846             : ///
     847             : /// Similar to createTemporaryFile, but instead of creating a file only
     848             : /// checks if it exists. This function is subject to race conditions, if you
     849             : /// want to use the returned name to actually create a file, use
     850             : /// createTemporaryFile instead.
     851             : std::error_code
     852             : getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
     853             :                                  SmallVectorImpl<char> &ResultPath);
     854             : 
     855             : inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
     856             :   return OpenFlags(unsigned(A) | unsigned(B));
     857             : }
     858             : 
     859             : inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
     860             :   A = A | B;
     861             :   return A;
     862             : }
     863             : 
     864             : inline FileAccess operator|(FileAccess A, FileAccess B) {
     865             :   return FileAccess(unsigned(A) | unsigned(B));
     866             : }
     867             : 
     868             : inline FileAccess &operator|=(FileAccess &A, FileAccess B) {
     869             :   A = A | B;
     870             :   return A;
     871             : }
     872             : 
     873             : /// @brief Opens a file with the specified creation disposition, access mode,
     874             : /// and flags and returns a file descriptor.
     875             : ///
     876             : /// The caller is responsible for closing the file descriptor once they are
     877             : /// finished with it.
     878             : ///
     879             : /// @param Name The path of the file to open, relative or absolute.
     880             : /// @param ResultFD If the file could be opened successfully, its descriptor
     881             : ///                 is stored in this location. Otherwise, this is set to -1.
     882             : /// @param Disp Value specifying the existing-file behavior.
     883             : /// @param Access Value specifying whether to open the file in read, write, or
     884             : ///               read-write mode.
     885             : /// @param Flags Additional flags.
     886             : /// @param Mode The access permissions of the file, represented in octal.
     887             : /// @returns errc::success if \a Name has been opened, otherwise a
     888             : ///          platform-specific error_code.
     889             : std::error_code openFile(const Twine &Name, int &ResultFD,
     890             :                          CreationDisposition Disp, FileAccess Access,
     891             :                          OpenFlags Flags, unsigned Mode = 0666);
     892             : 
     893             : /// @brief Opens a file with the specified creation disposition, access mode,
     894             : /// and flags and returns a platform-specific file object.
     895             : ///
     896             : /// The caller is responsible for closing the file object once they are
     897             : /// finished with it.
     898             : ///
     899             : /// @param Name The path of the file to open, relative or absolute.
     900             : /// @param Disp Value specifying the existing-file behavior.
     901             : /// @param Access Value specifying whether to open the file in read, write, or
     902             : ///               read-write mode.
     903             : /// @param Flags Additional flags.
     904             : /// @param Mode The access permissions of the file, represented in octal.
     905             : /// @returns errc::success if \a Name has been opened, otherwise a
     906             : ///          platform-specific error_code.
     907             : Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
     908             :                                 FileAccess Access, OpenFlags Flags,
     909             :                                 unsigned Mode = 0666);
     910             : 
     911             : /// @brief Opens the file with the given name in a write-only or read-write
     912             : /// mode, returning its open file descriptor. If the file does not exist, it
     913             : /// is created.
     914             : ///
     915             : /// The caller is responsible for closing the file descriptor once they are
     916             : /// finished with it.
     917             : ///
     918             : /// @param Name The path of the file to open, relative or absolute.
     919             : /// @param ResultFD If the file could be opened successfully, its descriptor
     920             : ///                 is stored in this location. Otherwise, this is set to -1.
     921             : /// @param Flags Additional flags used to determine whether the file should be
     922             : ///              opened in, for example, read-write or in write-only mode.
     923             : /// @param Mode The access permissions of the file, represented in octal.
     924             : /// @returns errc::success if \a Name has been opened, otherwise a
     925             : ///          platform-specific error_code.
     926             : inline std::error_code
     927             : openFileForWrite(const Twine &Name, int &ResultFD,
     928             :                  CreationDisposition Disp = CD_CreateAlways,
     929             :                  OpenFlags Flags = OF_None, unsigned Mode = 0666) {
     930       10622 :   return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
     931             : }
     932             : 
     933             : /// @brief Opens the file with the given name in a write-only or read-write
     934             : /// mode, returning its open file descriptor. If the file does not exist, it
     935             : /// is created.
     936             : ///
     937             : /// The caller is responsible for closing the freeing the file once they are
     938             : /// finished with it.
     939             : ///
     940             : /// @param Name The path of the file to open, relative or absolute.
     941             : /// @param Flags Additional flags used to determine whether the file should be
     942             : ///              opened in, for example, read-write or in write-only mode.
     943             : /// @param Mode The access permissions of the file, represented in octal.
     944             : /// @returns a platform-specific file descriptor if \a Name has been opened,
     945             : ///          otherwise an error object.
     946             : inline Expected<file_t> openNativeFileForWrite(const Twine &Name,
     947             :                                                CreationDisposition Disp,
     948             :                                                OpenFlags Flags,
     949             :                                                unsigned Mode = 0666) {
     950             :   return openNativeFile(Name, Disp, FA_Write, Flags, Mode);
     951             : }
     952             : 
     953             : /// @brief Opens the file with the given name in a write-only or read-write
     954             : /// mode, returning its open file descriptor. If the file does not exist, it
     955             : /// is created.
     956             : ///
     957             : /// The caller is responsible for closing the file descriptor once they are
     958             : /// finished with it.
     959             : ///
     960             : /// @param Name The path of the file to open, relative or absolute.
     961             : /// @param ResultFD If the file could be opened successfully, its descriptor
     962             : ///                 is stored in this location. Otherwise, this is set to -1.
     963             : /// @param Flags Additional flags used to determine whether the file should be
     964             : ///              opened in, for example, read-write or in write-only mode.
     965             : /// @param Mode The access permissions of the file, represented in octal.
     966             : /// @returns errc::success if \a Name has been opened, otherwise a
     967             : ///          platform-specific error_code.
     968             : inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
     969             :                                             CreationDisposition Disp,
     970             :                                             OpenFlags Flags,
     971             :                                             unsigned Mode = 0666) {
     972       25878 :   return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode);
     973             : }
     974             : 
     975             : /// @brief Opens the file with the given name in a write-only or read-write
     976             : /// mode, returning its open file descriptor. If the file does not exist, it
     977             : /// is created.
     978             : ///
     979             : /// The caller is responsible for closing the freeing the file once they are
     980             : /// finished with it.
     981             : ///
     982             : /// @param Name The path of the file to open, relative or absolute.
     983             : /// @param Flags Additional flags used to determine whether the file should be
     984             : ///              opened in, for example, read-write or in write-only mode.
     985             : /// @param Mode The access permissions of the file, represented in octal.
     986             : /// @returns a platform-specific file descriptor if \a Name has been opened,
     987             : ///          otherwise an error object.
     988             : inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name,
     989             :                                                    CreationDisposition Disp,
     990             :                                                    OpenFlags Flags,
     991             :                                                    unsigned Mode = 0666) {
     992             :   return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode);
     993             : }
     994             : 
     995             : /// @brief Opens the file with the given name in a read-only mode, returning
     996             : /// its open file descriptor.
     997             : ///
     998             : /// The caller is responsible for closing the file descriptor once they are
     999             : /// finished with it.
    1000             : ///
    1001             : /// @param Name The path of the file to open, relative or absolute.
    1002             : /// @param ResultFD If the file could be opened successfully, its descriptor
    1003             : ///                 is stored in this location. Otherwise, this is set to -1.
    1004             : /// @param RealPath If nonnull, extra work is done to determine the real path
    1005             : ///                 of the opened file, and that path is stored in this
    1006             : ///                 location.
    1007             : /// @returns errc::success if \a Name has been opened, otherwise a
    1008             : ///          platform-specific error_code.
    1009             : std::error_code openFileForRead(const Twine &Name, int &ResultFD,
    1010             :                                 OpenFlags Flags = OF_None,
    1011             :                                 SmallVectorImpl<char> *RealPath = nullptr);
    1012             : 
    1013             : /// @brief Opens the file with the given name in a read-only mode, returning
    1014             : /// its open file descriptor.
    1015             : ///
    1016             : /// The caller is responsible for closing the freeing the file once they are
    1017             : /// finished with it.
    1018             : ///
    1019             : /// @param Name The path of the file to open, relative or absolute.
    1020             : /// @param RealPath If nonnull, extra work is done to determine the real path
    1021             : ///                 of the opened file, and that path is stored in this
    1022             : ///                 location.
    1023             : /// @returns a platform-specific file descriptor if \a Name has been opened,
    1024             : ///          otherwise an error object.
    1025             : Expected<file_t>
    1026             : openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None,
    1027             :                       SmallVectorImpl<char> *RealPath = nullptr);
    1028             : 
    1029             : /// @brief Close the file object.  This should be used instead of ::close for
    1030             : /// portability.
    1031             : ///
    1032             : /// @param F On input, this is the file to close.  On output, the file is
    1033             : /// set to kInvalidFile.
    1034             : void closeFile(file_t &F);
    1035             : 
    1036             : std::error_code getUniqueID(const Twine Path, UniqueID &Result);
    1037             : 
    1038             : /// Get disk space usage information.
    1039             : ///
    1040             : /// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
    1041             : /// Note: Windows reports results according to the quota allocated to the user.
    1042             : ///
    1043             : /// @param Path Input path.
    1044             : /// @returns a space_info structure filled with the capacity, free, and
    1045             : /// available space on the device \a Path is on. A platform specific error_code
    1046             : /// is returned on error.
    1047             : ErrorOr<space_info> disk_space(const Twine &Path);
    1048             : 
    1049             : /// This class represents a memory mapped file. It is based on
    1050             : /// boost::iostreams::mapped_file.
    1051             : class mapped_file_region {
    1052             : public:
    1053             :   enum mapmode {
    1054             :     readonly, ///< May only access map via const_data as read only.
    1055             :     readwrite, ///< May access map via data and modify it. Written to path.
    1056             :     priv ///< May modify via data, but changes are lost on destruction.
    1057             :   };
    1058             : 
    1059             : private:
    1060             :   /// Platform-specific mapping state.
    1061             :   size_t Size;
    1062             :   void *Mapping;
    1063             : #ifdef _WIN32
    1064             :   void *FileHandle;
    1065             : #endif
    1066             :   mapmode Mode;
    1067             : 
    1068             :   std::error_code init(int FD, uint64_t Offset, mapmode Mode);
    1069             : 
    1070             : public:
    1071             :   mapped_file_region() = delete;
    1072             :   mapped_file_region(mapped_file_region&) = delete;
    1073             :   mapped_file_region &operator =(mapped_file_region&) = delete;
    1074             : 
    1075             :   /// \param fd An open file descriptor to map. mapped_file_region takes
    1076             :   ///   ownership if closefd is true. It must have been opended in the correct
    1077             :   ///   mode.
    1078             :   mapped_file_region(int fd, mapmode mode, size_t length, uint64_t offset,
    1079             :                      std::error_code &ec);
    1080             : 
    1081             :   ~mapped_file_region();
    1082             : 
    1083             :   size_t size() const;
    1084             :   char *data() const;
    1085             : 
    1086             :   /// Get a const view of the data. Modifying this memory has undefined
    1087             :   /// behavior.
    1088             :   const char *const_data() const;
    1089             : 
    1090             :   /// \returns The minimum alignment offset must be.
    1091             :   static int alignment();
    1092             : };
    1093             : 
    1094             : /// Return the path to the main executable, given the value of argv[0] from
    1095             : /// program startup and the address of main itself. In extremis, this function
    1096             : /// may fail and return an empty path.
    1097             : std::string getMainExecutable(const char *argv0, void *MainExecAddr);
    1098             : 
    1099             : /// @}
    1100             : /// @name Iterators
    1101             : /// @{
    1102             : 
    1103             : /// directory_entry - A single entry in a directory.
    1104     4403561 : class directory_entry {
    1105             :   // FIXME: different platforms make different information available "for free"
    1106             :   // when traversing a directory. The design of this class wraps most of the
    1107             :   // information in basic_file_status, so on platforms where we can't populate
    1108             :   // that whole structure, callers end up paying for a stat().
    1109             :   // std::filesystem::directory_entry may be a better model.
    1110             :   std::string Path;
    1111             :   file_type Type;           // Most platforms can provide this.
    1112             :   bool FollowSymlinks;      // Affects the behavior of status().
    1113             :   basic_file_status Status; // If available.
    1114             : 
    1115             : public:
    1116             :   explicit directory_entry(const Twine &Path, bool FollowSymlinks = true,
    1117             :                            file_type Type = file_type::type_unknown,
    1118             :                            basic_file_status Status = basic_file_status())
    1119       41062 :       : Path(Path.str()), Type(Type), FollowSymlinks(FollowSymlinks),
    1120       41062 :         Status(Status) {}
    1121             : 
    1122             :   directory_entry() = default;
    1123             : 
    1124             :   void replace_filename(const Twine &Filename, file_type Type,
    1125             :                         basic_file_status Status = basic_file_status());
    1126             : 
    1127         137 :   const std::string &path() const { return Path; }
    1128             :   // Get basic information about entry file (a subset of fs::status()).
    1129             :   // On most platforms this is a stat() call.
    1130             :   // On windows the information was already retrieved from the directory.
    1131             :   ErrorOr<basic_file_status> status() const;
    1132             :   // Get the type of this file.
    1133             :   // On most platforms (Linux/Mac/Windows/BSD), this was already retrieved.
    1134             :   // On some platforms (e.g. Solaris) this is a stat() call.
    1135       46693 :   file_type type() const {
    1136       46693 :     if (Type != file_type::type_unknown)
    1137             :       return Type;
    1138           0 :     auto S = status();
    1139           0 :     return S ? S->type() : file_type::type_unknown;
    1140             :   }
    1141             : 
    1142     4370781 :   bool operator==(const directory_entry& RHS) const { return Path == RHS.Path; }
    1143             :   bool operator!=(const directory_entry& RHS) const { return !(*this == RHS); }
    1144             :   bool operator< (const directory_entry& RHS) const;
    1145             :   bool operator<=(const directory_entry& RHS) const;
    1146             :   bool operator> (const directory_entry& RHS) const;
    1147             :   bool operator>=(const directory_entry& RHS) const;
    1148             : };
    1149             : 
    1150             : namespace detail {
    1151             : 
    1152             :   struct DirIterState;
    1153             : 
    1154             :   std::error_code directory_iterator_construct(DirIterState &, StringRef, bool);
    1155             :   std::error_code directory_iterator_increment(DirIterState &);
    1156             :   std::error_code directory_iterator_destruct(DirIterState &);
    1157             : 
    1158             :   /// Keeps state for the directory_iterator.
    1159             :   struct DirIterState {
    1160     8642920 :     ~DirIterState() {
    1161     4321455 :       directory_iterator_destruct(*this);
    1162     4321465 :     }
    1163             : 
    1164             :     intptr_t IterationHandle = 0;
    1165             :     directory_entry CurrentEntry;
    1166             :   };
    1167             : 
    1168             : } // end namespace detail
    1169             : 
    1170             : /// directory_iterator - Iterates through the entries in path. There is no
    1171             : /// operator++ because we need an error_code. If it's really needed we can make
    1172             : /// it call report_fatal_error on error.
    1173        1408 : class directory_iterator {
    1174             :   std::shared_ptr<detail::DirIterState> State;
    1175             :   bool FollowSymlinks = true;
    1176             : 
    1177             : public:
    1178     4321364 :   explicit directory_iterator(const Twine &path, std::error_code &ec,
    1179             :                               bool follow_symlinks = true)
    1180     8642728 :       : FollowSymlinks(follow_symlinks) {
    1181     4321322 :     State = std::make_shared<detail::DirIterState>();
    1182             :     SmallString<128> path_storage;
    1183             :     ec = detail::directory_iterator_construct(
    1184     4321322 :         *State, path.toStringRef(path_storage), FollowSymlinks);
    1185     4321385 :   }
    1186             : 
    1187          55 :   explicit directory_iterator(const directory_entry &de, std::error_code &ec,
    1188             :                               bool follow_symlinks = true)
    1189         110 :       : FollowSymlinks(follow_symlinks) {
    1190          55 :     State = std::make_shared<detail::DirIterState>();
    1191             :     ec = detail::directory_iterator_construct(
    1192         110 :         *State, de.path(), FollowSymlinks);
    1193          55 :   }
    1194             : 
    1195             :   /// Construct end iterator.
    1196       46736 :   directory_iterator() = default;
    1197             : 
    1198             :   // No operator++ because we need error_code.
    1199             :   directory_iterator &increment(std::error_code &ec) {
    1200       49648 :     ec = directory_iterator_increment(*State);
    1201             :     return *this;
    1202             :   }
    1203             : 
    1204         153 :   const directory_entry &operator*() const { return State->CurrentEntry; }
    1205       46655 :   const directory_entry *operator->() const { return &State->CurrentEntry; }
    1206             : 
    1207     4370781 :   bool operator==(const directory_iterator &RHS) const {
    1208     4370781 :     if (State == RHS.State)
    1209             :       return true;
    1210     4370781 :     if (!RHS.State)
    1211     8741562 :       return State->CurrentEntry == directory_entry();
    1212           0 :     if (!State)
    1213           0 :       return RHS.State->CurrentEntry == directory_entry();
    1214           0 :     return State->CurrentEntry == RHS.State->CurrentEntry;
    1215             :   }
    1216             : 
    1217             :   bool operator!=(const directory_iterator &RHS) const {
    1218     4324053 :     return !(*this == RHS);
    1219             :   }
    1220             : };
    1221             : 
    1222             : namespace detail {
    1223             : 
    1224             :   /// Keeps state for the recursive_directory_iterator.
    1225          41 :   struct RecDirIterState {
    1226             :     std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
    1227             :     uint16_t Level = 0;
    1228             :     bool HasNoPushRequest = false;
    1229             :   };
    1230             : 
    1231             : } // end namespace detail
    1232             : 
    1233             : /// recursive_directory_iterator - Same as directory_iterator except for it
    1234             : /// recurses down into child directories.
    1235           1 : class recursive_directory_iterator {
    1236             :   std::shared_ptr<detail::RecDirIterState> State;
    1237             :   bool Follow;
    1238             : 
    1239             : public:
    1240             :   recursive_directory_iterator() = default;
    1241          41 :   explicit recursive_directory_iterator(const Twine &path, std::error_code &ec,
    1242             :                                         bool follow_symlinks = true)
    1243          41 :       : State(std::make_shared<detail::RecDirIterState>()),
    1244          41 :         Follow(follow_symlinks) {
    1245          82 :     State->Stack.push(directory_iterator(path, ec, Follow));
    1246          82 :     if (State->Stack.top() == directory_iterator())
    1247             :       State.reset();
    1248          41 :   }
    1249             : 
    1250             :   // No operator++ because we need error_code.
    1251         216 :   recursive_directory_iterator &increment(std::error_code &ec) {
    1252             :     const directory_iterator end_itr = {};
    1253             : 
    1254         216 :     if (State->HasNoPushRequest)
    1255           1 :       State->HasNoPushRequest = false;
    1256             :     else {
    1257         215 :       file_type type = State->Stack.top()->type();
    1258         215 :       if (type == file_type::symlink_file && Follow) {
    1259             :         // Resolve the symlink: is it a directory to recurse into?
    1260           6 :         ErrorOr<basic_file_status> status = State->Stack.top()->status();
    1261           6 :         if (status)
    1262           1 :           type = status->type();
    1263             :         // Otherwise broken symlink, and we'll continue.
    1264             :       }
    1265         215 :       if (type == file_type::directory_file) {
    1266         132 :         State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
    1267          44 :         if (State->Stack.top() != end_itr) {
    1268          35 :           ++State->Level;
    1269          35 :           return *this;
    1270             :         }
    1271             :         State->Stack.pop();
    1272             :       }
    1273             :     }
    1274             : 
    1275          75 :     while (!State->Stack.empty()
    1276         471 :            && State->Stack.top().increment(ec) == end_itr) {
    1277             :       State->Stack.pop();
    1278          75 :       --State->Level;
    1279             :     }
    1280             : 
    1281             :     // Check if we are done. If so, create an end iterator.
    1282         181 :     if (State->Stack.empty())
    1283             :       State.reset();
    1284             : 
    1285             :     return *this;
    1286             :   }
    1287             : 
    1288             :   const directory_entry &operator*() const { return *State->Stack.top(); }
    1289             :   const directory_entry *operator->() const { return &*State->Stack.top(); }
    1290             : 
    1291             :   // observers
    1292             :   /// Gets the current level. Starting path is at level 0.
    1293           3 :   int level() const { return State->Level; }
    1294             : 
    1295             :   /// Returns true if no_push has been called for this directory_entry.
    1296             :   bool no_push_request() const { return State->HasNoPushRequest; }
    1297             : 
    1298             :   // modifiers
    1299             :   /// Goes up one level if Level > 0.
    1300           1 :   void pop() {
    1301             :     assert(State && "Cannot pop an end iterator!");
    1302             :     assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
    1303             : 
    1304             :     const directory_iterator end_itr = {};
    1305             :     std::error_code ec;
    1306             :     do {
    1307           1 :       if (ec)
    1308           0 :         report_fatal_error("Error incrementing directory iterator.");
    1309             :       State->Stack.pop();
    1310           1 :       --State->Level;
    1311             :     } while (!State->Stack.empty()
    1312           2 :              && State->Stack.top().increment(ec) == end_itr);
    1313             : 
    1314             :     // Check if we are done. If so, create an end iterator.
    1315           1 :     if (State->Stack.empty())
    1316             :       State.reset();
    1317           1 :   }
    1318             : 
    1319             :   /// Does not go down into the current directory_entry.
    1320           1 :   void no_push() { State->HasNoPushRequest = true; }
    1321             : 
    1322             :   bool operator==(const recursive_directory_iterator &RHS) const {
    1323             :     return State == RHS.State;
    1324             :   }
    1325             : 
    1326             :   bool operator!=(const recursive_directory_iterator &RHS) const {
    1327             :     return !(*this == RHS);
    1328             :   }
    1329             : };
    1330             : 
    1331             : /// @}
    1332             : 
    1333             : } // end namespace fs
    1334             : } // end namespace sys
    1335             : } // end namespace llvm
    1336             : 
    1337             : #endif // LLVM_SUPPORT_FILESYSTEM_H

Generated by: LCOV version 1.13