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/IntrusiveRefCntPtr.h" 31#include "llvm/ADT/SmallString.h" 32#include "llvm/ADT/StringRef.h" 33#include "llvm/ADT/Twine.h" 34#include "llvm/Support/DataTypes.h" 35#include "llvm/Support/ErrorHandling.h" 36#include "llvm/Support/ErrorOr.h" 37#include "llvm/Support/TimeValue.h" 38#include <cassert> 39#include <cstdint> 40#include <ctime> 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 51namespace llvm { 52namespace sys { 53namespace fs { 54 55/// An enumeration for the file system's view of the type. 56enum 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. 70struct space_info { 71 uint64_t capacity; 72 uint64_t free; 73 uint64_t available; 74}; 75 76enum 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 perms_not_known = 0xFFFF 98}; 99 100// Helper functions so that you can use & and | to manipulate perms bits: 101inline perms operator|(perms l, perms r) { 102 return static_cast<perms>(static_cast<unsigned short>(l) | 103 static_cast<unsigned short>(r)); 104} 105inline perms operator&(perms l, perms r) { 106 return static_cast<perms>(static_cast<unsigned short>(l) & 107 static_cast<unsigned short>(r)); 108} 109inline perms &operator|=(perms &l, perms r) { 110 l = l | r; 111 return l; 112} 113inline perms &operator&=(perms &l, perms r) { 114 l = l & r; 115 return l; 116} 117inline perms operator~(perms x) { 118 return static_cast<perms>(~static_cast<unsigned short>(x)); 119} 120 121class UniqueID { 122 uint64_t Device; 123 uint64_t File; 124 125public: 126 UniqueID() = default; 127 UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} 128 bool operator==(const UniqueID &Other) const { 129 return Device == Other.Device && File == Other.File; 130 } 131 bool operator!=(const UniqueID &Other) const { return !(*this == Other); } 132 bool operator<(const UniqueID &Other) const { 133 return std::tie(Device, File) < std::tie(Other.Device, Other.File); 134 } 135 uint64_t getDevice() const { return Device; } 136 uint64_t getFile() const { return File; } 137}; 138 139/// file_status - Represents the result of a call to stat and friends. It has 140/// a platform-specific member to store the result. 141class file_status 142{ 143 #if defined(LLVM_ON_UNIX) 144 dev_t fs_st_dev; 145 ino_t fs_st_ino; 146 time_t fs_st_atime; 147 time_t fs_st_mtime; 148 uid_t fs_st_uid; 149 gid_t fs_st_gid; 150 off_t fs_st_size; 151 #elif defined (LLVM_ON_WIN32) 152 uint32_t LastAccessedTimeHigh; 153 uint32_t LastAccessedTimeLow; 154 uint32_t LastWriteTimeHigh; 155 uint32_t LastWriteTimeLow; 156 uint32_t VolumeSerialNumber; 157 uint32_t FileSizeHigh; 158 uint32_t FileSizeLow; 159 uint32_t FileIndexHigh; 160 uint32_t FileIndexLow; 161 #endif 162 friend bool equivalent(file_status A, file_status B); 163 file_type Type; 164 perms Perms; 165 166public: 167 #if defined(LLVM_ON_UNIX) 168 file_status() 169 : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0), 170 fs_st_uid(0), fs_st_gid(0), fs_st_size(0), 171 Type(file_type::status_error), Perms(perms_not_known) {} 172 173 file_status(file_type Type) 174 : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0), 175 fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), 176 Perms(perms_not_known) {} 177 178 file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t ATime, 179 time_t MTime, uid_t UID, gid_t GID, off_t Size) 180 : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_atime(ATime), fs_st_mtime(MTime), 181 fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type), 182 Perms(Perms) {} 183 #elif defined(LLVM_ON_WIN32) 184 file_status() 185 : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0), 186 LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0), 187 FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), 188 Type(file_type::status_error), Perms(perms_not_known) {} 189 190 file_status(file_type Type) 191 : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0), 192 LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0), 193 FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), Type(Type), 194 Perms(perms_not_known) {} 195 196 file_status(file_type Type, uint32_t LastAccessTimeHigh, 197 uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh, 198 uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, 199 uint32_t FileSizeHigh, uint32_t FileSizeLow, 200 uint32_t FileIndexHigh, uint32_t FileIndexLow) 201 : LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow), 202 LastWriteTimeHigh(LastWriteTimeHigh), 203 LastWriteTimeLow(LastWriteTimeLow), 204 VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), 205 FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), 206 FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} 207 #endif 208 209 // getters 210 file_type type() const { return Type; } 211 perms permissions() const { return Perms; } 212 TimeValue getLastAccessedTime() const; 213 TimeValue getLastModificationTime() const; 214 UniqueID getUniqueID() const; 215 216 #if defined(LLVM_ON_UNIX) 217 uint32_t getUser() const { return fs_st_uid; } 218 uint32_t getGroup() const { return fs_st_gid; } 219 uint64_t getSize() const { return fs_st_size; } 220 #elif defined (LLVM_ON_WIN32) 221 uint32_t getUser() const { 222 return 9999; // Not applicable to Windows, so... 223 } 224 uint32_t getGroup() const { 225 return 9999; // Not applicable to Windows, so... 226 } 227 uint64_t getSize() const { 228 return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; 229 } 230 #endif 231 232 // setters 233 void type(file_type v) { Type = v; } 234 void permissions(perms p) { Perms = p; } 235}; 236 237/// file_magic - An "enum class" enumeration of file types based on magic (the first 238/// N bytes of the file). 239struct file_magic { 240 enum Impl { 241 unknown = 0, ///< Unrecognized file 242 bitcode, ///< Bitcode file 243 archive, ///< ar style archive file 244 elf, ///< ELF Unknown type 245 elf_relocatable, ///< ELF Relocatable object file 246 elf_executable, ///< ELF Executable image 247 elf_shared_object, ///< ELF dynamically linked shared lib 248 elf_core, ///< ELF core image 249 macho_object, ///< Mach-O Object file 250 macho_executable, ///< Mach-O Executable 251 macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM 252 macho_core, ///< Mach-O Core File 253 macho_preload_executable, ///< Mach-O Preloaded Executable 254 macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib 255 macho_dynamic_linker, ///< The Mach-O dynamic linker 256 macho_bundle, ///< Mach-O Bundle file 257 macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub 258 macho_dsym_companion, ///< Mach-O dSYM companion file 259 macho_kext_bundle, ///< Mach-O kext bundle file 260 macho_universal_binary, ///< Mach-O universal binary 261 coff_object, ///< COFF object file 262 coff_import_library, ///< COFF import library 263 pecoff_executable, ///< PECOFF executable file 264 windows_resource ///< Windows compiled resource file (.rc) 265 }; 266 267 bool is_object() const { 268 return V != unknown; 269 } 270 271 file_magic() : V(unknown) {} 272 file_magic(Impl V) : V(V) {} 273 operator Impl() const { return V; } 274 275private: 276 Impl V; 277}; 278 279/// @} 280/// @name Physical Operators 281/// @{ 282 283/// @brief Make \a path an absolute path. 284/// 285/// Makes \a path absolute using the \a current_directory if it is not already. 286/// An empty \a path will result in the \a current_directory. 287/// 288/// /absolute/path => /absolute/path 289/// relative/../path => <current-directory>/relative/../path 290/// 291/// @param path A path that is modified to be an absolute path. 292/// @returns errc::success if \a path has been made absolute, otherwise a 293/// platform-specific error_code. 294std::error_code make_absolute(const Twine ¤t_directory, 295 SmallVectorImpl<char> &path); 296 297/// @brief Make \a path an absolute path. 298/// 299/// Makes \a path absolute using the current directory if it is not already. An 300/// empty \a path will result in the current directory. 301/// 302/// /absolute/path => /absolute/path 303/// relative/../path => <current-directory>/relative/../path 304/// 305/// @param path A path that is modified to be an absolute path. 306/// @returns errc::success if \a path has been made absolute, otherwise a 307/// platform-specific error_code. 308std::error_code make_absolute(SmallVectorImpl<char> &path); 309 310/// @brief Create all the non-existent directories in path. 311/// 312/// @param path Directories to create. 313/// @returns errc::success if is_directory(path), otherwise a platform 314/// specific error_code. If IgnoreExisting is false, also returns 315/// error if the directory already existed. 316std::error_code create_directories(const Twine &path, 317 bool IgnoreExisting = true, 318 perms Perms = owner_all | group_all); 319 320/// @brief Create the directory in path. 321/// 322/// @param path Directory to create. 323/// @returns errc::success if is_directory(path), otherwise a platform 324/// specific error_code. If IgnoreExisting is false, also returns 325/// error if the directory already existed. 326std::error_code create_directory(const Twine &path, bool IgnoreExisting = true, 327 perms Perms = owner_all | group_all); 328 329/// @brief Create a link from \a from to \a to. 330/// 331/// The link may be a soft or a hard link, depending on the platform. The caller 332/// may not assume which one. Currently on windows it creates a hard link since 333/// soft links require extra privileges. On unix, it creates a soft link since 334/// hard links don't work on SMB file systems. 335/// 336/// @param to The path to hard link to. 337/// @param from The path to hard link from. This is created. 338/// @returns errc::success if the link was created, otherwise a platform 339/// specific error_code. 340std::error_code create_link(const Twine &to, const Twine &from); 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. 347std::error_code current_path(SmallVectorImpl<char> &result); 348 349/// @brief Remove path. Equivalent to POSIX remove(). 350/// 351/// @param path Input path. 352/// @returns errc::success if path has been removed or didn't exist, otherwise a 353/// platform-specific error code. If IgnoreNonExisting is false, also 354/// returns error if the file didn't exist. 355std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); 356 357/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 358/// 359/// @param from The path to rename from. 360/// @param to The path to rename to. This is created. 361std::error_code rename(const Twine &from, const Twine &to); 362 363/// @brief Copy the contents of \a From to \a To. 364/// 365/// @param From The path to copy from. 366/// @param To The path to copy to. This is created. 367std::error_code copy_file(const Twine &From, const Twine &To); 368 369/// @brief Resize path to size. File is resized as if by POSIX truncate(). 370/// 371/// @param FD Input file descriptor. 372/// @param Size Size to resize to. 373/// @returns errc::success if \a path has been resized to \a size, otherwise a 374/// platform-specific error_code. 375std::error_code resize_file(int FD, uint64_t Size); 376 377/// @} 378/// @name Physical Observers 379/// @{ 380 381/// @brief Does file exist? 382/// 383/// @param status A file_status previously returned from stat. 384/// @returns True if the file represented by status exists, false if it does 385/// not. 386bool exists(file_status status); 387 388enum class AccessMode { Exist, Write, Execute }; 389 390/// @brief Can the file be accessed? 391/// 392/// @param Path Input path. 393/// @returns errc::success if the path can be accessed, otherwise a 394/// platform-specific error_code. 395std::error_code access(const Twine &Path, AccessMode Mode); 396 397/// @brief Does file exist? 398/// 399/// @param Path Input path. 400/// @returns True if it exists, false otherwise. 401inline bool exists(const Twine &Path) { 402 return !access(Path, AccessMode::Exist); 403} 404 405/// @brief Can we execute this file? 406/// 407/// @param Path Input path. 408/// @returns True if we can execute it, false otherwise. 409bool can_execute(const Twine &Path); 410 411/// @brief Can we write this file? 412/// 413/// @param Path Input path. 414/// @returns True if we can write to it, false otherwise. 415inline bool can_write(const Twine &Path) { 416 return !access(Path, AccessMode::Write); 417} 418 419/// @brief Do file_status's represent the same thing? 420/// 421/// @param A Input file_status. 422/// @param B Input file_status. 423/// 424/// assert(status_known(A) || status_known(B)); 425/// 426/// @returns True if A and B both represent the same file system entity, false 427/// otherwise. 428bool equivalent(file_status A, file_status B); 429 430/// @brief Do paths represent the same thing? 431/// 432/// assert(status_known(A) || status_known(B)); 433/// 434/// @param A Input path A. 435/// @param B Input path B. 436/// @param result Set to true if stat(A) and stat(B) have the same device and 437/// inode (or equivalent). 438/// @returns errc::success if result has been successfully set, otherwise a 439/// platform-specific error_code. 440std::error_code equivalent(const Twine &A, const Twine &B, bool &result); 441 442/// @brief Simpler version of equivalent for clients that don't need to 443/// differentiate between an error and false. 444inline bool equivalent(const Twine &A, const Twine &B) { 445 bool result; 446 return !equivalent(A, B, result) && result; 447} 448 449/// @brief Does status represent a directory? 450/// 451/// @param status A file_status previously returned from status. 452/// @returns status.type() == file_type::directory_file. 453bool is_directory(file_status status); 454 455/// @brief Is path a directory? 456/// 457/// @param path Input path. 458/// @param result Set to true if \a path is a directory, false if it is not. 459/// Undefined otherwise. 460/// @returns errc::success if result has been successfully set, otherwise a 461/// platform-specific error_code. 462std::error_code is_directory(const Twine &path, bool &result); 463 464/// @brief Simpler version of is_directory for clients that don't need to 465/// differentiate between an error and false. 466inline bool is_directory(const Twine &Path) { 467 bool Result; 468 return !is_directory(Path, Result) && Result; 469} 470 471/// @brief Does status represent a regular file? 472/// 473/// @param status A file_status previously returned from status. 474/// @returns status_known(status) && status.type() == file_type::regular_file. 475bool is_regular_file(file_status status); 476 477/// @brief Is path a regular file? 478/// 479/// @param path Input path. 480/// @param result Set to true if \a path is a regular file, false if it is not. 481/// Undefined otherwise. 482/// @returns errc::success if result has been successfully set, otherwise a 483/// platform-specific error_code. 484std::error_code is_regular_file(const Twine &path, bool &result); 485 486/// @brief Simpler version of is_regular_file for clients that don't need to 487/// differentiate between an error and false. 488inline bool is_regular_file(const Twine &Path) { 489 bool Result; 490 if (is_regular_file(Path, Result)) 491 return false; 492 return Result; 493} 494 495/// @brief Does this status represent something that exists but is not a 496/// directory, regular file, or symlink? 497/// 498/// @param status A file_status previously returned from status. 499/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) 500bool is_other(file_status status); 501 502/// @brief Is path something that exists but is not a directory, 503/// regular file, or symlink? 504/// 505/// @param path Input path. 506/// @param result Set to true if \a path exists, but is not a directory, regular 507/// file, or a symlink, false if it does not. Undefined otherwise. 508/// @returns errc::success if result has been successfully set, otherwise a 509/// platform-specific error_code. 510std::error_code is_other(const Twine &path, bool &result); 511 512/// @brief Get file status as if by POSIX stat(). 513/// 514/// @param path Input path. 515/// @param result Set to the file status. 516/// @returns errc::success if result has been successfully set, otherwise a 517/// platform-specific error_code. 518std::error_code status(const Twine &path, file_status &result); 519 520/// @brief A version for when a file descriptor is already available. 521std::error_code status(int FD, file_status &Result); 522 523/// @brief Get file size. 524/// 525/// @param Path Input path. 526/// @param Result Set to the size of the file in \a Path. 527/// @returns errc::success if result has been successfully set, otherwise a 528/// platform-specific error_code. 529inline std::error_code file_size(const Twine &Path, uint64_t &Result) { 530 file_status Status; 531 std::error_code EC = status(Path, Status); 532 if (EC) 533 return EC; 534 Result = Status.getSize(); 535 return std::error_code(); 536} 537 538/// @brief Set the file modification and access time. 539/// 540/// @returns errc::success if the file times were successfully set, otherwise a 541/// platform-specific error_code or errc::function_not_supported on 542/// platforms where the functionality isn't available. 543std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); 544 545/// @brief Is status available? 546/// 547/// @param s Input file status. 548/// @returns True if status() != status_error. 549bool status_known(file_status s); 550 551/// @brief Is status available? 552/// 553/// @param path Input path. 554/// @param result Set to true if status() != status_error. 555/// @returns errc::success if result has been successfully set, otherwise a 556/// platform-specific error_code. 557std::error_code status_known(const Twine &path, bool &result); 558 559/// @brief Create a uniquely named file. 560/// 561/// Generates a unique path suitable for a temporary file and then opens it as a 562/// file. The name is based on \a model with '%' replaced by a random char in 563/// [0-9a-f]. If \a model is not an absolute path, the temporary file will be 564/// created in the current directory. 565/// 566/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 567/// 568/// This is an atomic operation. Either the file is created and opened, or the 569/// file system is left untouched. 570/// 571/// The intended use is for files that are to be kept, possibly after 572/// renaming them. For example, when running 'clang -c foo.o', the file can 573/// be first created as foo-abc123.o and then renamed. 574/// 575/// @param Model Name to base unique path off of. 576/// @param ResultFD Set to the opened file's file descriptor. 577/// @param ResultPath Set to the opened file's absolute path. 578/// @returns errc::success if Result{FD,Path} have been successfully set, 579/// otherwise a platform-specific error_code. 580std::error_code createUniqueFile(const Twine &Model, int &ResultFD, 581 SmallVectorImpl<char> &ResultPath, 582 unsigned Mode = all_read | all_write); 583 584/// @brief Simpler version for clients that don't want an open file. 585std::error_code createUniqueFile(const Twine &Model, 586 SmallVectorImpl<char> &ResultPath); 587 588/// @brief Create a file in the system temporary directory. 589/// 590/// The filename is of the form prefix-random_chars.suffix. Since the directory 591/// is not know to the caller, Prefix and Suffix cannot have path separators. 592/// The files are created with mode 0600. 593/// 594/// This should be used for things like a temporary .s that is removed after 595/// running the assembler. 596std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 597 int &ResultFD, 598 SmallVectorImpl<char> &ResultPath); 599 600/// @brief Simpler version for clients that don't want an open file. 601std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 602 SmallVectorImpl<char> &ResultPath); 603 604std::error_code createUniqueDirectory(const Twine &Prefix, 605 SmallVectorImpl<char> &ResultPath); 606 607/// @brief Fetch a path to an open file, as specified by a file descriptor 608/// 609/// @param FD File descriptor to a currently open file 610/// @param ResultPath The buffer into which to write the path 611std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath); 612 613enum OpenFlags : unsigned { 614 F_None = 0, 615 616 /// F_Excl - When opening a file, this flag makes raw_fd_ostream 617 /// report an error if the file already exists. 618 F_Excl = 1, 619 620 /// F_Append - When opening a file, if it already exists append to the 621 /// existing file instead of returning an error. This may not be specified 622 /// with F_Excl. 623 F_Append = 2, 624 625 /// The file should be opened in text mode on platforms that make this 626 /// distinction. 627 F_Text = 4, 628 629 /// Open the file for read and write. 630 F_RW = 8 631}; 632 633inline OpenFlags operator|(OpenFlags A, OpenFlags B) { 634 return OpenFlags(unsigned(A) | unsigned(B)); 635} 636 637inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { 638 A = A | B; 639 return A; 640} 641 642std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 643 OpenFlags Flags, unsigned Mode = 0666); 644 645std::error_code openFileForRead(const Twine &Name, int &ResultFD, 646 SmallVectorImpl<char> *RealPath = nullptr); 647 648/// @brief Identify the type of a binary file based on how magical it is. 649file_magic identify_magic(StringRef magic); 650 651/// @brief Get and identify \a path's type based on its content. 652/// 653/// @param path Input path. 654/// @param result Set to the type of file, or file_magic::unknown. 655/// @returns errc::success if result has been successfully set, otherwise a 656/// platform-specific error_code. 657std::error_code identify_magic(const Twine &path, file_magic &result); 658 659std::error_code getUniqueID(const Twine Path, UniqueID &Result); 660 661/// @brief Get disk space usage information. 662/// 663/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug. 664/// Note: Windows reports results according to the quota allocated to the user. 665/// 666/// @param Path Input path. 667/// @returns a space_info structure filled with the capacity, free, and 668/// available space on the device \a Path is on. A platform specific error_code 669/// is returned on error. 670ErrorOr<space_info> disk_space(const Twine &Path); 671 672/// This class represents a memory mapped file. It is based on 673/// boost::iostreams::mapped_file. 674class mapped_file_region { 675 mapped_file_region() = delete; 676 mapped_file_region(mapped_file_region&) = delete; 677 mapped_file_region &operator =(mapped_file_region&) = delete; 678 679public: 680 enum mapmode { 681 readonly, ///< May only access map via const_data as read only. 682 readwrite, ///< May access map via data and modify it. Written to path. 683 priv ///< May modify via data, but changes are lost on destruction. 684 }; 685 686private: 687 /// Platform-specific mapping state. 688 uint64_t Size; 689 void *Mapping; 690 691 std::error_code init(int FD, uint64_t Offset, mapmode Mode); 692 693public: 694 /// \param fd An open file descriptor to map. mapped_file_region takes 695 /// ownership if closefd is true. It must have been opended in the correct 696 /// mode. 697 mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset, 698 std::error_code &ec); 699 700 ~mapped_file_region(); 701 702 uint64_t size() const; 703 char *data() const; 704 705 /// Get a const view of the data. Modifying this memory has undefined 706 /// behavior. 707 const char *const_data() const; 708 709 /// \returns The minimum alignment offset must be. 710 static int alignment(); 711}; 712 713/// Return the path to the main executable, given the value of argv[0] from 714/// program startup and the address of main itself. In extremis, this function 715/// may fail and return an empty path. 716std::string getMainExecutable(const char *argv0, void *MainExecAddr); 717 718/// @} 719/// @name Iterators 720/// @{ 721 722/// directory_entry - A single entry in a directory. Caches the status either 723/// from the result of the iteration syscall, or the first time status is 724/// called. 725class directory_entry { 726 std::string Path; 727 mutable file_status Status; 728 729public: 730 explicit directory_entry(const Twine &path, file_status st = file_status()) 731 : Path(path.str()) 732 , Status(st) {} 733 734 directory_entry() {} 735 736 void assign(const Twine &path, file_status st = file_status()) { 737 Path = path.str(); 738 Status = st; 739 } 740 741 void replace_filename(const Twine &filename, file_status st = file_status()); 742 743 const std::string &path() const { return Path; } 744 std::error_code status(file_status &result) const; 745 746 bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 747 bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 748 bool operator< (const directory_entry& rhs) const; 749 bool operator<=(const directory_entry& rhs) const; 750 bool operator> (const directory_entry& rhs) const; 751 bool operator>=(const directory_entry& rhs) const; 752}; 753 754namespace detail { 755 struct DirIterState; 756 757 std::error_code directory_iterator_construct(DirIterState &, StringRef); 758 std::error_code directory_iterator_increment(DirIterState &); 759 std::error_code directory_iterator_destruct(DirIterState &); 760 761 /// DirIterState - Keeps state for the directory_iterator. It is reference 762 /// counted in order to preserve InputIterator semantics on copy. 763 struct DirIterState : public RefCountedBase<DirIterState> { 764 DirIterState() 765 : IterationHandle(0) {} 766 767 ~DirIterState() { 768 directory_iterator_destruct(*this); 769 } 770 771 intptr_t IterationHandle; 772 directory_entry CurrentEntry; 773 }; 774} // end namespace detail 775 776/// directory_iterator - Iterates through the entries in path. There is no 777/// operator++ because we need an error_code. If it's really needed we can make 778/// it call report_fatal_error on error. 779class directory_iterator { 780 IntrusiveRefCntPtr<detail::DirIterState> State; 781 782public: 783 explicit directory_iterator(const Twine &path, std::error_code &ec) { 784 State = new detail::DirIterState; 785 SmallString<128> path_storage; 786 ec = detail::directory_iterator_construct(*State, 787 path.toStringRef(path_storage)); 788 } 789 790 explicit directory_iterator(const directory_entry &de, std::error_code &ec) { 791 State = new detail::DirIterState; 792 ec = detail::directory_iterator_construct(*State, de.path()); 793 } 794 795 /// Construct end iterator. 796 directory_iterator() : State(nullptr) {} 797 798 // No operator++ because we need error_code. 799 directory_iterator &increment(std::error_code &ec) { 800 ec = directory_iterator_increment(*State); 801 return *this; 802 } 803 804 const directory_entry &operator*() const { return State->CurrentEntry; } 805 const directory_entry *operator->() const { return &State->CurrentEntry; } 806 807 bool operator==(const directory_iterator &RHS) const { 808 if (State == RHS.State) 809 return true; 810 if (!RHS.State) 811 return State->CurrentEntry == directory_entry(); 812 if (!State) 813 return RHS.State->CurrentEntry == directory_entry(); 814 return State->CurrentEntry == RHS.State->CurrentEntry; 815 } 816 817 bool operator!=(const directory_iterator &RHS) const { 818 return !(*this == RHS); 819 } 820 // Other members as required by 821 // C++ Std, 24.1.1 Input iterators [input.iterators] 822}; 823 824namespace detail { 825 /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is 826 /// reference counted in order to preserve InputIterator semantics on copy. 827 struct RecDirIterState : public RefCountedBase<RecDirIterState> { 828 RecDirIterState() 829 : Level(0) 830 , HasNoPushRequest(false) {} 831 832 std::stack<directory_iterator, std::vector<directory_iterator> > Stack; 833 uint16_t Level; 834 bool HasNoPushRequest; 835 }; 836} // end namespace detail 837 838/// recursive_directory_iterator - Same as directory_iterator except for it 839/// recurses down into child directories. 840class recursive_directory_iterator { 841 IntrusiveRefCntPtr<detail::RecDirIterState> State; 842 843public: 844 recursive_directory_iterator() {} 845 explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) 846 : State(new detail::RecDirIterState) { 847 State->Stack.push(directory_iterator(path, ec)); 848 if (State->Stack.top() == directory_iterator()) 849 State.reset(); 850 } 851 // No operator++ because we need error_code. 852 recursive_directory_iterator &increment(std::error_code &ec) { 853 const directory_iterator end_itr; 854 855 if (State->HasNoPushRequest) 856 State->HasNoPushRequest = false; 857 else { 858 file_status st; 859 if ((ec = State->Stack.top()->status(st))) return *this; 860 if (is_directory(st)) { 861 State->Stack.push(directory_iterator(*State->Stack.top(), ec)); 862 if (ec) return *this; 863 if (State->Stack.top() != end_itr) { 864 ++State->Level; 865 return *this; 866 } 867 State->Stack.pop(); 868 } 869 } 870 871 while (!State->Stack.empty() 872 && State->Stack.top().increment(ec) == end_itr) { 873 State->Stack.pop(); 874 --State->Level; 875 } 876 877 // Check if we are done. If so, create an end iterator. 878 if (State->Stack.empty()) 879 State.reset(); 880 881 return *this; 882 } 883 884 const directory_entry &operator*() const { return *State->Stack.top(); } 885 const directory_entry *operator->() const { return &*State->Stack.top(); } 886 887 // observers 888 /// Gets the current level. Starting path is at level 0. 889 int level() const { return State->Level; } 890 891 /// Returns true if no_push has been called for this directory_entry. 892 bool no_push_request() const { return State->HasNoPushRequest; } 893 894 // modifiers 895 /// Goes up one level if Level > 0. 896 void pop() { 897 assert(State && "Cannot pop an end iterator!"); 898 assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 899 900 const directory_iterator end_itr; 901 std::error_code ec; 902 do { 903 if (ec) 904 report_fatal_error("Error incrementing directory iterator."); 905 State->Stack.pop(); 906 --State->Level; 907 } while (!State->Stack.empty() 908 && State->Stack.top().increment(ec) == end_itr); 909 910 // Check if we are done. If so, create an end iterator. 911 if (State->Stack.empty()) 912 State.reset(); 913 } 914 915 /// Does not go down into the current directory_entry. 916 void no_push() { State->HasNoPushRequest = true; } 917 918 bool operator==(const recursive_directory_iterator &RHS) const { 919 return State == RHS.State; 920 } 921 922 bool operator!=(const recursive_directory_iterator &RHS) const { 923 return !(*this == RHS); 924 } 925 // Other members as required by 926 // C++ Std, 24.1.1 Input iterators [input.iterators] 927}; 928 929/// @} 930 931} // end namespace fs 932} // end namespace sys 933} // end namespace llvm 934 935#endif // LLVM_SUPPORT_FILESYSTEM_H 936