1 //===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the llvm::sys::fs namespace. It is designed after 10 // TR2/boost filesystem (v3), but modified to remove exception handling and the 11 // path class. 12 // 13 // All functions return an error_code and their actual work via the last out 14 // argument. The out argument is defined if and only if errc::success is 15 // returned. A function may return any error code in the generic or system 16 // category. However, they shall be equivalent to any error conditions listed 17 // in each functions respective documentation if the condition applies. [ note: 18 // this does not guarantee that error_code will be in the set of explicitly 19 // listed codes, but it does guarantee that if any of the explicitly listed 20 // errors occur, the correct error_code will be used ]. All functions may 21 // return errc::not_enough_memory if there is not enough memory to complete the 22 // operation. 23 // 24 //===----------------------------------------------------------------------===// 25 26 #ifndef LLVM_SUPPORT_FILESYSTEM_H 27 #define LLVM_SUPPORT_FILESYSTEM_H 28 29 #include "llvm/ADT/SmallString.h" 30 #include "llvm/ADT/StringRef.h" 31 #include "llvm/ADT/Twine.h" 32 #include "llvm/Config/llvm-config.h" 33 #include "llvm/Support/Chrono.h" 34 #include "llvm/Support/Error.h" 35 #include "llvm/Support/ErrorHandling.h" 36 #include "llvm/Support/ErrorOr.h" 37 #include "llvm/Support/MD5.h" 38 #include <cassert> 39 #include <cstdint> 40 #include <ctime> 41 #include <memory> 42 #include <stack> 43 #include <string> 44 #include <system_error> 45 #include <tuple> 46 #include <vector> 47 48 #ifdef HAVE_SYS_STAT_H 49 #include <sys/stat.h> 50 #endif 51 52 namespace llvm { 53 namespace sys { 54 namespace fs { 55 56 #if defined(_WIN32) 57 // A Win32 HANDLE is a typedef of void* 58 using file_t = void *; 59 #else 60 using file_t = int; 61 #endif 62 63 extern const file_t kInvalidFile; 64 65 /// An enumeration for the file system's view of the type. 66 enum class file_type { 67 status_error, 68 file_not_found, 69 regular_file, 70 directory_file, 71 symlink_file, 72 block_file, 73 character_file, 74 fifo_file, 75 socket_file, 76 type_unknown 77 }; 78 79 /// space_info - Self explanatory. 80 struct space_info { 81 uint64_t capacity; 82 uint64_t free; 83 uint64_t available; 84 }; 85 86 enum perms { 87 no_perms = 0, 88 owner_read = 0400, 89 owner_write = 0200, 90 owner_exe = 0100, 91 owner_all = owner_read | owner_write | owner_exe, 92 group_read = 040, 93 group_write = 020, 94 group_exe = 010, 95 group_all = group_read | group_write | group_exe, 96 others_read = 04, 97 others_write = 02, 98 others_exe = 01, 99 others_all = others_read | others_write | others_exe, 100 all_read = owner_read | group_read | others_read, 101 all_write = owner_write | group_write | others_write, 102 all_exe = owner_exe | group_exe | others_exe, 103 all_all = owner_all | group_all | others_all, 104 set_uid_on_exe = 04000, 105 set_gid_on_exe = 02000, 106 sticky_bit = 01000, 107 all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit, 108 perms_not_known = 0xFFFF 109 }; 110 111 // Helper functions so that you can use & and | to manipulate perms bits: 112 inline perms operator|(perms l, perms r) { 113 return static_cast<perms>(static_cast<unsigned short>(l) | 114 static_cast<unsigned short>(r)); 115 } 116 inline perms operator&(perms l, perms r) { 117 return static_cast<perms>(static_cast<unsigned short>(l) & 118 static_cast<unsigned short>(r)); 119 } 120 inline perms &operator|=(perms &l, perms r) { 121 l = l | r; 122 return l; 123 } 124 inline perms &operator&=(perms &l, perms r) { 125 l = l & r; 126 return l; 127 } 128 inline perms operator~(perms x) { 129 // Avoid UB by explicitly truncating the (unsigned) ~ result. 130 return static_cast<perms>( 131 static_cast<unsigned short>(~static_cast<unsigned short>(x))); 132 } 133 134 class UniqueID { 135 uint64_t Device; 136 uint64_t File; 137 138 public: 139 UniqueID() = default; 140 UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} 141 142 bool operator==(const UniqueID &Other) const { 143 return Device == Other.Device && File == Other.File; 144 } 145 bool operator!=(const UniqueID &Other) const { return !(*this == Other); } 146 bool operator<(const UniqueID &Other) const { 147 return std::tie(Device, File) < std::tie(Other.Device, Other.File); 148 } 149 150 uint64_t getDevice() const { return Device; } 151 uint64_t getFile() const { return File; } 152 }; 153 154 /// Represents the result of a call to directory_iterator::status(). This is a 155 /// subset of the information returned by a regular sys::fs::status() call, and 156 /// represents the information provided by Windows FileFirstFile/FindNextFile. 157 class basic_file_status { 158 protected: 159 #if defined(LLVM_ON_UNIX) 160 time_t fs_st_atime = 0; 161 time_t fs_st_mtime = 0; 162 uint32_t fs_st_atime_nsec = 0; 163 uint32_t fs_st_mtime_nsec = 0; 164 uid_t fs_st_uid = 0; 165 gid_t fs_st_gid = 0; 166 off_t fs_st_size = 0; 167 #elif defined (_WIN32) 168 uint32_t LastAccessedTimeHigh = 0; 169 uint32_t LastAccessedTimeLow = 0; 170 uint32_t LastWriteTimeHigh = 0; 171 uint32_t LastWriteTimeLow = 0; 172 uint32_t FileSizeHigh = 0; 173 uint32_t FileSizeLow = 0; 174 #endif 175 file_type Type = file_type::status_error; 176 perms Perms = perms_not_known; 177 178 public: 179 basic_file_status() = default; 180 181 explicit basic_file_status(file_type Type) : Type(Type) {} 182 183 #if defined(LLVM_ON_UNIX) 184 basic_file_status(file_type Type, perms Perms, time_t ATime, 185 uint32_t ATimeNSec, time_t MTime, uint32_t MTimeNSec, 186 uid_t UID, gid_t GID, off_t Size) 187 : fs_st_atime(ATime), fs_st_mtime(MTime), 188 fs_st_atime_nsec(ATimeNSec), fs_st_mtime_nsec(MTimeNSec), 189 fs_st_uid(UID), fs_st_gid(GID), 190 fs_st_size(Size), Type(Type), Perms(Perms) {} 191 #elif defined(_WIN32) 192 basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh, 193 uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh, 194 uint32_t LastWriteTimeLow, uint32_t FileSizeHigh, 195 uint32_t FileSizeLow) 196 : LastAccessedTimeHigh(LastAccessTimeHigh), 197 LastAccessedTimeLow(LastAccessTimeLow), 198 LastWriteTimeHigh(LastWriteTimeHigh), 199 LastWriteTimeLow(LastWriteTimeLow), FileSizeHigh(FileSizeHigh), 200 FileSizeLow(FileSizeLow), Type(Type), Perms(Perms) {} 201 #endif 202 203 // getters 204 file_type type() const { return Type; } 205 perms permissions() const { return Perms; } 206 207 /// The file access time as reported from the underlying file system. 208 /// 209 /// Also see comments on \c getLastModificationTime() related to the precision 210 /// of the returned value. 211 TimePoint<> getLastAccessedTime() const; 212 213 /// The file modification time as reported from the underlying file system. 214 /// 215 /// The returned value allows for nanosecond precision but the actual 216 /// resolution is an implementation detail of the underlying file system. 217 /// There is no guarantee for what kind of resolution you can expect, the 218 /// resolution can differ across platforms and even across mountpoints on the 219 /// same machine. 220 TimePoint<> getLastModificationTime() const; 221 222 #if defined(LLVM_ON_UNIX) 223 uint32_t getUser() const { return fs_st_uid; } 224 uint32_t getGroup() const { return fs_st_gid; } 225 uint64_t getSize() const { return fs_st_size; } 226 #elif defined (_WIN32) 227 uint32_t getUser() const { 228 return 9999; // Not applicable to Windows, so... 229 } 230 231 uint32_t getGroup() const { 232 return 9999; // Not applicable to Windows, so... 233 } 234 235 uint64_t getSize() const { 236 return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; 237 } 238 #endif 239 240 // setters 241 void type(file_type v) { Type = v; } 242 void permissions(perms p) { Perms = p; } 243 }; 244 245 /// Represents the result of a call to sys::fs::status(). 246 class file_status : public basic_file_status { 247 friend bool equivalent(file_status A, file_status B); 248 249 #if defined(LLVM_ON_UNIX) 250 dev_t fs_st_dev = 0; 251 nlink_t fs_st_nlinks = 0; 252 ino_t fs_st_ino = 0; 253 #elif defined (_WIN32) 254 uint32_t NumLinks = 0; 255 uint32_t VolumeSerialNumber = 0; 256 uint32_t FileIndexHigh = 0; 257 uint32_t FileIndexLow = 0; 258 #endif 259 260 public: 261 file_status() = default; 262 263 explicit file_status(file_type Type) : basic_file_status(Type) {} 264 265 #if defined(LLVM_ON_UNIX) 266 file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino, 267 time_t ATime, uint32_t ATimeNSec, 268 time_t MTime, uint32_t MTimeNSec, 269 uid_t UID, gid_t GID, off_t Size) 270 : basic_file_status(Type, Perms, ATime, ATimeNSec, MTime, MTimeNSec, 271 UID, GID, Size), 272 fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {} 273 #elif defined(_WIN32) 274 file_status(file_type Type, perms Perms, uint32_t LinkCount, 275 uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow, 276 uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow, 277 uint32_t VolumeSerialNumber, uint32_t FileSizeHigh, 278 uint32_t FileSizeLow, uint32_t FileIndexHigh, 279 uint32_t FileIndexLow) 280 : basic_file_status(Type, Perms, LastAccessTimeHigh, LastAccessTimeLow, 281 LastWriteTimeHigh, LastWriteTimeLow, FileSizeHigh, 282 FileSizeLow), 283 NumLinks(LinkCount), VolumeSerialNumber(VolumeSerialNumber), 284 FileIndexHigh(FileIndexHigh), FileIndexLow(FileIndexLow) {} 285 #endif 286 287 UniqueID getUniqueID() const; 288 uint32_t getLinkCount() const; 289 }; 290 291 /// @} 292 /// @name Physical Operators 293 /// @{ 294 295 /// Make \a path an absolute path. 296 /// 297 /// Makes \a path absolute using the \a current_directory if it is not already. 298 /// An empty \a path will result in the \a current_directory. 299 /// 300 /// /absolute/path => /absolute/path 301 /// relative/../path => <current-directory>/relative/../path 302 /// 303 /// @param path A path that is modified to be an absolute path. 304 void make_absolute(const Twine ¤t_directory, SmallVectorImpl<char> &path); 305 306 /// Make \a path an absolute path. 307 /// 308 /// Makes \a path absolute using the current directory if it is not already. An 309 /// empty \a path will result in the current directory. 310 /// 311 /// /absolute/path => /absolute/path 312 /// relative/../path => <current-directory>/relative/../path 313 /// 314 /// @param path A path that is modified to be an absolute path. 315 /// @returns errc::success if \a path has been made absolute, otherwise a 316 /// platform-specific error_code. 317 std::error_code make_absolute(SmallVectorImpl<char> &path); 318 319 /// Create all the non-existent directories in path. 320 /// 321 /// @param path Directories to create. 322 /// @returns errc::success if is_directory(path), otherwise a platform 323 /// specific error_code. If IgnoreExisting is false, also returns 324 /// error if the directory already existed. 325 std::error_code create_directories(const Twine &path, 326 bool IgnoreExisting = true, 327 perms Perms = owner_all | group_all); 328 329 /// Create the directory in path. 330 /// 331 /// @param path Directory to create. 332 /// @returns errc::success if is_directory(path), otherwise a platform 333 /// specific error_code. If IgnoreExisting is false, also returns 334 /// error if the directory already existed. 335 std::error_code create_directory(const Twine &path, bool IgnoreExisting = true, 336 perms Perms = owner_all | group_all); 337 338 /// Create a link from \a from to \a to. 339 /// 340 /// The link may be a soft or a hard link, depending on the platform. The caller 341 /// may not assume which one. Currently on windows it creates a hard link since 342 /// soft links require extra privileges. On unix, it creates a soft link since 343 /// hard links don't work on SMB file systems. 344 /// 345 /// @param to The path to hard link to. 346 /// @param from The path to hard link from. This is created. 347 /// @returns errc::success if the link was created, otherwise a platform 348 /// specific error_code. 349 std::error_code create_link(const Twine &to, const Twine &from); 350 351 /// Create a hard link from \a from to \a to, or return an error. 352 /// 353 /// @param to The path to hard link to. 354 /// @param from The path to hard link from. This is created. 355 /// @returns errc::success if the link was created, otherwise a platform 356 /// specific error_code. 357 std::error_code create_hard_link(const Twine &to, const Twine &from); 358 359 /// Collapse all . and .. patterns, resolve all symlinks, and optionally 360 /// expand ~ expressions to the user's home directory. 361 /// 362 /// @param path The path to resolve. 363 /// @param output The location to store the resolved path. 364 /// @param expand_tilde If true, resolves ~ expressions to the user's home 365 /// directory. 366 std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output, 367 bool expand_tilde = false); 368 369 /// Expands ~ expressions to the user's home directory. On Unix ~user 370 /// directories are resolved as well. 371 /// 372 /// @param path The path to resolve. 373 void expand_tilde(const Twine &path, SmallVectorImpl<char> &output); 374 375 /// Get the current path. 376 /// 377 /// @param result Holds the current path on return. 378 /// @returns errc::success if the current path has been stored in result, 379 /// otherwise a platform-specific error_code. 380 std::error_code current_path(SmallVectorImpl<char> &result); 381 382 /// Set the current path. 383 /// 384 /// @param path The path to set. 385 /// @returns errc::success if the current path was successfully set, 386 /// otherwise a platform-specific error_code. 387 std::error_code set_current_path(const Twine &path); 388 389 /// Remove path. Equivalent to POSIX remove(). 390 /// 391 /// @param path Input path. 392 /// @returns errc::success if path has been removed or didn't exist, otherwise a 393 /// platform-specific error code. If IgnoreNonExisting is false, also 394 /// returns error if the file didn't exist. 395 std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); 396 397 /// Recursively delete a directory. 398 /// 399 /// @param path Input path. 400 /// @returns errc::success if path has been removed or didn't exist, otherwise a 401 /// platform-specific error code. 402 std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true); 403 404 /// Rename \a from to \a to. 405 /// 406 /// Files are renamed as if by POSIX rename(), except that on Windows there may 407 /// be a short interval of time during which the destination file does not 408 /// exist. 409 /// 410 /// @param from The path to rename from. 411 /// @param to The path to rename to. This is created. 412 std::error_code rename(const Twine &from, const Twine &to); 413 414 /// Copy the contents of \a From to \a To. 415 /// 416 /// @param From The path to copy from. 417 /// @param To The path to copy to. This is created. 418 std::error_code copy_file(const Twine &From, const Twine &To); 419 420 /// Copy the contents of \a From to \a To. 421 /// 422 /// @param From The path to copy from. 423 /// @param ToFD The open file descriptor of the destination file. 424 std::error_code copy_file(const Twine &From, int ToFD); 425 426 /// Resize path to size. File is resized as if by POSIX truncate(). 427 /// 428 /// @param FD Input file descriptor. 429 /// @param Size Size to resize to. 430 /// @returns errc::success if \a path has been resized to \a size, otherwise a 431 /// platform-specific error_code. 432 std::error_code resize_file(int FD, uint64_t Size); 433 434 /// Compute an MD5 hash of a file's contents. 435 /// 436 /// @param FD Input file descriptor. 437 /// @returns An MD5Result with the hash computed, if successful, otherwise a 438 /// std::error_code. 439 ErrorOr<MD5::MD5Result> md5_contents(int FD); 440 441 /// Version of compute_md5 that doesn't require an open file descriptor. 442 ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path); 443 444 /// @} 445 /// @name Physical Observers 446 /// @{ 447 448 /// Does file exist? 449 /// 450 /// @param status A basic_file_status previously returned from stat. 451 /// @returns True if the file represented by status exists, false if it does 452 /// not. 453 bool exists(const basic_file_status &status); 454 455 enum class AccessMode { Exist, Write, Execute }; 456 457 /// Can the file be accessed? 458 /// 459 /// @param Path Input path. 460 /// @returns errc::success if the path can be accessed, otherwise a 461 /// platform-specific error_code. 462 std::error_code access(const Twine &Path, AccessMode Mode); 463 464 /// Does file exist? 465 /// 466 /// @param Path Input path. 467 /// @returns True if it exists, false otherwise. 468 inline bool exists(const Twine &Path) { 469 return !access(Path, AccessMode::Exist); 470 } 471 472 /// Can we execute this file? 473 /// 474 /// @param Path Input path. 475 /// @returns True if we can execute it, false otherwise. 476 bool can_execute(const Twine &Path); 477 478 /// Can we write this file? 479 /// 480 /// @param Path Input path. 481 /// @returns True if we can write to it, false otherwise. 482 inline bool can_write(const Twine &Path) { 483 return !access(Path, AccessMode::Write); 484 } 485 486 /// Do file_status's represent the same thing? 487 /// 488 /// @param A Input file_status. 489 /// @param B Input file_status. 490 /// 491 /// assert(status_known(A) || status_known(B)); 492 /// 493 /// @returns True if A and B both represent the same file system entity, false 494 /// otherwise. 495 bool equivalent(file_status A, file_status B); 496 497 /// Do paths represent the same thing? 498 /// 499 /// assert(status_known(A) || status_known(B)); 500 /// 501 /// @param A Input path A. 502 /// @param B Input path B. 503 /// @param result Set to true if stat(A) and stat(B) have the same device and 504 /// inode (or equivalent). 505 /// @returns errc::success if result has been successfully set, otherwise a 506 /// platform-specific error_code. 507 std::error_code equivalent(const Twine &A, const Twine &B, bool &result); 508 509 /// Simpler version of equivalent for clients that don't need to 510 /// differentiate between an error and false. 511 inline bool equivalent(const Twine &A, const Twine &B) { 512 bool result; 513 return !equivalent(A, B, result) && result; 514 } 515 516 /// Is the file mounted on a local filesystem? 517 /// 518 /// @param path Input path. 519 /// @param result Set to true if \a path is on fixed media such as a hard disk, 520 /// false if it is not. 521 /// @returns errc::success if result has been successfully set, otherwise a 522 /// platform specific error_code. 523 std::error_code is_local(const Twine &path, bool &result); 524 525 /// Version of is_local accepting an open file descriptor. 526 std::error_code is_local(int FD, bool &result); 527 528 /// Simpler version of is_local for clients that don't need to 529 /// differentiate between an error and false. 530 inline bool is_local(const Twine &Path) { 531 bool Result; 532 return !is_local(Path, Result) && Result; 533 } 534 535 /// Simpler version of is_local accepting an open file descriptor for 536 /// clients that don't need to differentiate between an error and false. 537 inline bool is_local(int FD) { 538 bool Result; 539 return !is_local(FD, Result) && Result; 540 } 541 542 /// Does status represent a directory? 543 /// 544 /// @param Path The path to get the type of. 545 /// @param Follow For symbolic links, indicates whether to return the file type 546 /// of the link itself, or of the target. 547 /// @returns A value from the file_type enumeration indicating the type of file. 548 file_type get_file_type(const Twine &Path, bool Follow = true); 549 550 /// Does status represent a directory? 551 /// 552 /// @param status A basic_file_status previously returned from status. 553 /// @returns status.type() == file_type::directory_file. 554 bool is_directory(const basic_file_status &status); 555 556 /// Is path a directory? 557 /// 558 /// @param path Input path. 559 /// @param result Set to true if \a path is a directory (after following 560 /// symlinks, false if it is not. Undefined otherwise. 561 /// @returns errc::success if result has been successfully set, otherwise a 562 /// platform-specific error_code. 563 std::error_code is_directory(const Twine &path, bool &result); 564 565 /// Simpler version of is_directory for clients that don't need to 566 /// differentiate between an error and false. 567 inline bool is_directory(const Twine &Path) { 568 bool Result; 569 return !is_directory(Path, Result) && Result; 570 } 571 572 /// Does status represent a regular file? 573 /// 574 /// @param status A basic_file_status previously returned from status. 575 /// @returns status_known(status) && status.type() == file_type::regular_file. 576 bool is_regular_file(const basic_file_status &status); 577 578 /// Is path a regular file? 579 /// 580 /// @param path Input path. 581 /// @param result Set to true if \a path is a regular file (after following 582 /// symlinks), false if it is not. Undefined otherwise. 583 /// @returns errc::success if result has been successfully set, otherwise a 584 /// platform-specific error_code. 585 std::error_code is_regular_file(const Twine &path, bool &result); 586 587 /// Simpler version of is_regular_file for clients that don't need to 588 /// differentiate between an error and false. 589 inline bool is_regular_file(const Twine &Path) { 590 bool Result; 591 if (is_regular_file(Path, Result)) 592 return false; 593 return Result; 594 } 595 596 /// Does status represent a symlink file? 597 /// 598 /// @param status A basic_file_status previously returned from status. 599 /// @returns status_known(status) && status.type() == file_type::symlink_file. 600 bool is_symlink_file(const basic_file_status &status); 601 602 /// Is path a symlink file? 603 /// 604 /// @param path Input path. 605 /// @param result Set to true if \a path is a symlink file, false if it is not. 606 /// Undefined otherwise. 607 /// @returns errc::success if result has been successfully set, otherwise a 608 /// platform-specific error_code. 609 std::error_code is_symlink_file(const Twine &path, bool &result); 610 611 /// Simpler version of is_symlink_file for clients that don't need to 612 /// differentiate between an error and false. 613 inline bool is_symlink_file(const Twine &Path) { 614 bool Result; 615 if (is_symlink_file(Path, Result)) 616 return false; 617 return Result; 618 } 619 620 /// Does this status represent something that exists but is not a 621 /// directory or regular file? 622 /// 623 /// @param status A basic_file_status previously returned from status. 624 /// @returns exists(s) && !is_regular_file(s) && !is_directory(s) 625 bool is_other(const basic_file_status &status); 626 627 /// Is path something that exists but is not a directory, 628 /// regular file, or symlink? 629 /// 630 /// @param path Input path. 631 /// @param result Set to true if \a path exists, but is not a directory, regular 632 /// file, or a symlink, false if it does not. Undefined otherwise. 633 /// @returns errc::success if result has been successfully set, otherwise a 634 /// platform-specific error_code. 635 std::error_code is_other(const Twine &path, bool &result); 636 637 /// Get file status as if by POSIX stat(). 638 /// 639 /// @param path Input path. 640 /// @param result Set to the file status. 641 /// @param follow When true, follows symlinks. Otherwise, the symlink itself is 642 /// statted. 643 /// @returns errc::success if result has been successfully set, otherwise a 644 /// platform-specific error_code. 645 std::error_code status(const Twine &path, file_status &result, 646 bool follow = true); 647 648 /// A version for when a file descriptor is already available. 649 std::error_code status(int FD, file_status &Result); 650 651 #ifdef _WIN32 652 /// A version for when a file descriptor is already available. 653 std::error_code status(file_t FD, file_status &Result); 654 #endif 655 656 /// Get file creation mode mask of the process. 657 /// 658 /// @returns Mask reported by umask(2) 659 /// @note There is no umask on Windows. This function returns 0 always 660 /// on Windows. This function does not return an error_code because 661 /// umask(2) never fails. It is not thread safe. 662 unsigned getUmask(); 663 664 /// Set file permissions. 665 /// 666 /// @param Path File to set permissions on. 667 /// @param Permissions New file permissions. 668 /// @returns errc::success if the permissions were successfully set, otherwise 669 /// a platform-specific error_code. 670 /// @note On Windows, all permissions except *_write are ignored. Using any of 671 /// owner_write, group_write, or all_write will make the file writable. 672 /// Otherwise, the file will be marked as read-only. 673 std::error_code setPermissions(const Twine &Path, perms Permissions); 674 675 /// Vesion of setPermissions accepting a file descriptor. 676 /// TODO Delete the path based overload once we implement the FD based overload 677 /// on Windows. 678 std::error_code setPermissions(int FD, perms Permissions); 679 680 /// Get file permissions. 681 /// 682 /// @param Path File to get permissions from. 683 /// @returns the permissions if they were successfully retrieved, otherwise a 684 /// platform-specific error_code. 685 /// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY 686 /// attribute, all_all will be returned. Otherwise, all_read | all_exe 687 /// will be returned. 688 ErrorOr<perms> getPermissions(const Twine &Path); 689 690 /// Get file size. 691 /// 692 /// @param Path Input path. 693 /// @param Result Set to the size of the file in \a Path. 694 /// @returns errc::success if result has been successfully set, otherwise a 695 /// platform-specific error_code. 696 inline std::error_code file_size(const Twine &Path, uint64_t &Result) { 697 file_status Status; 698 std::error_code EC = status(Path, Status); 699 if (EC) 700 return EC; 701 Result = Status.getSize(); 702 return std::error_code(); 703 } 704 705 /// Set the file modification and access time. 706 /// 707 /// @returns errc::success if the file times were successfully set, otherwise a 708 /// platform-specific error_code or errc::function_not_supported on 709 /// platforms where the functionality isn't available. 710 std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, 711 TimePoint<> ModificationTime); 712 713 /// Simpler version that sets both file modification and access time to the same 714 /// time. 715 inline std::error_code setLastAccessAndModificationTime(int FD, 716 TimePoint<> Time) { 717 return setLastAccessAndModificationTime(FD, Time, Time); 718 } 719 720 /// Is status available? 721 /// 722 /// @param s Input file status. 723 /// @returns True if status() != status_error. 724 bool status_known(const basic_file_status &s); 725 726 /// Is status available? 727 /// 728 /// @param path Input path. 729 /// @param result Set to true if status() != status_error. 730 /// @returns errc::success if result has been successfully set, otherwise a 731 /// platform-specific error_code. 732 std::error_code status_known(const Twine &path, bool &result); 733 734 enum CreationDisposition : unsigned { 735 /// CD_CreateAlways - When opening a file: 736 /// * If it already exists, truncate it. 737 /// * If it does not already exist, create a new file. 738 CD_CreateAlways = 0, 739 740 /// CD_CreateNew - When opening a file: 741 /// * If it already exists, fail. 742 /// * If it does not already exist, create a new file. 743 CD_CreateNew = 1, 744 745 /// CD_OpenExisting - When opening a file: 746 /// * If it already exists, open the file with the offset set to 0. 747 /// * If it does not already exist, fail. 748 CD_OpenExisting = 2, 749 750 /// CD_OpenAlways - When opening a file: 751 /// * If it already exists, open the file with the offset set to 0. 752 /// * If it does not already exist, create a new file. 753 CD_OpenAlways = 3, 754 }; 755 756 enum FileAccess : unsigned { 757 FA_Read = 1, 758 FA_Write = 2, 759 }; 760 761 enum OpenFlags : unsigned { 762 OF_None = 0, 763 F_None = 0, // For compatibility 764 765 /// The file should be opened in text mode on platforms that make this 766 /// distinction. 767 OF_Text = 1, 768 F_Text = 1, // For compatibility 769 770 /// The file should be opened in append mode. 771 OF_Append = 2, 772 F_Append = 2, // For compatibility 773 774 /// Delete the file on close. Only makes a difference on windows. 775 OF_Delete = 4, 776 777 /// When a child process is launched, this file should remain open in the 778 /// child process. 779 OF_ChildInherit = 8, 780 781 /// Force files Atime to be updated on access. Only makes a difference on windows. 782 OF_UpdateAtime = 16, 783 }; 784 785 /// Create a potentially unique file name but does not create it. 786 /// 787 /// Generates a unique path suitable for a temporary file but does not 788 /// open or create the file. The name is based on \a Model with '%' 789 /// replaced by a random char in [0-9a-f]. If \a MakeAbsolute is true 790 /// then the system's temp directory is prepended first. If \a MakeAbsolute 791 /// is false the current directory will be used instead. 792 /// 793 /// This function does not check if the file exists. If you want to be sure 794 /// that the file does not yet exist, you should use use enough '%' characters 795 /// in your model to ensure this. Each '%' gives 4-bits of entropy so you can 796 /// use 32 of them to get 128 bits of entropy. 797 /// 798 /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 799 /// 800 /// @param Model Name to base unique path off of. 801 /// @param ResultPath Set to the file's path. 802 /// @param MakeAbsolute Whether to use the system temp directory. 803 void createUniquePath(const Twine &Model, SmallVectorImpl<char> &ResultPath, 804 bool MakeAbsolute); 805 806 /// Create a uniquely named file. 807 /// 808 /// Generates a unique path suitable for a temporary file and then opens it as a 809 /// file. The name is based on \a Model with '%' replaced by a random char in 810 /// [0-9a-f]. If \a Model is not an absolute path, the temporary file will be 811 /// created in the current directory. 812 /// 813 /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 814 /// 815 /// This is an atomic operation. Either the file is created and opened, or the 816 /// file system is left untouched. 817 /// 818 /// The intended use is for files that are to be kept, possibly after 819 /// renaming them. For example, when running 'clang -c foo.o', the file can 820 /// be first created as foo-abc123.o and then renamed. 821 /// 822 /// @param Model Name to base unique path off of. 823 /// @param ResultFD Set to the opened file's file descriptor. 824 /// @param ResultPath Set to the opened file's absolute path. 825 /// @returns errc::success if Result{FD,Path} have been successfully set, 826 /// otherwise a platform-specific error_code. 827 std::error_code createUniqueFile(const Twine &Model, int &ResultFD, 828 SmallVectorImpl<char> &ResultPath, 829 unsigned Mode = all_read | all_write); 830 831 /// Simpler version for clients that don't want an open file. An empty 832 /// file will still be created. 833 std::error_code createUniqueFile(const Twine &Model, 834 SmallVectorImpl<char> &ResultPath, 835 unsigned Mode = all_read | all_write); 836 837 /// Represents a temporary file. 838 /// 839 /// The temporary file must be eventually discarded or given a final name and 840 /// kept. 841 /// 842 /// The destructor doesn't implicitly discard because there is no way to 843 /// properly handle errors in a destructor. 844 class TempFile { 845 bool Done = false; 846 TempFile(StringRef Name, int FD); 847 848 public: 849 /// This creates a temporary file with createUniqueFile and schedules it for 850 /// deletion with sys::RemoveFileOnSignal. 851 static Expected<TempFile> create(const Twine &Model, 852 unsigned Mode = all_read | all_write); 853 TempFile(TempFile &&Other); 854 TempFile &operator=(TempFile &&Other); 855 856 // Name of the temporary file. 857 std::string TmpName; 858 859 // The open file descriptor. 860 int FD = -1; 861 862 // Keep this with the given name. 863 Error keep(const Twine &Name); 864 865 // Keep this with the temporary name. 866 Error keep(); 867 868 // Delete the file. 869 Error discard(); 870 871 // This checks that keep or delete was called. 872 ~TempFile(); 873 }; 874 875 /// Create a file in the system temporary directory. 876 /// 877 /// The filename is of the form prefix-random_chars.suffix. Since the directory 878 /// is not know to the caller, Prefix and Suffix cannot have path separators. 879 /// The files are created with mode 0600. 880 /// 881 /// This should be used for things like a temporary .s that is removed after 882 /// running the assembler. 883 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 884 int &ResultFD, 885 SmallVectorImpl<char> &ResultPath); 886 887 /// Simpler version for clients that don't want an open file. An empty 888 /// file will still be created. 889 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 890 SmallVectorImpl<char> &ResultPath); 891 892 std::error_code createUniqueDirectory(const Twine &Prefix, 893 SmallVectorImpl<char> &ResultPath); 894 895 /// Get a unique name, not currently exisiting in the filesystem. Subject 896 /// to race conditions, prefer to use createUniqueFile instead. 897 /// 898 /// Similar to createUniqueFile, but instead of creating a file only 899 /// checks if it exists. This function is subject to race conditions, if you 900 /// want to use the returned name to actually create a file, use 901 /// createUniqueFile instead. 902 std::error_code getPotentiallyUniqueFileName(const Twine &Model, 903 SmallVectorImpl<char> &ResultPath); 904 905 /// Get a unique temporary file name, not currently exisiting in the 906 /// filesystem. Subject to race conditions, prefer to use createTemporaryFile 907 /// instead. 908 /// 909 /// Similar to createTemporaryFile, but instead of creating a file only 910 /// checks if it exists. This function is subject to race conditions, if you 911 /// want to use the returned name to actually create a file, use 912 /// createTemporaryFile instead. 913 std::error_code 914 getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix, 915 SmallVectorImpl<char> &ResultPath); 916 917 inline OpenFlags operator|(OpenFlags A, OpenFlags B) { 918 return OpenFlags(unsigned(A) | unsigned(B)); 919 } 920 921 inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { 922 A = A | B; 923 return A; 924 } 925 926 inline FileAccess operator|(FileAccess A, FileAccess B) { 927 return FileAccess(unsigned(A) | unsigned(B)); 928 } 929 930 inline FileAccess &operator|=(FileAccess &A, FileAccess B) { 931 A = A | B; 932 return A; 933 } 934 935 /// @brief Opens a file with the specified creation disposition, access mode, 936 /// and flags and returns a file descriptor. 937 /// 938 /// The caller is responsible for closing the file descriptor once they are 939 /// finished with it. 940 /// 941 /// @param Name The path of the file to open, relative or absolute. 942 /// @param ResultFD If the file could be opened successfully, its descriptor 943 /// is stored in this location. Otherwise, this is set to -1. 944 /// @param Disp Value specifying the existing-file behavior. 945 /// @param Access Value specifying whether to open the file in read, write, or 946 /// read-write mode. 947 /// @param Flags Additional flags. 948 /// @param Mode The access permissions of the file, represented in octal. 949 /// @returns errc::success if \a Name has been opened, otherwise a 950 /// platform-specific error_code. 951 std::error_code openFile(const Twine &Name, int &ResultFD, 952 CreationDisposition Disp, FileAccess Access, 953 OpenFlags Flags, unsigned Mode = 0666); 954 955 /// @brief Opens a file with the specified creation disposition, access mode, 956 /// and flags and returns a platform-specific file object. 957 /// 958 /// The caller is responsible for closing the file object once they are 959 /// finished with it. 960 /// 961 /// @param Name The path of the file to open, relative or absolute. 962 /// @param Disp Value specifying the existing-file behavior. 963 /// @param Access Value specifying whether to open the file in read, write, or 964 /// read-write mode. 965 /// @param Flags Additional flags. 966 /// @param Mode The access permissions of the file, represented in octal. 967 /// @returns errc::success if \a Name has been opened, otherwise a 968 /// platform-specific error_code. 969 Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp, 970 FileAccess Access, OpenFlags Flags, 971 unsigned Mode = 0666); 972 973 /// Converts from a Posix file descriptor number to a native file handle. 974 /// On Windows, this retreives the underlying handle. On non-Windows, this is a 975 /// no-op. 976 file_t convertFDToNativeFile(int FD); 977 978 #ifndef _WIN32 979 inline file_t convertFDToNativeFile(int FD) { return FD; } 980 #endif 981 982 /// Return an open handle to standard in. On Unix, this is typically FD 0. 983 /// Returns kInvalidFile when the stream is closed. 984 file_t getStdinHandle(); 985 986 /// Return an open handle to standard out. On Unix, this is typically FD 1. 987 /// Returns kInvalidFile when the stream is closed. 988 file_t getStdoutHandle(); 989 990 /// Return an open handle to standard error. On Unix, this is typically FD 2. 991 /// Returns kInvalidFile when the stream is closed. 992 file_t getStderrHandle(); 993 994 /// Reads \p Buf.size() bytes from \p FileHandle into \p Buf. Returns the number 995 /// of bytes actually read. On Unix, this is equivalent to `return ::read(FD, 996 /// Buf.data(), Buf.size())`, with error reporting. Returns 0 when reaching EOF. 997 /// 998 /// @param FileHandle File to read from. 999 /// @param Buf Buffer to read into. 1000 /// @returns The number of bytes read, or error. 1001 Expected<size_t> readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf); 1002 1003 /// Reads \p Buf.size() bytes from \p FileHandle at offset \p Offset into \p 1004 /// Buf. If 'pread' is available, this will use that, otherwise it will use 1005 /// 'lseek'. Returns the number of bytes actually read. Returns 0 when reaching 1006 /// EOF. 1007 /// 1008 /// @param FileHandle File to read from. 1009 /// @param Buf Buffer to read into. 1010 /// @param Offset Offset into the file at which the read should occur. 1011 /// @returns The number of bytes read, or error. 1012 Expected<size_t> readNativeFileSlice(file_t FileHandle, 1013 MutableArrayRef<char> Buf, 1014 uint64_t Offset); 1015 1016 /// @brief Opens the file with the given name in a write-only or read-write 1017 /// mode, returning its open file descriptor. If the file does not exist, it 1018 /// is created. 1019 /// 1020 /// The caller is responsible for closing the file descriptor once they are 1021 /// finished with it. 1022 /// 1023 /// @param Name The path of the file to open, relative or absolute. 1024 /// @param ResultFD If the file could be opened successfully, its descriptor 1025 /// is stored in this location. Otherwise, this is set to -1. 1026 /// @param Flags Additional flags used to determine whether the file should be 1027 /// opened in, for example, read-write or in write-only mode. 1028 /// @param Mode The access permissions of the file, represented in octal. 1029 /// @returns errc::success if \a Name has been opened, otherwise a 1030 /// platform-specific error_code. 1031 inline std::error_code 1032 openFileForWrite(const Twine &Name, int &ResultFD, 1033 CreationDisposition Disp = CD_CreateAlways, 1034 OpenFlags Flags = OF_None, unsigned Mode = 0666) { 1035 return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode); 1036 } 1037 1038 /// @brief Opens the file with the given name in a write-only or read-write 1039 /// mode, returning its open file descriptor. If the file does not exist, it 1040 /// is created. 1041 /// 1042 /// The caller is responsible for closing the freeing the file once they are 1043 /// finished with it. 1044 /// 1045 /// @param Name The path of the file to open, relative or absolute. 1046 /// @param Flags Additional flags used to determine whether the file should be 1047 /// opened in, for example, read-write or in write-only mode. 1048 /// @param Mode The access permissions of the file, represented in octal. 1049 /// @returns a platform-specific file descriptor if \a Name has been opened, 1050 /// otherwise an error object. 1051 inline Expected<file_t> openNativeFileForWrite(const Twine &Name, 1052 CreationDisposition Disp, 1053 OpenFlags Flags, 1054 unsigned Mode = 0666) { 1055 return openNativeFile(Name, Disp, FA_Write, Flags, Mode); 1056 } 1057 1058 /// @brief Opens the file with the given name in a write-only or read-write 1059 /// mode, returning its open file descriptor. If the file does not exist, it 1060 /// is created. 1061 /// 1062 /// The caller is responsible for closing the file descriptor once they are 1063 /// finished with it. 1064 /// 1065 /// @param Name The path of the file to open, relative or absolute. 1066 /// @param ResultFD If the file could be opened successfully, its descriptor 1067 /// is stored in this location. Otherwise, this is set to -1. 1068 /// @param Flags Additional flags used to determine whether the file should be 1069 /// opened in, for example, read-write or in write-only mode. 1070 /// @param Mode The access permissions of the file, represented in octal. 1071 /// @returns errc::success if \a Name has been opened, otherwise a 1072 /// platform-specific error_code. 1073 inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD, 1074 CreationDisposition Disp, 1075 OpenFlags Flags, 1076 unsigned Mode = 0666) { 1077 return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode); 1078 } 1079 1080 /// @brief Opens the file with the given name in a write-only or read-write 1081 /// mode, returning its open file descriptor. If the file does not exist, it 1082 /// is created. 1083 /// 1084 /// The caller is responsible for closing the freeing the file once they are 1085 /// finished with it. 1086 /// 1087 /// @param Name The path of the file to open, relative or absolute. 1088 /// @param Flags Additional flags used to determine whether the file should be 1089 /// opened in, for example, read-write or in write-only mode. 1090 /// @param Mode The access permissions of the file, represented in octal. 1091 /// @returns a platform-specific file descriptor if \a Name has been opened, 1092 /// otherwise an error object. 1093 inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name, 1094 CreationDisposition Disp, 1095 OpenFlags Flags, 1096 unsigned Mode = 0666) { 1097 return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode); 1098 } 1099 1100 /// @brief Opens the file with the given name in a read-only mode, returning 1101 /// its open file descriptor. 1102 /// 1103 /// The caller is responsible for closing the file descriptor once they are 1104 /// finished with it. 1105 /// 1106 /// @param Name The path of the file to open, relative or absolute. 1107 /// @param ResultFD If the file could be opened successfully, its descriptor 1108 /// is stored in this location. Otherwise, this is set to -1. 1109 /// @param RealPath If nonnull, extra work is done to determine the real path 1110 /// of the opened file, and that path is stored in this 1111 /// location. 1112 /// @returns errc::success if \a Name has been opened, otherwise a 1113 /// platform-specific error_code. 1114 std::error_code openFileForRead(const Twine &Name, int &ResultFD, 1115 OpenFlags Flags = OF_None, 1116 SmallVectorImpl<char> *RealPath = nullptr); 1117 1118 /// @brief Opens the file with the given name in a read-only mode, returning 1119 /// its open file descriptor. 1120 /// 1121 /// The caller is responsible for closing the freeing the file once they are 1122 /// finished with it. 1123 /// 1124 /// @param Name The path of the file to open, relative or absolute. 1125 /// @param RealPath If nonnull, extra work is done to determine the real path 1126 /// of the opened file, and that path is stored in this 1127 /// location. 1128 /// @returns a platform-specific file descriptor if \a Name has been opened, 1129 /// otherwise an error object. 1130 Expected<file_t> 1131 openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None, 1132 SmallVectorImpl<char> *RealPath = nullptr); 1133 1134 /// @brief Close the file object. This should be used instead of ::close for 1135 /// portability. On error, the caller should assume the file is closed, as is 1136 /// the case for Process::SafelyCloseFileDescriptor 1137 /// 1138 /// @param F On input, this is the file to close. On output, the file is 1139 /// set to kInvalidFile. 1140 /// 1141 /// @returns An error code if closing the file failed. Typically, an error here 1142 /// means that the filesystem may have failed to perform some buffered writes. 1143 std::error_code closeFile(file_t &F); 1144 1145 std::error_code getUniqueID(const Twine Path, UniqueID &Result); 1146 1147 /// Get disk space usage information. 1148 /// 1149 /// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug. 1150 /// Note: Windows reports results according to the quota allocated to the user. 1151 /// 1152 /// @param Path Input path. 1153 /// @returns a space_info structure filled with the capacity, free, and 1154 /// available space on the device \a Path is on. A platform specific error_code 1155 /// is returned on error. 1156 ErrorOr<space_info> disk_space(const Twine &Path); 1157 1158 /// This class represents a memory mapped file. It is based on 1159 /// boost::iostreams::mapped_file. 1160 class mapped_file_region { 1161 public: 1162 enum mapmode { 1163 readonly, ///< May only access map via const_data as read only. 1164 readwrite, ///< May access map via data and modify it. Written to path. 1165 priv ///< May modify via data, but changes are lost on destruction. 1166 }; 1167 1168 private: 1169 /// Platform-specific mapping state. 1170 size_t Size; 1171 void *Mapping; 1172 #ifdef _WIN32 1173 sys::fs::file_t FileHandle; 1174 #endif 1175 mapmode Mode; 1176 1177 std::error_code init(sys::fs::file_t FD, uint64_t Offset, mapmode Mode); 1178 1179 public: 1180 mapped_file_region() = delete; 1181 mapped_file_region(mapped_file_region&) = delete; 1182 mapped_file_region &operator =(mapped_file_region&) = delete; 1183 1184 /// \param fd An open file descriptor to map. Does not take ownership of fd. 1185 mapped_file_region(sys::fs::file_t fd, mapmode mode, size_t length, uint64_t offset, 1186 std::error_code &ec); 1187 1188 ~mapped_file_region(); 1189 1190 size_t size() const; 1191 char *data() const; 1192 1193 /// Get a const view of the data. Modifying this memory has undefined 1194 /// behavior. 1195 const char *const_data() const; 1196 1197 /// \returns The minimum alignment offset must be. 1198 static int alignment(); 1199 }; 1200 1201 /// Return the path to the main executable, given the value of argv[0] from 1202 /// program startup and the address of main itself. In extremis, this function 1203 /// may fail and return an empty path. 1204 std::string getMainExecutable(const char *argv0, void *MainExecAddr); 1205 1206 /// @} 1207 /// @name Iterators 1208 /// @{ 1209 1210 /// directory_entry - A single entry in a directory. 1211 class directory_entry { 1212 // FIXME: different platforms make different information available "for free" 1213 // when traversing a directory. The design of this class wraps most of the 1214 // information in basic_file_status, so on platforms where we can't populate 1215 // that whole structure, callers end up paying for a stat(). 1216 // std::filesystem::directory_entry may be a better model. 1217 std::string Path; 1218 file_type Type = file_type::type_unknown; // Most platforms can provide this. 1219 bool FollowSymlinks = true; // Affects the behavior of status(). 1220 basic_file_status Status; // If available. 1221 1222 public: 1223 explicit directory_entry(const Twine &Path, bool FollowSymlinks = true, 1224 file_type Type = file_type::type_unknown, 1225 basic_file_status Status = basic_file_status()) 1226 : Path(Path.str()), Type(Type), FollowSymlinks(FollowSymlinks), 1227 Status(Status) {} 1228 1229 directory_entry() = default; 1230 1231 void replace_filename(const Twine &Filename, file_type Type, 1232 basic_file_status Status = basic_file_status()); 1233 1234 const std::string &path() const { return Path; } 1235 // Get basic information about entry file (a subset of fs::status()). 1236 // On most platforms this is a stat() call. 1237 // On windows the information was already retrieved from the directory. 1238 ErrorOr<basic_file_status> status() const; 1239 // Get the type of this file. 1240 // On most platforms (Linux/Mac/Windows/BSD), this was already retrieved. 1241 // On some platforms (e.g. Solaris) this is a stat() call. 1242 file_type type() const { 1243 if (Type != file_type::type_unknown) 1244 return Type; 1245 auto S = status(); 1246 return S ? S->type() : file_type::type_unknown; 1247 } 1248 1249 bool operator==(const directory_entry& RHS) const { return Path == RHS.Path; } 1250 bool operator!=(const directory_entry& RHS) const { return !(*this == RHS); } 1251 bool operator< (const directory_entry& RHS) const; 1252 bool operator<=(const directory_entry& RHS) const; 1253 bool operator> (const directory_entry& RHS) const; 1254 bool operator>=(const directory_entry& RHS) const; 1255 }; 1256 1257 namespace detail { 1258 1259 struct DirIterState; 1260 1261 std::error_code directory_iterator_construct(DirIterState &, StringRef, bool); 1262 std::error_code directory_iterator_increment(DirIterState &); 1263 std::error_code directory_iterator_destruct(DirIterState &); 1264 1265 /// Keeps state for the directory_iterator. 1266 struct DirIterState { 1267 ~DirIterState() { 1268 directory_iterator_destruct(*this); 1269 } 1270 1271 intptr_t IterationHandle = 0; 1272 directory_entry CurrentEntry; 1273 }; 1274 1275 } // end namespace detail 1276 1277 /// directory_iterator - Iterates through the entries in path. There is no 1278 /// operator++ because we need an error_code. If it's really needed we can make 1279 /// it call report_fatal_error on error. 1280 class directory_iterator { 1281 std::shared_ptr<detail::DirIterState> State; 1282 bool FollowSymlinks = true; 1283 1284 public: 1285 explicit directory_iterator(const Twine &path, std::error_code &ec, 1286 bool follow_symlinks = true) 1287 : FollowSymlinks(follow_symlinks) { 1288 State = std::make_shared<detail::DirIterState>(); 1289 SmallString<128> path_storage; 1290 ec = detail::directory_iterator_construct( 1291 *State, path.toStringRef(path_storage), FollowSymlinks); 1292 } 1293 1294 explicit directory_iterator(const directory_entry &de, std::error_code &ec, 1295 bool follow_symlinks = true) 1296 : FollowSymlinks(follow_symlinks) { 1297 State = std::make_shared<detail::DirIterState>(); 1298 ec = detail::directory_iterator_construct( 1299 *State, de.path(), FollowSymlinks); 1300 } 1301 1302 /// Construct end iterator. 1303 directory_iterator() = default; 1304 1305 // No operator++ because we need error_code. 1306 directory_iterator &increment(std::error_code &ec) { 1307 ec = directory_iterator_increment(*State); 1308 return *this; 1309 } 1310 1311 const directory_entry &operator*() const { return State->CurrentEntry; } 1312 const directory_entry *operator->() const { return &State->CurrentEntry; } 1313 1314 bool operator==(const directory_iterator &RHS) const { 1315 if (State == RHS.State) 1316 return true; 1317 if (!RHS.State) 1318 return State->CurrentEntry == directory_entry(); 1319 if (!State) 1320 return RHS.State->CurrentEntry == directory_entry(); 1321 return State->CurrentEntry == RHS.State->CurrentEntry; 1322 } 1323 1324 bool operator!=(const directory_iterator &RHS) const { 1325 return !(*this == RHS); 1326 } 1327 }; 1328 1329 namespace detail { 1330 1331 /// Keeps state for the recursive_directory_iterator. 1332 struct RecDirIterState { 1333 std::stack<directory_iterator, std::vector<directory_iterator>> Stack; 1334 uint16_t Level = 0; 1335 bool HasNoPushRequest = false; 1336 }; 1337 1338 } // end namespace detail 1339 1340 /// recursive_directory_iterator - Same as directory_iterator except for it 1341 /// recurses down into child directories. 1342 class recursive_directory_iterator { 1343 std::shared_ptr<detail::RecDirIterState> State; 1344 bool Follow; 1345 1346 public: 1347 recursive_directory_iterator() = default; 1348 explicit recursive_directory_iterator(const Twine &path, std::error_code &ec, 1349 bool follow_symlinks = true) 1350 : State(std::make_shared<detail::RecDirIterState>()), 1351 Follow(follow_symlinks) { 1352 State->Stack.push(directory_iterator(path, ec, Follow)); 1353 if (State->Stack.top() == directory_iterator()) 1354 State.reset(); 1355 } 1356 1357 // No operator++ because we need error_code. 1358 recursive_directory_iterator &increment(std::error_code &ec) { 1359 const directory_iterator end_itr = {}; 1360 1361 if (State->HasNoPushRequest) 1362 State->HasNoPushRequest = false; 1363 else { 1364 file_type type = State->Stack.top()->type(); 1365 if (type == file_type::symlink_file && Follow) { 1366 // Resolve the symlink: is it a directory to recurse into? 1367 ErrorOr<basic_file_status> status = State->Stack.top()->status(); 1368 if (status) 1369 type = status->type(); 1370 // Otherwise broken symlink, and we'll continue. 1371 } 1372 if (type == file_type::directory_file) { 1373 State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow)); 1374 if (State->Stack.top() != end_itr) { 1375 ++State->Level; 1376 return *this; 1377 } 1378 State->Stack.pop(); 1379 } 1380 } 1381 1382 while (!State->Stack.empty() 1383 && State->Stack.top().increment(ec) == end_itr) { 1384 State->Stack.pop(); 1385 --State->Level; 1386 } 1387 1388 // Check if we are done. If so, create an end iterator. 1389 if (State->Stack.empty()) 1390 State.reset(); 1391 1392 return *this; 1393 } 1394 1395 const directory_entry &operator*() const { return *State->Stack.top(); } 1396 const directory_entry *operator->() const { return &*State->Stack.top(); } 1397 1398 // observers 1399 /// Gets the current level. Starting path is at level 0. 1400 int level() const { return State->Level; } 1401 1402 /// Returns true if no_push has been called for this directory_entry. 1403 bool no_push_request() const { return State->HasNoPushRequest; } 1404 1405 // modifiers 1406 /// Goes up one level if Level > 0. 1407 void pop() { 1408 assert(State && "Cannot pop an end iterator!"); 1409 assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 1410 1411 const directory_iterator end_itr = {}; 1412 std::error_code ec; 1413 do { 1414 if (ec) 1415 report_fatal_error("Error incrementing directory iterator."); 1416 State->Stack.pop(); 1417 --State->Level; 1418 } while (!State->Stack.empty() 1419 && State->Stack.top().increment(ec) == end_itr); 1420 1421 // Check if we are done. If so, create an end iterator. 1422 if (State->Stack.empty()) 1423 State.reset(); 1424 } 1425 1426 /// Does not go down into the current directory_entry. 1427 void no_push() { State->HasNoPushRequest = true; } 1428 1429 bool operator==(const recursive_directory_iterator &RHS) const { 1430 return State == RHS.State; 1431 } 1432 1433 bool operator!=(const recursive_directory_iterator &RHS) const { 1434 return !(*this == RHS); 1435 } 1436 }; 1437 1438 /// @} 1439 1440 } // end namespace fs 1441 } // end namespace sys 1442 } // end namespace llvm 1443 1444 #endif // LLVM_SUPPORT_FILESYSTEM_H 1445