Home | History | Annotate | Download | only in Support
      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   return static_cast<perms>(static_cast<unsigned short>(l) |
    115                             static_cast<unsigned short>(r));
    116 }
    117 inline perms operator&(perms l, perms r) {
    118   return static_cast<perms>(static_cast<unsigned short>(l) &
    119                             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   UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
    142 
    143   bool operator==(const UniqueID &Other) const {
    144     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   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   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   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   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   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   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   if (is_regular_file(Path, Result))
    569     return false;
    570   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 inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
    656   file_status Status;
    657   std::error_code EC = status(Path, Status);
    658   if (EC)
    659     return EC;
    660   Result = Status.getSize();
    661   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   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   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 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       : 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   const std::string &path() const { return Path; }
   1119   ErrorOr<basic_file_status> status() const;
   1120 
   1121   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     ~DirIterState() {
   1140       directory_iterator_destruct(*this);
   1141     }
   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 class directory_iterator {
   1153   std::shared_ptr<detail::DirIterState> State;
   1154   bool FollowSymlinks = true;
   1155 
   1156 public:
   1157   explicit directory_iterator(const Twine &path, std::error_code &ec,
   1158                               bool follow_symlinks = true)
   1159       : FollowSymlinks(follow_symlinks) {
   1160     State = std::make_shared<detail::DirIterState>();
   1161     SmallString<128> path_storage;
   1162     ec = detail::directory_iterator_construct(
   1163         *State, path.toStringRef(path_storage), FollowSymlinks);
   1164     update_error_code_for_current_entry(ec);
   1165   }
   1166 
   1167   explicit directory_iterator(const directory_entry &de, std::error_code &ec,
   1168                               bool follow_symlinks = true)
   1169       : FollowSymlinks(follow_symlinks) {
   1170     State = std::make_shared<detail::DirIterState>();
   1171     ec = detail::directory_iterator_construct(
   1172         *State, de.path(), FollowSymlinks);
   1173     update_error_code_for_current_entry(ec);
   1174   }
   1175 
   1176   /// Construct end iterator.
   1177   directory_iterator() = default;
   1178 
   1179   // No operator++ because we need error_code.
   1180   directory_iterator &increment(std::error_code &ec) {
   1181     ec = directory_iterator_increment(*State);
   1182     update_error_code_for_current_entry(ec);
   1183     return *this;
   1184   }
   1185 
   1186   const directory_entry &operator*() const { return State->CurrentEntry; }
   1187   const directory_entry *operator->() const { return &State->CurrentEntry; }
   1188 
   1189   bool operator==(const directory_iterator &RHS) const {
   1190     if (State == RHS.State)
   1191       return true;
   1192     if (!RHS.State)
   1193       return State->CurrentEntry == directory_entry();
   1194     if (!State)
   1195       return RHS.State->CurrentEntry == directory_entry();
   1196     return State->CurrentEntry == RHS.State->CurrentEntry;
   1197   }
   1198 
   1199   bool operator!=(const directory_iterator &RHS) const {
   1200     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   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     if (ec)
   1211       return;
   1212 
   1213     // Empty directory entry is used to mark the end of an interation, it's not
   1214     // an error.
   1215     if (State->CurrentEntry == directory_entry())
   1216       return;
   1217 
   1218     ErrorOr<basic_file_status> status = State->CurrentEntry.status();
   1219     if (!status)
   1220       ec = status.getError();
   1221   }
   1222 };
   1223 
   1224 namespace detail {
   1225 
   1226   /// Keeps state for the recursive_directory_iterator.
   1227   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 class recursive_directory_iterator {
   1238   std::shared_ptr<detail::RecDirIterState> State;
   1239   bool Follow;
   1240 
   1241 public:
   1242   recursive_directory_iterator() = default;
   1243   explicit recursive_directory_iterator(const Twine &path, std::error_code &ec,
   1244                                         bool follow_symlinks = true)
   1245       : State(std::make_shared<detail::RecDirIterState>()),
   1246         Follow(follow_symlinks) {
   1247     State->Stack.push(directory_iterator(path, ec, Follow));
   1248     if (State->Stack.top() == directory_iterator())
   1249       State.reset();
   1250   }
   1251 
   1252   // No operator++ because we need error_code.
   1253   recursive_directory_iterator &increment(std::error_code &ec) {
   1254     const directory_iterator end_itr = {};
   1255 
   1256     if (State->HasNoPushRequest)
   1257       State->HasNoPushRequest = false;
   1258     else {
   1259       ErrorOr<basic_file_status> status = State->Stack.top()->status();
   1260       if (status && is_directory(*status)) {
   1261         State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
   1262         if (State->Stack.top() != end_itr) {
   1263           ++State->Level;
   1264           return *this;
   1265         }
   1266         State->Stack.pop();
   1267       }
   1268     }
   1269 
   1270     while (!State->Stack.empty()
   1271            && State->Stack.top().increment(ec) == end_itr) {
   1272       State->Stack.pop();
   1273       --State->Level;
   1274     }
   1275 
   1276     // Check if we are done. If so, create an end iterator.
   1277     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   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   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       if (ec)
   1303         report_fatal_error("Error incrementing directory iterator.");
   1304       State->Stack.pop();
   1305       --State->Level;
   1306     } while (!State->Stack.empty()
   1307              && State->Stack.top().increment(ec) == end_itr);
   1308 
   1309     // Check if we are done. If so, create an end iterator.
   1310     if (State->Stack.empty())
   1311       State.reset();
   1312   }
   1313 
   1314   /// Does not go down into the current directory_entry.
   1315   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
   1335