Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/bits/fs_dir.h
1 // Filesystem directory utilities -*- C++ -*- 2 3 // Copyright (C) 2014-2025 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file include/bits/fs_dir.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{filesystem} 28 */ 29 30 #ifndef _GLIBCXX_FS_DIR_H 31 #define _GLIBCXX_FS_DIR_H 1 32 33 #if __cplusplus >= 201703L 34 # include <typeinfo> 35 # include <ext/concurrence.h> 36 # include <bits/unique_ptr.h> 37 # include <bits/shared_ptr.h> 38 39 #if __cplusplus >= 202002L 40 # include <compare> // std::strong_ordering 41 # include <bits/iterator_concepts.h> // std::default_sentinel_t 42 # include <bits/ranges_base.h> // enable_view, enable_borrowed_range 43 #endif 44 45 namespace std _GLIBCXX_VISIBILITY(default) 46 { 47 _GLIBCXX_BEGIN_NAMESPACE_VERSION 48 49 namespace filesystem 50 { 51 /** @addtogroup filesystem 52 * @{ 53 */ 54 55 /// Information about a file's type and permissions. 56 /** 57 * @headerfile filesystem 58 * @since C++17 59 */ 60 class file_status 61 { 62 public: 63 // constructors and destructor 64 file_status() noexcept : file_status(file_type::none) {} 65 66 explicit 67 file_status(file_type __ft, perms __prms = perms::unknown) noexcept 68 : _M_type(__ft), _M_perms(__prms) { } 69 70 file_status(const file_status&) noexcept = default; 71 file_status(file_status&&) noexcept = default; 72 ~file_status() = default; 73 74 file_status& operator=(const file_status&) noexcept = default; 75 file_status& operator=(file_status&&) noexcept = default; 76 77 // observers 78 file_type type() const noexcept { return _M_type; } 79 perms permissions() const noexcept { return _M_perms; } 80 81 // modifiers 82 void type(file_type __ft) noexcept { _M_type = __ft; } 83 void permissions(perms __prms) noexcept { _M_perms = __prms; } 84 85 #if __cpp_lib_three_way_comparison 86 friend bool 87 operator==(const file_status&, const file_status&) noexcept = default; 88 #endif 89 90 private: 91 file_type _M_type; 92 perms _M_perms; 93 }; 94 95 _GLIBCXX_BEGIN_NAMESPACE_CXX11 96 97 struct _Dir; 98 class directory_iterator; 99 class recursive_directory_iterator; 100 101 /// The value type used by directory iterators 102 /** 103 * @headerfile filesystem 104 * @since C++17 105 */ 106 class directory_entry 107 { 108 public: 109 // constructors and destructor 110 directory_entry() noexcept = default; 111 directory_entry(const directory_entry&) = default; 112 directory_entry(directory_entry&&) noexcept = default; 113 114 explicit 115 directory_entry(const filesystem::path& __p) 116 : _M_path(__p) 117 { refresh(); } 118 119 directory_entry(const filesystem::path& __p, error_code& __ec) 120 : _M_path(__p) 121 { 122 refresh(__ec); 123 if (__ec) 124 _M_path.clear(); 125 } 126 127 ~directory_entry() = default; 128 129 // modifiers 130 directory_entry& operator=(const directory_entry&) = default; 131 directory_entry& operator=(directory_entry&&) noexcept = default; 132 133 void 134 assign(const filesystem::path& __p) 135 { 136 _M_path = __p; 137 refresh(); 138 } 139 140 void 141 assign(const filesystem::path& __p, error_code& __ec) 142 { 143 _M_path = __p; 144 refresh(__ec); 145 } 146 147 void 148 replace_filename(const filesystem::path& __p) 149 { 150 _M_path.replace_filename(__p); 151 refresh(); 152 } 153 154 void 155 replace_filename(const filesystem::path& __p, error_code& __ec) 156 { 157 _M_path.replace_filename(__p); 158 refresh(__ec); 159 } 160 161 void 162 refresh() 163 { _M_type = symlink_status().type(); } 164 165 void 166 refresh(error_code& __ec) noexcept 167 { _M_type = symlink_status(__ec).type(); } 168 169 // observers 170 const filesystem::path& path() const noexcept { return _M_path; } 171 operator const filesystem::path& () const noexcept { return _M_path; } 172 173 bool 174 exists() const 175 { return filesystem::exists(file_status{_M_file_type()}); } 176 177 bool 178 exists(error_code& __ec) const noexcept 179 { return filesystem::exists(file_status{_M_file_type(__ec)}); } 180 181 bool 182 is_block_file() const 183 { return _M_file_type() == file_type::block; } 184 185 bool 186 is_block_file(error_code& __ec) const noexcept 187 { return _M_file_type(__ec) == file_type::block; } 188 189 bool 190 is_character_file() const 191 { return _M_file_type() == file_type::character; } 192 193 bool 194 is_character_file(error_code& __ec) const noexcept 195 { return _M_file_type(__ec) == file_type::character; } 196 197 bool 198 is_directory() const 199 { return _M_file_type() == file_type::directory; } 200 201 bool 202 is_directory(error_code& __ec) const noexcept 203 { return _M_file_type(__ec) == file_type::directory; } 204 205 bool 206 is_fifo() const 207 { return _M_file_type() == file_type::fifo; } 208 209 bool 210 is_fifo(error_code& __ec) const noexcept 211 { return _M_file_type(__ec) == file_type::fifo; } 212 213 bool 214 is_other() const 215 { return filesystem::is_other(file_status{_M_file_type()}); } 216 217 bool 218 is_other(error_code& __ec) const noexcept 219 { return filesystem::is_other(file_status{_M_file_type(__ec)}); } 220 221 bool 222 is_regular_file() const 223 { return _M_file_type() == file_type::regular; } 224 225 bool 226 is_regular_file(error_code& __ec) const noexcept 227 { return _M_file_type(__ec) == file_type::regular; } 228 229 bool 230 is_socket() const 231 { return _M_file_type() == file_type::socket; } 232 233 bool 234 is_socket(error_code& __ec) const noexcept 235 { return _M_file_type(__ec) == file_type::socket; } 236 237 bool 238 is_symlink() const 239 { 240 if (_M_type != file_type::none) 241 return _M_type == file_type::symlink; 242 return symlink_status().type() == file_type::symlink; 243 } 244 245 bool 246 is_symlink(error_code& __ec) const noexcept 247 { 248 if (_M_type != file_type::none) 249 return _M_type == file_type::symlink; 250 return symlink_status(__ec).type() == file_type::symlink; 251 } 252 253 uintmax_t 254 file_size() const 255 { return filesystem::file_size(_M_path); } 256 257 uintmax_t 258 file_size(error_code& __ec) const noexcept 259 { return filesystem::file_size(_M_path, __ec); } 260 261 uintmax_t 262 hard_link_count() const 263 { return filesystem::hard_link_count(_M_path); } 264 265 uintmax_t 266 hard_link_count(error_code& __ec) const noexcept 267 { return filesystem::hard_link_count(_M_path, __ec); } 268 269 file_time_type 270 last_write_time() const 271 { return filesystem::last_write_time(_M_path); } 272 273 274 file_time_type 275 last_write_time(error_code& __ec) const noexcept 276 { return filesystem::last_write_time(_M_path, __ec); } 277 278 file_status 279 status() const 280 { return filesystem::status(_M_path); } 281 282 file_status 283 status(error_code& __ec) const noexcept 284 { return filesystem::status(_M_path, __ec); } 285 286 file_status 287 symlink_status() const 288 { return filesystem::symlink_status(_M_path); } 289 290 file_status 291 symlink_status(error_code& __ec) const noexcept 292 { return filesystem::symlink_status(_M_path, __ec); } 293 294 bool 295 operator==(const directory_entry& __rhs) const noexcept 296 { return _M_path == __rhs._M_path; } 297 298 #if __cpp_lib_three_way_comparison 299 strong_ordering 300 operator<=>(const directory_entry& __rhs) const noexcept 301 { return _M_path <=> __rhs._M_path; } 302 #else 303 bool 304 operator!=(const directory_entry& __rhs) const noexcept 305 { return _M_path != __rhs._M_path; } 306 307 bool 308 operator< (const directory_entry& __rhs) const noexcept 309 { return _M_path < __rhs._M_path; } 310 311 bool 312 operator<=(const directory_entry& __rhs) const noexcept 313 { return _M_path <= __rhs._M_path; } 314 315 bool 316 operator> (const directory_entry& __rhs) const noexcept 317 { return _M_path > __rhs._M_path; } 318 319 bool 320 operator>=(const directory_entry& __rhs) const noexcept 321 { return _M_path >= __rhs._M_path; } 322 #endif 323 324 private: 325 friend struct _Dir; 326 friend class directory_iterator; 327 friend class recursive_directory_iterator; 328 329 // _GLIBCXX_RESOLVE_LIB_DEFECTS 330 // 3171. LWG 2989 breaks directory_entry stream insertion 331 template<typename _CharT, typename _Traits> 332 friend basic_ostream<_CharT, _Traits>& 333 operator<<(basic_ostream<_CharT, _Traits>& __os, 334 const directory_entry& __d) 335 { return __os << __d.path(); } 336 337 directory_entry(const filesystem::path& __p, file_type __t) 338 : _M_path(__p), _M_type(__t) 339 { } 340 341 // Equivalent to status().type() but uses cached value, if any. 342 file_type 343 _M_file_type() const 344 { 345 if (_M_type != file_type::none && _M_type != file_type::symlink) 346 return _M_type; 347 return status().type(); 348 } 349 350 // Equivalent to status(__ec).type() but uses cached value, if any. 351 file_type 352 _M_file_type(error_code& __ec) const noexcept 353 { 354 if (_M_type != file_type::none && _M_type != file_type::symlink) 355 { 356 __ec.clear(); 357 return _M_type; 358 } 359 return status(__ec).type(); 360 } 361 362 filesystem::path _M_path; 363 file_type _M_type = file_type::none; 364 }; 365 366 /// @cond undocumented 367 368 /// Proxy returned by post-increment on directory iterators. 369 /** 370 * @headerfile filesystem 371 * @since C++17 372 */ 373 struct __directory_iterator_proxy 374 { 375 const directory_entry& operator*() const& noexcept { return _M_entry; } 376 377 directory_entry operator*() && noexcept { return std::move(_M_entry); } 378 379 private: 380 friend class directory_iterator; 381 friend class recursive_directory_iterator; 382 383 explicit 384 __directory_iterator_proxy(const directory_entry& __e) : _M_entry(__e) { } 385 386 directory_entry _M_entry; 387 }; 388 /// @endcond 389 390 /// Iterator type for traversing the entries in a single directory. 391 /** 392 * @headerfile filesystem 393 * @since C++17 394 */ 395 class directory_iterator 396 { 397 public: 398 typedef directory_entry value_type; 399 typedef ptrdiff_t difference_type; 400 typedef const directory_entry* pointer; 401 typedef const directory_entry& reference; 402 typedef input_iterator_tag iterator_category; 403 404 directory_iterator() = default; 405 406 explicit 407 directory_iterator(const path& __p) 408 : directory_iterator(__p, directory_options::none, nullptr) { } 409 410 directory_iterator(const path& __p, directory_options __options) 411 : directory_iterator(__p, __options, nullptr) { } 412 413 directory_iterator(const path& __p, error_code& __ec) 414 : directory_iterator(__p, directory_options::none, __ec) { } 415 416 directory_iterator(const path& __p, directory_options __options, 417 error_code& __ec) 418 : directory_iterator(__p, __options, &__ec) { } 419 420 directory_iterator(const directory_iterator& __rhs) = default; 421 422 directory_iterator(directory_iterator&& __rhs) noexcept = default; 423 424 ~directory_iterator() = default; 425 426 directory_iterator& 427 operator=(const directory_iterator& __rhs) = default; 428 429 directory_iterator& 430 operator=(directory_iterator&& __rhs) noexcept = default; 431 432 const directory_entry& operator*() const noexcept; 433 const directory_entry* operator->() const noexcept { return &**this; } 434 directory_iterator& operator++(); 435 directory_iterator& increment(error_code& __ec); 436 437 __directory_iterator_proxy operator++(int) 438 { 439 __directory_iterator_proxy __pr{**this}; 440 ++*this; 441 return __pr; 442 } 443 444 friend bool 445 operator==(const directory_iterator& __lhs, 446 const directory_iterator& __rhs) noexcept 447 { 448 return !__rhs._M_dir.owner_before(__lhs._M_dir) 449 && !__lhs._M_dir.owner_before(__rhs._M_dir); 450 } 451 452 #if __cplusplus >= 202002L 453 // _GLIBCXX_RESOLVE_LIB_DEFECTS 454 // 3719. Directory iterators should be usable with default sentinel 455 bool operator==(default_sentinel_t) const noexcept 456 { return !_M_dir; } 457 #endif 458 459 #if __cpp_impl_three_way_comparison < 201907L 460 friend bool 461 operator!=(const directory_iterator& __lhs, 462 const directory_iterator& __rhs) noexcept 463 { return !(__lhs == __rhs); } 464 #endif 465 466 private: 467 directory_iterator(const path&, directory_options, error_code*); 468 469 friend class recursive_directory_iterator; 470 471 std::__shared_ptr<_Dir> _M_dir; 472 }; 473 474 /** @relates std::filesystem::directory_iterator 475 * @headerfile filesystem 476 * @since C++17 477 * @{ 478 */ 479 480 /** @brief Enable range-based `for` using directory_iterator. 481 * 482 * e.g. `for (auto& entry : std::filesystem::directory_iterator(".")) ...` 483 */ 484 inline directory_iterator 485 begin(directory_iterator __iter) noexcept 486 { return __iter; } 487 488 /// Return a past-the-end directory_iterator 489 inline directory_iterator 490 end(directory_iterator) noexcept 491 { return directory_iterator(); } 492 /// @} 493 494 /// Iterator type for recursively traversing a directory hierarchy. 495 /** 496 * @headerfile filesystem 497 * @since C++17 498 */ 499 class recursive_directory_iterator 500 { 501 public: 502 typedef directory_entry value_type; 503 typedef ptrdiff_t difference_type; 504 typedef const directory_entry* pointer; 505 typedef const directory_entry& reference; 506 typedef input_iterator_tag iterator_category; 507 508 recursive_directory_iterator() = default; 509 510 explicit 511 recursive_directory_iterator(const path& __p) 512 : recursive_directory_iterator(__p, directory_options::none, nullptr) { } 513 514 recursive_directory_iterator(const path& __p, directory_options __options) 515 : recursive_directory_iterator(__p, __options, nullptr) { } 516 517 recursive_directory_iterator(const path& __p, directory_options __options, 518 error_code& __ec) 519 : recursive_directory_iterator(__p, __options, &__ec) { } 520 521 recursive_directory_iterator(const path& __p, error_code& __ec) 522 : recursive_directory_iterator(__p, directory_options::none, &__ec) { } 523 524 recursive_directory_iterator( 525 const recursive_directory_iterator&) = default; 526 527 recursive_directory_iterator(recursive_directory_iterator&&) = default; 528 529 ~recursive_directory_iterator(); 530 531 // observers 532 directory_options options() const noexcept; 533 int depth() const noexcept; 534 bool recursion_pending() const noexcept; 535 536 const directory_entry& operator*() const noexcept; 537 const directory_entry* operator->() const noexcept { return &**this; } 538 539 // modifiers 540 recursive_directory_iterator& 541 operator=(const recursive_directory_iterator& __rhs) noexcept; 542 recursive_directory_iterator& 543 operator=(recursive_directory_iterator&& __rhs) noexcept; 544 545 recursive_directory_iterator& operator++(); 546 recursive_directory_iterator& increment(error_code& __ec); 547 548 __directory_iterator_proxy operator++(int) 549 { 550 __directory_iterator_proxy __pr{**this}; 551 ++*this; 552 return __pr; 553 } 554 555 void pop(); 556 void pop(error_code&); 557 558 void disable_recursion_pending() noexcept; 559 560 friend bool 561 operator==(const recursive_directory_iterator& __lhs, 562 const recursive_directory_iterator& __rhs) noexcept 563 { 564 return !__rhs._M_dirs.owner_before(__lhs._M_dirs) 565 && !__lhs._M_dirs.owner_before(__rhs._M_dirs); 566 } 567 568 #if __cplusplus >= 202002L 569 // _GLIBCXX_RESOLVE_LIB_DEFECTS 570 // 3719. Directory iterators should be usable with default sentinel 571 bool operator==(default_sentinel_t) const noexcept 572 { return !_M_dirs; } 573 #endif 574 575 #if __cpp_impl_three_way_comparison < 201907L 576 friend bool 577 operator!=(const recursive_directory_iterator& __lhs, 578 const recursive_directory_iterator& __rhs) noexcept 579 { return !(__lhs == __rhs); } 580 #endif 581 582 private: 583 recursive_directory_iterator(const path&, directory_options, error_code*); 584 585 struct _Dir_stack; 586 std::__shared_ptr<_Dir_stack> _M_dirs; 587 588 recursive_directory_iterator& 589 __erase(error_code* = nullptr); 590 591 friend uintmax_t 592 filesystem::remove_all(const path&, error_code&); 593 friend uintmax_t 594 filesystem::remove_all(const path&); 595 }; 596 597 /** @relates std::filesystem::directory_iterator 598 * @headerfile filesystem 599 * @since C++17 600 * @{ 601 */ 602 603 /** @brief Enable range-based `for` using recursive_directory_iterator. 604 * 605 * e.g. `for (auto& entry : recursive_directory_iterator(".")) ...` 606 */ 607 inline recursive_directory_iterator 608 begin(recursive_directory_iterator __iter) noexcept 609 { return __iter; } 610 611 /// Return a past-the-end recursive_directory_iterator 612 inline recursive_directory_iterator 613 end(recursive_directory_iterator) noexcept 614 { return recursive_directory_iterator(); } 615 /// @} 616 617 _GLIBCXX_END_NAMESPACE_CXX11 618 619 /// @} group filesystem 620 } // namespace filesystem 621 622 // Use explicit instantiations of these types. Any inconsistency in the 623 // value of __default_lock_policy between code including this header and 624 // the library will cause a linker error. 625 extern template class 626 __shared_ptr<filesystem::_Dir>; 627 extern template class 628 __shared_ptr<filesystem::recursive_directory_iterator::_Dir_stack>; 629 630 #if __glibcxx_ranges // >= C++20 631 // _GLIBCXX_RESOLVE_LIB_DEFECTS 632 // 3480. directory_iterator and recursive_directory_iterator are not ranges 633 namespace ranges 634 { 635 template<> 636 inline constexpr bool 637 enable_borrowed_range<filesystem::directory_iterator> = true; 638 template<> 639 inline constexpr bool 640 enable_borrowed_range<filesystem::recursive_directory_iterator> = true; 641 642 template<> 643 inline constexpr bool 644 enable_view<filesystem::directory_iterator> = true; 645 template<> 646 inline constexpr bool 647 enable_view<filesystem::recursive_directory_iterator> = true; 648 } // namespace ranges 649 #endif // ranges 650 651 _GLIBCXX_END_NAMESPACE_VERSION 652 } // namespace std 653 654 #endif // C++17 655 656 #endif // _GLIBCXX_FS_DIR_H