LCOV - code coverage report
Current view: top level - include/llvm/Support - FileSystem.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 83 89 93.3 %
Date: 2018-02-25 19:55:18 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13