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_FILE_SYSTEM_H 28 #define LLVM_SUPPORT_FILE_SYSTEM_H 29 30 #include "llvm/ADT/IntrusiveRefCntPtr.h" 31 #include "llvm/ADT/SmallString.h" 32 #include "llvm/ADT/Twine.h" 33 #include "llvm/Support/DataTypes.h" 34 #include "llvm/Support/ErrorHandling.h" 35 #include "llvm/Support/system_error.h" 36 #include <ctime> 37 #include <iterator> 38 #include <stack> 39 #include <string> 40 #include <vector> 41 42 #if HAVE_SYS_STAT_H 43 #include <sys/stat.h> 44 #endif 45 46 namespace llvm { 47 namespace sys { 48 namespace fs { 49 50 /// file_type - An "enum class" enumeration for the file system's view of the 51 /// type. 52 struct file_type { 53 enum _ { 54 status_error, 55 file_not_found, 56 regular_file, 57 directory_file, 58 symlink_file, 59 block_file, 60 character_file, 61 fifo_file, 62 socket_file, 63 type_unknown 64 }; 65 66 file_type(_ v) : v_(v) {} 67 explicit file_type(int v) : v_(_(v)) {} 68 operator int() const {return v_;} 69 70 private: 71 int v_; 72 }; 73 74 /// copy_option - An "enum class" enumeration of copy semantics for copy 75 /// operations. 76 struct copy_option { 77 enum _ { 78 fail_if_exists, 79 overwrite_if_exists 80 }; 81 82 copy_option(_ v) : v_(v) {} 83 explicit copy_option(int v) : v_(_(v)) {} 84 operator int() const {return v_;} 85 86 private: 87 int v_; 88 }; 89 90 /// space_info - Self explanatory. 91 struct space_info { 92 uint64_t capacity; 93 uint64_t free; 94 uint64_t available; 95 }; 96 97 /// file_status - Represents the result of a call to stat and friends. It has 98 /// a platform specific member to store the result. 99 class file_status 100 { 101 #if defined(LLVM_ON_UNIX) 102 dev_t st_dev; 103 ino_t st_ino; 104 #elif defined (LLVM_ON_WIN32) 105 uint32_t LastWriteTimeHigh; 106 uint32_t LastWriteTimeLow; 107 uint32_t VolumeSerialNumber; 108 uint32_t FileSizeHigh; 109 uint32_t FileSizeLow; 110 uint32_t FileIndexHigh; 111 uint32_t FileIndexLow; 112 #endif 113 friend bool equivalent(file_status A, file_status B); 114 friend error_code status(const Twine &path, file_status &result); 115 file_type Type; 116 public: 117 explicit file_status(file_type v=file_type::status_error) 118 : Type(v) {} 119 120 file_type type() const { return Type; } 121 void type(file_type v) { Type = v; } 122 }; 123 124 /// file_magic - An "enum class" enumeration of file types based on magic (the first 125 /// N bytes of the file). 126 struct file_magic { 127 enum _ { 128 unknown = 0, ///< Unrecognized file 129 bitcode, ///< Bitcode file 130 archive, ///< ar style archive file 131 elf_relocatable, ///< ELF Relocatable object file 132 elf_executable, ///< ELF Executable image 133 elf_shared_object, ///< ELF dynamically linked shared lib 134 elf_core, ///< ELF core image 135 macho_object, ///< Mach-O Object file 136 macho_executable, ///< Mach-O Executable 137 macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM 138 macho_core, ///< Mach-O Core File 139 macho_preload_executabl, ///< Mach-O Preloaded Executable 140 macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib 141 macho_dynamic_linker, ///< The Mach-O dynamic linker 142 macho_bundle, ///< Mach-O Bundle file 143 macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub 144 macho_dsym_companion, ///< Mach-O dSYM companion file 145 coff_object, ///< COFF object file 146 pecoff_executable ///< PECOFF executable file 147 }; 148 149 bool is_object() const { 150 return v_ == unknown ? false : true; 151 } 152 153 file_magic() : v_(unknown) {} 154 file_magic(_ v) : v_(v) {} 155 explicit file_magic(int v) : v_(_(v)) {} 156 operator int() const {return v_;} 157 158 private: 159 int v_; 160 }; 161 162 /// @} 163 /// @name Physical Operators 164 /// @{ 165 166 /// @brief Make \a path an absolute path. 167 /// 168 /// Makes \a path absolute using the current directory if it is not already. An 169 /// empty \a path will result in the current directory. 170 /// 171 /// /absolute/path => /absolute/path 172 /// relative/../path => <current-directory>/relative/../path 173 /// 174 /// @param path A path that is modified to be an absolute path. 175 /// @returns errc::success if \a path has been made absolute, otherwise a 176 /// platform specific error_code. 177 error_code make_absolute(SmallVectorImpl<char> &path); 178 179 /// @brief Copy the file at \a from to the path \a to. 180 /// 181 /// @param from The path to copy the file from. 182 /// @param to The path to copy the file to. 183 /// @param copt Behavior if \a to already exists. 184 /// @returns errc::success if the file has been successfully copied. 185 /// errc::file_exists if \a to already exists and \a copt == 186 /// copy_option::fail_if_exists. Otherwise a platform specific 187 /// error_code. 188 error_code copy_file(const Twine &from, const Twine &to, 189 copy_option copt = copy_option::fail_if_exists); 190 191 /// @brief Create all the non-existent directories in path. 192 /// 193 /// @param path Directories to create. 194 /// @param existed Set to true if \a path already existed, false otherwise. 195 /// @returns errc::success if is_directory(path) and existed have been set, 196 /// otherwise a platform specific error_code. 197 error_code create_directories(const Twine &path, bool &existed); 198 199 /// @brief Create the directory in path. 200 /// 201 /// @param path Directory to create. 202 /// @param existed Set to true if \a path already existed, false otherwise. 203 /// @returns errc::success if is_directory(path) and existed have been set, 204 /// otherwise a platform specific error_code. 205 error_code create_directory(const Twine &path, bool &existed); 206 207 /// @brief Create a hard link from \a from to \a to. 208 /// 209 /// @param to The path to hard link to. 210 /// @param from The path to hard link from. This is created. 211 /// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) 212 /// , otherwise a platform specific error_code. 213 error_code create_hard_link(const Twine &to, const Twine &from); 214 215 /// @brief Create a symbolic link from \a from to \a to. 216 /// 217 /// @param to The path to symbolically link to. 218 /// @param from The path to symbolically link from. This is created. 219 /// @returns errc::success if exists(to) && exists(from) && is_symlink(from), 220 /// otherwise a platform specific error_code. 221 error_code create_symlink(const Twine &to, const Twine &from); 222 223 /// @brief Get the current path. 224 /// 225 /// @param result Holds the current path on return. 226 /// @results errc::success if the current path has been stored in result, 227 /// otherwise a platform specific error_code. 228 error_code current_path(SmallVectorImpl<char> &result); 229 230 /// @brief Remove path. Equivalent to POSIX remove(). 231 /// 232 /// @param path Input path. 233 /// @param existed Set to true if \a path existed, false if it did not. 234 /// undefined otherwise. 235 /// @results errc::success if path has been removed and existed has been 236 /// successfully set, otherwise a platform specific error_code. 237 error_code remove(const Twine &path, bool &existed); 238 239 /// @brief Recursively remove all files below \a path, then \a path. Files are 240 /// removed as if by POSIX remove(). 241 /// 242 /// @param path Input path. 243 /// @param num_removed Number of files removed. 244 /// @results errc::success if path has been removed and num_removed has been 245 /// successfully set, otherwise a platform specific error_code. 246 error_code remove_all(const Twine &path, uint32_t &num_removed); 247 248 /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 249 /// 250 /// @param from The path to rename from. 251 /// @param to The path to rename to. This is created. 252 error_code rename(const Twine &from, const Twine &to); 253 254 /// @brief Resize path to size. File is resized as if by POSIX truncate(). 255 /// 256 /// @param path Input path. 257 /// @param size Size to resize to. 258 /// @returns errc::success if \a path has been resized to \a size, otherwise a 259 /// platform specific error_code. 260 error_code resize_file(const Twine &path, uint64_t size); 261 262 /// @} 263 /// @name Physical Observers 264 /// @{ 265 266 /// @brief Does file exist? 267 /// 268 /// @param status A file_status previously returned from stat. 269 /// @results True if the file represented by status exists, false if it does 270 /// not. 271 bool exists(file_status status); 272 273 /// @brief Does file exist? 274 /// 275 /// @param path Input path. 276 /// @param result Set to true if the file represented by status exists, false if 277 /// it does not. Undefined otherwise. 278 /// @results errc::success if result has been successfully set, otherwise a 279 /// platform specific error_code. 280 error_code exists(const Twine &path, bool &result); 281 282 /// @brief Simpler version of exists for clients that don't need to 283 /// differentiate between an error and false. 284 inline bool exists(const Twine &path) { 285 bool result; 286 return !exists(path, result) && result; 287 } 288 289 /// @brief Do file_status's represent the same thing? 290 /// 291 /// @param A Input file_status. 292 /// @param B Input file_status. 293 /// 294 /// assert(status_known(A) || status_known(B)); 295 /// 296 /// @results True if A and B both represent the same file system entity, false 297 /// otherwise. 298 bool equivalent(file_status A, file_status B); 299 300 /// @brief Do paths represent the same thing? 301 /// 302 /// assert(status_known(A) || status_known(B)); 303 /// 304 /// @param A Input path A. 305 /// @param B Input path B. 306 /// @param result Set to true if stat(A) and stat(B) have the same device and 307 /// inode (or equivalent). 308 /// @results errc::success if result has been successfully set, otherwise a 309 /// platform specific error_code. 310 error_code equivalent(const Twine &A, const Twine &B, bool &result); 311 312 /// @brief Get file size. 313 /// 314 /// @param path Input path. 315 /// @param result Set to the size of the file in \a path. 316 /// @returns errc::success if result has been successfully set, otherwise a 317 /// platform specific error_code. 318 error_code file_size(const Twine &path, uint64_t &result); 319 320 /// @brief Does status represent a directory? 321 /// 322 /// @param status A file_status previously returned from status. 323 /// @results status.type() == file_type::directory_file. 324 bool is_directory(file_status status); 325 326 /// @brief Is path a directory? 327 /// 328 /// @param path Input path. 329 /// @param result Set to true if \a path is a directory, false if it is not. 330 /// Undefined otherwise. 331 /// @results errc::success if result has been successfully set, otherwise a 332 /// platform specific error_code. 333 error_code is_directory(const Twine &path, bool &result); 334 335 /// @brief Does status represent a regular file? 336 /// 337 /// @param status A file_status previously returned from status. 338 /// @results status_known(status) && status.type() == file_type::regular_file. 339 bool is_regular_file(file_status status); 340 341 /// @brief Is path a regular file? 342 /// 343 /// @param path Input path. 344 /// @param result Set to true if \a path is a regular file, false if it is not. 345 /// Undefined otherwise. 346 /// @results errc::success if result has been successfully set, otherwise a 347 /// platform specific error_code. 348 error_code is_regular_file(const Twine &path, bool &result); 349 350 /// @brief Does this status represent something that exists but is not a 351 /// directory, regular file, or symlink? 352 /// 353 /// @param status A file_status previously returned from status. 354 /// @results exists(s) && !is_regular_file(s) && !is_directory(s) && 355 /// !is_symlink(s) 356 bool is_other(file_status status); 357 358 /// @brief Is path something that exists but is not a directory, 359 /// regular file, or symlink? 360 /// 361 /// @param path Input path. 362 /// @param result Set to true if \a path exists, but is not a directory, regular 363 /// file, or a symlink, false if it does not. Undefined otherwise. 364 /// @results errc::success if result has been successfully set, otherwise a 365 /// platform specific error_code. 366 error_code is_other(const Twine &path, bool &result); 367 368 /// @brief Does status represent a symlink? 369 /// 370 /// @param status A file_status previously returned from stat. 371 /// @param result status.type() == symlink_file. 372 bool is_symlink(file_status status); 373 374 /// @brief Is path a symlink? 375 /// 376 /// @param path Input path. 377 /// @param result Set to true if \a path is a symlink, false if it is not. 378 /// Undefined otherwise. 379 /// @results errc::success if result has been successfully set, otherwise a 380 /// platform specific error_code. 381 error_code is_symlink(const Twine &path, bool &result); 382 383 /// @brief Get file status as if by POSIX stat(). 384 /// 385 /// @param path Input path. 386 /// @param result Set to the file status. 387 /// @results errc::success if result has been successfully set, otherwise a 388 /// platform specific error_code. 389 error_code status(const Twine &path, file_status &result); 390 391 /// @brief Is status available? 392 /// 393 /// @param path Input path. 394 /// @results True if status() != status_error. 395 bool status_known(file_status s); 396 397 /// @brief Is status available? 398 /// 399 /// @param path Input path. 400 /// @param result Set to true if status() != status_error. 401 /// @results errc::success if result has been successfully set, otherwise a 402 /// platform specific error_code. 403 error_code status_known(const Twine &path, bool &result); 404 405 /// @brief Generate a unique path and open it as a file. 406 /// 407 /// Generates a unique path suitable for a temporary file and then opens it as a 408 /// file. The name is based on \a model with '%' replaced by a random char in 409 /// [0-9a-f]. If \a model is not an absolute path, a suitable temporary 410 /// directory will be prepended. 411 /// 412 /// This is an atomic operation. Either the file is created and opened, or the 413 /// file system is left untouched. 414 /// 415 /// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s 416 /// 417 /// @param model Name to base unique path off of. 418 /// @param result_fs Set to the opened file's file descriptor. 419 /// @param result_path Set to the opened file's absolute path. 420 /// @param makeAbsolute If true and @model is not an absolute path, a temp 421 /// directory will be prepended. 422 /// @results errc::success if result_{fd,path} have been successfully set, 423 /// otherwise a platform specific error_code. 424 error_code unique_file(const Twine &model, int &result_fd, 425 SmallVectorImpl<char> &result_path, 426 bool makeAbsolute = true); 427 428 /// @brief Canonicalize path. 429 /// 430 /// Sets result to the file system's idea of what path is. The result is always 431 /// absolute and has the same capitalization as the file system. 432 /// 433 /// @param path Input path. 434 /// @param result Set to the canonicalized version of \a path. 435 /// @results errc::success if result has been successfully set, otherwise a 436 /// platform specific error_code. 437 error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); 438 439 /// @brief Are \a path's first bytes \a magic? 440 /// 441 /// @param path Input path. 442 /// @param magic Byte sequence to compare \a path's first len(magic) bytes to. 443 /// @results errc::success if result has been successfully set, otherwise a 444 /// platform specific error_code. 445 error_code has_magic(const Twine &path, const Twine &magic, bool &result); 446 447 /// @brief Get \a path's first \a len bytes. 448 /// 449 /// @param path Input path. 450 /// @param len Number of magic bytes to get. 451 /// @param result Set to the first \a len bytes in the file pointed to by 452 /// \a path. Or the entire file if file_size(path) < len, in which 453 /// case result.size() returns the size of the file. 454 /// @results errc::success if result has been successfully set, 455 /// errc::value_too_large if len is larger then the file pointed to by 456 /// \a path, otherwise a platform specific error_code. 457 error_code get_magic(const Twine &path, uint32_t len, 458 SmallVectorImpl<char> &result); 459 460 /// @brief Identify the type of a binary file based on how magical it is. 461 file_magic identify_magic(StringRef magic); 462 463 /// @brief Get and identify \a path's type based on its content. 464 /// 465 /// @param path Input path. 466 /// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. 467 /// @results errc::success if result has been successfully set, otherwise a 468 /// platform specific error_code. 469 error_code identify_magic(const Twine &path, file_magic &result); 470 471 /// @brief Get library paths the system linker uses. 472 /// 473 /// @param result Set to the list of system library paths. 474 /// @results errc::success if result has been successfully set, otherwise a 475 /// platform specific error_code. 476 error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); 477 478 /// @brief Get bitcode library paths the system linker uses 479 /// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. 480 /// 481 /// @param result Set to the list of bitcode library paths. 482 /// @results errc::success if result has been successfully set, otherwise a 483 /// platform specific error_code. 484 error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); 485 486 /// @brief Find a library. 487 /// 488 /// Find the path to a library using its short name. Use the system 489 /// dependent library paths to locate the library. 490 /// 491 /// c => /usr/lib/libc.so 492 /// 493 /// @param short_name Library name one would give to the system linker. 494 /// @param result Set to the absolute path \a short_name represents. 495 /// @results errc::success if result has been successfully set, otherwise a 496 /// platform specific error_code. 497 error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); 498 499 /// @brief Get absolute path of main executable. 500 /// 501 /// @param argv0 The program name as it was spelled on the command line. 502 /// @param MainAddr Address of some symbol in the executable (not in a library). 503 /// @param result Set to the absolute path of the current executable. 504 /// @results errc::success if result has been successfully set, otherwise a 505 /// platform specific error_code. 506 error_code GetMainExecutable(const char *argv0, void *MainAddr, 507 SmallVectorImpl<char> &result); 508 509 /// @} 510 /// @name Iterators 511 /// @{ 512 513 /// directory_entry - A single entry in a directory. Caches the status either 514 /// from the result of the iteration syscall, or the first time status is 515 /// called. 516 class directory_entry { 517 std::string Path; 518 mutable file_status Status; 519 520 public: 521 explicit directory_entry(const Twine &path, file_status st = file_status()) 522 : Path(path.str()) 523 , Status(st) {} 524 525 directory_entry() {} 526 527 void assign(const Twine &path, file_status st = file_status()) { 528 Path = path.str(); 529 Status = st; 530 } 531 532 void replace_filename(const Twine &filename, file_status st = file_status()); 533 534 const std::string &path() const { return Path; } 535 error_code status(file_status &result) const; 536 537 bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 538 bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 539 bool operator< (const directory_entry& rhs) const; 540 bool operator<=(const directory_entry& rhs) const; 541 bool operator> (const directory_entry& rhs) const; 542 bool operator>=(const directory_entry& rhs) const; 543 }; 544 545 namespace detail { 546 struct DirIterState; 547 548 error_code directory_iterator_construct(DirIterState&, StringRef); 549 error_code directory_iterator_increment(DirIterState&); 550 error_code directory_iterator_destruct(DirIterState&); 551 552 /// DirIterState - Keeps state for the directory_iterator. It is reference 553 /// counted in order to preserve InputIterator semantics on copy. 554 struct DirIterState : public RefCountedBase<DirIterState> { 555 DirIterState() 556 : IterationHandle(0) {} 557 558 ~DirIterState() { 559 directory_iterator_destruct(*this); 560 } 561 562 intptr_t IterationHandle; 563 directory_entry CurrentEntry; 564 }; 565 } 566 567 /// directory_iterator - Iterates through the entries in path. There is no 568 /// operator++ because we need an error_code. If it's really needed we can make 569 /// it call report_fatal_error on error. 570 class directory_iterator { 571 IntrusiveRefCntPtr<detail::DirIterState> State; 572 573 public: 574 explicit directory_iterator(const Twine &path, error_code &ec) { 575 State = new detail::DirIterState; 576 SmallString<128> path_storage; 577 ec = detail::directory_iterator_construct(*State, 578 path.toStringRef(path_storage)); 579 } 580 581 explicit directory_iterator(const directory_entry &de, error_code &ec) { 582 State = new detail::DirIterState; 583 ec = detail::directory_iterator_construct(*State, de.path()); 584 } 585 586 /// Construct end iterator. 587 directory_iterator() : State(new detail::DirIterState) {} 588 589 // No operator++ because we need error_code. 590 directory_iterator &increment(error_code &ec) { 591 ec = directory_iterator_increment(*State); 592 return *this; 593 } 594 595 const directory_entry &operator*() const { return State->CurrentEntry; } 596 const directory_entry *operator->() const { return &State->CurrentEntry; } 597 598 bool operator==(const directory_iterator &RHS) const { 599 return State->CurrentEntry == RHS.State->CurrentEntry; 600 } 601 602 bool operator!=(const directory_iterator &RHS) const { 603 return !(*this == RHS); 604 } 605 // Other members as required by 606 // C++ Std, 24.1.1 Input iterators [input.iterators] 607 }; 608 609 namespace detail { 610 /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is 611 /// reference counted in order to preserve InputIterator semantics on copy. 612 struct RecDirIterState : public RefCountedBase<RecDirIterState> { 613 RecDirIterState() 614 : Level(0) 615 , HasNoPushRequest(false) {} 616 617 std::stack<directory_iterator, std::vector<directory_iterator> > Stack; 618 uint16_t Level; 619 bool HasNoPushRequest; 620 }; 621 } 622 623 /// recursive_directory_iterator - Same as directory_iterator except for it 624 /// recurses down into child directories. 625 class recursive_directory_iterator { 626 IntrusiveRefCntPtr<detail::RecDirIterState> State; 627 628 public: 629 recursive_directory_iterator() {} 630 explicit recursive_directory_iterator(const Twine &path, error_code &ec) 631 : State(new detail::RecDirIterState) { 632 State->Stack.push(directory_iterator(path, ec)); 633 if (State->Stack.top() == directory_iterator()) 634 State.reset(); 635 } 636 // No operator++ because we need error_code. 637 recursive_directory_iterator &increment(error_code &ec) { 638 static const directory_iterator end_itr; 639 640 if (State->HasNoPushRequest) 641 State->HasNoPushRequest = false; 642 else { 643 file_status st; 644 if ((ec = State->Stack.top()->status(st))) return *this; 645 if (is_directory(st)) { 646 State->Stack.push(directory_iterator(*State->Stack.top(), ec)); 647 if (ec) return *this; 648 if (State->Stack.top() != end_itr) { 649 ++State->Level; 650 return *this; 651 } 652 State->Stack.pop(); 653 } 654 } 655 656 while (!State->Stack.empty() 657 && State->Stack.top().increment(ec) == end_itr) { 658 State->Stack.pop(); 659 --State->Level; 660 } 661 662 // Check if we are done. If so, create an end iterator. 663 if (State->Stack.empty()) 664 State.reset(); 665 666 return *this; 667 } 668 669 const directory_entry &operator*() const { return *State->Stack.top(); } 670 const directory_entry *operator->() const { return &*State->Stack.top(); } 671 672 // observers 673 /// Gets the current level. Starting path is at level 0. 674 int level() const { return State->Level; } 675 676 /// Returns true if no_push has been called for this directory_entry. 677 bool no_push_request() const { return State->HasNoPushRequest; } 678 679 // modifiers 680 /// Goes up one level if Level > 0. 681 void pop() { 682 assert(State && "Cannot pop and end itertor!"); 683 assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 684 685 static const directory_iterator end_itr; 686 error_code ec; 687 do { 688 if (ec) 689 report_fatal_error("Error incrementing directory iterator."); 690 State->Stack.pop(); 691 --State->Level; 692 } while (!State->Stack.empty() 693 && State->Stack.top().increment(ec) == end_itr); 694 695 // Check if we are done. If so, create an end iterator. 696 if (State->Stack.empty()) 697 State.reset(); 698 } 699 700 /// Does not go down into the current directory_entry. 701 void no_push() { State->HasNoPushRequest = true; } 702 703 bool operator==(const recursive_directory_iterator &RHS) const { 704 return State == RHS.State; 705 } 706 707 bool operator!=(const recursive_directory_iterator &RHS) const { 708 return !(*this == RHS); 709 } 710 // Other members as required by 711 // C++ Std, 24.1.1 Input iterators [input.iterators] 712 }; 713 714 /// @} 715 716 } // end namespace fs 717 } // end namespace sys 718 } // end namespace llvm 719 720 #endif 721