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

Generated by: LCOV version 1.13