Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:47

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H
0011 #define _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H
0012 
0013 #include <__chrono/time_point.h>
0014 #include <__compare/ordering.h>
0015 #include <__config>
0016 #include <__filesystem/file_status.h>
0017 #include <__filesystem/file_time_type.h>
0018 #include <__filesystem/file_type.h>
0019 #include <__filesystem/filesystem_error.h>
0020 #include <__filesystem/operations.h>
0021 #include <__filesystem/path.h>
0022 #include <__filesystem/perms.h>
0023 #include <__fwd/ostream.h>
0024 #include <__system_error/errc.h>
0025 #include <__system_error/error_category.h>
0026 #include <__system_error/error_code.h>
0027 #include <__system_error/error_condition.h>
0028 #include <__utility/move.h>
0029 #include <__utility/unreachable.h>
0030 #include <cstdint>
0031 
0032 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0033 #  pragma GCC system_header
0034 #endif
0035 
0036 _LIBCPP_PUSH_MACROS
0037 #include <__undef_macros>
0038 
0039 #if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
0040 
0041 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
0042 
0043 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
0044 
0045 class directory_entry {
0046   typedef filesystem::path _Path;
0047 
0048 public:
0049   // constructors and destructors
0050   _LIBCPP_HIDE_FROM_ABI directory_entry() noexcept                  = default;
0051   _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry const&)     = default;
0052   _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry&&) noexcept = default;
0053 
0054   _LIBCPP_HIDE_FROM_ABI explicit directory_entry(_Path const& __p) : __p_(__p) {
0055     error_code __ec;
0056     __refresh(&__ec);
0057   }
0058 
0059   _LIBCPP_HIDE_FROM_ABI directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) { __refresh(&__ec); }
0060 
0061   _LIBCPP_HIDE_FROM_ABI ~directory_entry() {}
0062 
0063   _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry const&)     = default;
0064   _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry&&) noexcept = default;
0065 
0066   _LIBCPP_HIDE_FROM_ABI void assign(_Path const& __p) {
0067     __p_ = __p;
0068     error_code __ec;
0069     __refresh(&__ec);
0070   }
0071 
0072   _LIBCPP_HIDE_FROM_ABI void assign(_Path const& __p, error_code& __ec) {
0073     __p_ = __p;
0074     __refresh(&__ec);
0075   }
0076 
0077   _LIBCPP_HIDE_FROM_ABI void replace_filename(_Path const& __p) {
0078     __p_.replace_filename(__p);
0079     error_code __ec;
0080     __refresh(&__ec);
0081   }
0082 
0083   _LIBCPP_HIDE_FROM_ABI void replace_filename(_Path const& __p, error_code& __ec) {
0084     __p_ = __p_.parent_path() / __p;
0085     __refresh(&__ec);
0086   }
0087 
0088   _LIBCPP_HIDE_FROM_ABI void refresh() { __refresh(); }
0089 
0090   _LIBCPP_HIDE_FROM_ABI void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
0091 
0092   _LIBCPP_HIDE_FROM_ABI _Path const& path() const noexcept { return __p_; }
0093 
0094   _LIBCPP_HIDE_FROM_ABI operator const _Path&() const noexcept { return __p_; }
0095 
0096   _LIBCPP_HIDE_FROM_ABI bool exists() const { return filesystem::exists(file_status{__get_ft()}); }
0097 
0098   _LIBCPP_HIDE_FROM_ABI bool exists(error_code& __ec) const noexcept {
0099     return filesystem::exists(file_status{__get_ft(&__ec)});
0100   }
0101 
0102   _LIBCPP_HIDE_FROM_ABI bool is_block_file() const { return __get_ft() == file_type::block; }
0103 
0104   _LIBCPP_HIDE_FROM_ABI bool is_block_file(error_code& __ec) const noexcept {
0105     return __get_ft(&__ec) == file_type::block;
0106   }
0107 
0108   _LIBCPP_HIDE_FROM_ABI bool is_character_file() const { return __get_ft() == file_type::character; }
0109 
0110   _LIBCPP_HIDE_FROM_ABI bool is_character_file(error_code& __ec) const noexcept {
0111     return __get_ft(&__ec) == file_type::character;
0112   }
0113 
0114   _LIBCPP_HIDE_FROM_ABI bool is_directory() const { return __get_ft() == file_type::directory; }
0115 
0116   _LIBCPP_HIDE_FROM_ABI bool is_directory(error_code& __ec) const noexcept {
0117     return __get_ft(&__ec) == file_type::directory;
0118   }
0119 
0120   _LIBCPP_HIDE_FROM_ABI bool is_fifo() const { return __get_ft() == file_type::fifo; }
0121 
0122   _LIBCPP_HIDE_FROM_ABI bool is_fifo(error_code& __ec) const noexcept { return __get_ft(&__ec) == file_type::fifo; }
0123 
0124   _LIBCPP_HIDE_FROM_ABI bool is_other() const { return filesystem::is_other(file_status{__get_ft()}); }
0125 
0126   _LIBCPP_HIDE_FROM_ABI bool is_other(error_code& __ec) const noexcept {
0127     return filesystem::is_other(file_status{__get_ft(&__ec)});
0128   }
0129 
0130   _LIBCPP_HIDE_FROM_ABI bool is_regular_file() const { return __get_ft() == file_type::regular; }
0131 
0132   _LIBCPP_HIDE_FROM_ABI bool is_regular_file(error_code& __ec) const noexcept {
0133     return __get_ft(&__ec) == file_type::regular;
0134   }
0135 
0136   _LIBCPP_HIDE_FROM_ABI bool is_socket() const { return __get_ft() == file_type::socket; }
0137 
0138   _LIBCPP_HIDE_FROM_ABI bool is_socket(error_code& __ec) const noexcept { return __get_ft(&__ec) == file_type::socket; }
0139 
0140   _LIBCPP_HIDE_FROM_ABI bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
0141 
0142   _LIBCPP_HIDE_FROM_ABI bool is_symlink(error_code& __ec) const noexcept {
0143     return __get_sym_ft(&__ec) == file_type::symlink;
0144   }
0145   _LIBCPP_HIDE_FROM_ABI uintmax_t file_size() const { return __get_size(); }
0146 
0147   _LIBCPP_HIDE_FROM_ABI uintmax_t file_size(error_code& __ec) const noexcept { return __get_size(&__ec); }
0148 
0149   _LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count() const { return __get_nlink(); }
0150 
0151   _LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count(error_code& __ec) const noexcept { return __get_nlink(&__ec); }
0152 
0153   _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time() const { return __get_write_time(); }
0154 
0155   _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(error_code& __ec) const noexcept {
0156     return __get_write_time(&__ec);
0157   }
0158 
0159   _LIBCPP_HIDE_FROM_ABI file_status status() const { return __get_status(); }
0160 
0161   _LIBCPP_HIDE_FROM_ABI file_status status(error_code& __ec) const noexcept { return __get_status(&__ec); }
0162 
0163   _LIBCPP_HIDE_FROM_ABI file_status symlink_status() const { return __get_symlink_status(); }
0164 
0165   _LIBCPP_HIDE_FROM_ABI file_status symlink_status(error_code& __ec) const noexcept {
0166     return __get_symlink_status(&__ec);
0167   }
0168 
0169   _LIBCPP_HIDE_FROM_ABI bool operator==(directory_entry const& __rhs) const noexcept { return __p_ == __rhs.__p_; }
0170 
0171 #  if _LIBCPP_STD_VER <= 17
0172   _LIBCPP_HIDE_FROM_ABI bool operator!=(directory_entry const& __rhs) const noexcept { return __p_ != __rhs.__p_; }
0173 
0174   _LIBCPP_HIDE_FROM_ABI bool operator<(directory_entry const& __rhs) const noexcept { return __p_ < __rhs.__p_; }
0175 
0176   _LIBCPP_HIDE_FROM_ABI bool operator<=(directory_entry const& __rhs) const noexcept { return __p_ <= __rhs.__p_; }
0177 
0178   _LIBCPP_HIDE_FROM_ABI bool operator>(directory_entry const& __rhs) const noexcept { return __p_ > __rhs.__p_; }
0179 
0180   _LIBCPP_HIDE_FROM_ABI bool operator>=(directory_entry const& __rhs) const noexcept { return __p_ >= __rhs.__p_; }
0181 
0182 #  else // _LIBCPP_STD_VER <= 17
0183 
0184   _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const directory_entry& __rhs) const noexcept {
0185     return __p_ <=> __rhs.__p_;
0186   }
0187 
0188 #  endif // _LIBCPP_STD_VER <= 17
0189 
0190   template <class _CharT, class _Traits>
0191   _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&
0192   operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) {
0193     return __os << __d.path();
0194   }
0195 
0196 private:
0197   friend class directory_iterator;
0198   friend class recursive_directory_iterator;
0199   friend class _LIBCPP_HIDDEN __dir_stream;
0200 
0201   enum _CacheType : unsigned char {
0202     _Empty,
0203     _IterSymlink,
0204     _IterNonSymlink,
0205     _RefreshSymlink,
0206     _RefreshSymlinkUnresolved,
0207     _RefreshNonSymlink,
0208     _IterCachedSymlink,
0209     _IterCachedNonSymlink
0210   };
0211 
0212   struct __cached_data {
0213     uintmax_t __size_;
0214     uintmax_t __nlink_;
0215     file_time_type __write_time_;
0216     perms __sym_perms_;
0217     perms __non_sym_perms_;
0218     file_type __type_;
0219     _CacheType __cache_type_;
0220 
0221     _LIBCPP_HIDE_FROM_ABI __cached_data() noexcept { __reset(); }
0222 
0223     _LIBCPP_HIDE_FROM_ABI void __reset() {
0224       __cache_type_ = _Empty;
0225       __type_       = file_type::none;
0226       __sym_perms_ = __non_sym_perms_ = perms::unknown;
0227       __size_ = __nlink_ = uintmax_t(-1);
0228       __write_time_      = file_time_type::min();
0229     }
0230   };
0231 
0232   _LIBCPP_HIDE_FROM_ABI static __cached_data __create_iter_result(file_type __ft) {
0233     __cached_data __data;
0234     __data.__type_       = __ft;
0235     __data.__cache_type_ = [&]() {
0236       switch (__ft) {
0237       case file_type::none:
0238         return _Empty;
0239       case file_type::symlink:
0240         return _IterSymlink;
0241       default:
0242         return _IterNonSymlink;
0243       }
0244     }();
0245     return __data;
0246   }
0247 
0248   _LIBCPP_HIDE_FROM_ABI static __cached_data
0249   __create_iter_cached_result(file_type __ft, uintmax_t __size, perms __perm, file_time_type __write_time) {
0250     __cached_data __data;
0251     __data.__type_       = __ft;
0252     __data.__size_       = __size;
0253     __data.__write_time_ = __write_time;
0254     if (__ft == file_type::symlink)
0255       __data.__sym_perms_ = __perm;
0256     else
0257       __data.__non_sym_perms_ = __perm;
0258     __data.__cache_type_ = [&]() {
0259       switch (__ft) {
0260       case file_type::none:
0261         return _Empty;
0262       case file_type::symlink:
0263         return _IterCachedSymlink;
0264       default:
0265         return _IterCachedNonSymlink;
0266       }
0267     }();
0268     return __data;
0269   }
0270 
0271   _LIBCPP_HIDE_FROM_ABI void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
0272     __p_    = std::move(__p);
0273     __data_ = __dt;
0274   }
0275 
0276   _LIBCPP_EXPORTED_FROM_ABI error_code __do_refresh() noexcept;
0277 
0278   _LIBCPP_HIDE_FROM_ABI static bool __is_dne_error(error_code const& __ec) {
0279     return !__ec || __ec == errc::no_such_file_or_directory || __ec == errc::not_a_directory;
0280   }
0281 
0282   _LIBCPP_HIDE_FROM_ABI void
0283   __handle_error(const char* __msg, error_code* __dest_ec, error_code const& __ec, bool __allow_dne = false) const {
0284     if (__dest_ec) {
0285       *__dest_ec = __ec;
0286       return;
0287     }
0288     if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
0289       __throw_filesystem_error(__msg, __p_, __ec);
0290   }
0291 
0292   _LIBCPP_HIDE_FROM_ABI void __refresh(error_code* __ec = nullptr) {
0293     __handle_error("in directory_entry::refresh",
0294                    __ec,
0295                    __do_refresh(),
0296                    /*allow_dne*/ true);
0297   }
0298 
0299   _LIBCPP_HIDE_FROM_ABI file_type __get_sym_ft(error_code* __ec = nullptr) const {
0300     switch (__data_.__cache_type_) {
0301     case _Empty:
0302       return __symlink_status(__p_, __ec).type();
0303     case _IterSymlink:
0304     case _IterCachedSymlink:
0305     case _RefreshSymlink:
0306     case _RefreshSymlinkUnresolved:
0307       if (__ec)
0308         __ec->clear();
0309       return file_type::symlink;
0310     case _IterCachedNonSymlink:
0311     case _IterNonSymlink:
0312     case _RefreshNonSymlink: {
0313       file_status __st(__data_.__type_);
0314       if (__ec && !filesystem::exists(__st))
0315         *__ec = make_error_code(errc::no_such_file_or_directory);
0316       else if (__ec)
0317         __ec->clear();
0318       return __data_.__type_;
0319     }
0320     }
0321     __libcpp_unreachable();
0322   }
0323 
0324   _LIBCPP_HIDE_FROM_ABI file_type __get_ft(error_code* __ec = nullptr) const {
0325     switch (__data_.__cache_type_) {
0326     case _Empty:
0327     case _IterSymlink:
0328     case _IterCachedSymlink:
0329     case _RefreshSymlinkUnresolved:
0330       return __status(__p_, __ec).type();
0331     case _IterCachedNonSymlink:
0332     case _IterNonSymlink:
0333     case _RefreshNonSymlink:
0334     case _RefreshSymlink: {
0335       file_status __st(__data_.__type_);
0336       if (__ec && !filesystem::exists(__st))
0337         *__ec = make_error_code(errc::no_such_file_or_directory);
0338       else if (__ec)
0339         __ec->clear();
0340       return __data_.__type_;
0341     }
0342     }
0343     __libcpp_unreachable();
0344   }
0345 
0346   _LIBCPP_HIDE_FROM_ABI file_status __get_status(error_code* __ec = nullptr) const {
0347     switch (__data_.__cache_type_) {
0348     case _Empty:
0349     case _IterNonSymlink:
0350     case _IterSymlink:
0351     case _IterCachedSymlink:
0352     case _RefreshSymlinkUnresolved:
0353       return __status(__p_, __ec);
0354     case _IterCachedNonSymlink:
0355     case _RefreshNonSymlink:
0356     case _RefreshSymlink:
0357       return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
0358     }
0359     __libcpp_unreachable();
0360   }
0361 
0362   _LIBCPP_HIDE_FROM_ABI file_status __get_symlink_status(error_code* __ec = nullptr) const {
0363     switch (__data_.__cache_type_) {
0364     case _Empty:
0365     case _IterNonSymlink:
0366     case _IterSymlink:
0367       return __symlink_status(__p_, __ec);
0368     case _IterCachedNonSymlink:
0369     case _RefreshNonSymlink:
0370       return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
0371     case _IterCachedSymlink:
0372     case _RefreshSymlink:
0373     case _RefreshSymlinkUnresolved:
0374       return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
0375     }
0376     __libcpp_unreachable();
0377   }
0378 
0379   _LIBCPP_HIDE_FROM_ABI uintmax_t __get_size(error_code* __ec = nullptr) const {
0380     switch (__data_.__cache_type_) {
0381     case _Empty:
0382     case _IterNonSymlink:
0383     case _IterSymlink:
0384     case _IterCachedSymlink:
0385     case _RefreshSymlinkUnresolved:
0386       return filesystem::__file_size(__p_, __ec);
0387     case _IterCachedNonSymlink:
0388     case _RefreshSymlink:
0389     case _RefreshNonSymlink: {
0390       error_code __m_ec;
0391       file_status __st(__get_ft(&__m_ec));
0392       __handle_error("in directory_entry::file_size", __ec, __m_ec);
0393       if (filesystem::exists(__st) && !filesystem::is_regular_file(__st)) {
0394         errc __err_kind = filesystem::is_directory(__st) ? errc::is_a_directory : errc::not_supported;
0395         __handle_error("in directory_entry::file_size", __ec, make_error_code(__err_kind));
0396       }
0397       return __data_.__size_;
0398     }
0399     }
0400     __libcpp_unreachable();
0401   }
0402 
0403   _LIBCPP_HIDE_FROM_ABI uintmax_t __get_nlink(error_code* __ec = nullptr) const {
0404     switch (__data_.__cache_type_) {
0405     case _Empty:
0406     case _IterNonSymlink:
0407     case _IterSymlink:
0408     case _IterCachedNonSymlink:
0409     case _IterCachedSymlink:
0410     case _RefreshSymlinkUnresolved:
0411       return filesystem::__hard_link_count(__p_, __ec);
0412     case _RefreshSymlink:
0413     case _RefreshNonSymlink: {
0414       error_code __m_ec;
0415       (void)__get_ft(&__m_ec);
0416       __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
0417       return __data_.__nlink_;
0418     }
0419     }
0420     __libcpp_unreachable();
0421   }
0422 
0423   _LIBCPP_HIDE_FROM_ABI file_time_type __get_write_time(error_code* __ec = nullptr) const {
0424     switch (__data_.__cache_type_) {
0425     case _Empty:
0426     case _IterNonSymlink:
0427     case _IterSymlink:
0428     case _IterCachedSymlink:
0429     case _RefreshSymlinkUnresolved:
0430       return filesystem::__last_write_time(__p_, __ec);
0431     case _IterCachedNonSymlink:
0432     case _RefreshSymlink:
0433     case _RefreshNonSymlink: {
0434       error_code __m_ec;
0435       file_status __st(__get_ft(&__m_ec));
0436       __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
0437       if (filesystem::exists(__st) && __data_.__write_time_ == file_time_type::min())
0438         __handle_error("in directory_entry::last_write_time", __ec, make_error_code(errc::value_too_large));
0439       return __data_.__write_time_;
0440     }
0441     }
0442     __libcpp_unreachable();
0443   }
0444 
0445 private:
0446   _Path __p_;
0447   __cached_data __data_;
0448 };
0449 
0450 class __dir_element_proxy {
0451 public:
0452   inline _LIBCPP_HIDE_FROM_ABI directory_entry operator*() { return std::move(__elem_); }
0453 
0454 private:
0455   friend class directory_iterator;
0456   friend class recursive_directory_iterator;
0457   _LIBCPP_HIDE_FROM_ABI explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
0458   _LIBCPP_HIDE_FROM_ABI __dir_element_proxy(__dir_element_proxy&& __o) : __elem_(std::move(__o.__elem_)) {}
0459   directory_entry __elem_;
0460 };
0461 
0462 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
0463 
0464 _LIBCPP_END_NAMESPACE_FILESYSTEM
0465 
0466 #endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
0467 
0468 _LIBCPP_POP_MACROS
0469 
0470 #endif // _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H