brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.2 KiB · 3513a49 Raw
467 lines · c
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H11#define _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H12 13#include <__chrono/time_point.h>14#include <__compare/ordering.h>15#include <__config>16#include <__filesystem/file_status.h>17#include <__filesystem/file_time_type.h>18#include <__filesystem/file_type.h>19#include <__filesystem/filesystem_error.h>20#include <__filesystem/operations.h>21#include <__filesystem/path.h>22#include <__filesystem/perms.h>23#include <__fwd/ostream.h>24#include <__system_error/errc.h>25#include <__system_error/error_category.h>26#include <__system_error/error_code.h>27#include <__system_error/error_condition.h>28#include <__utility/move.h>29#include <__utility/unreachable.h>30#include <cstdint>31 32#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)33#  pragma GCC system_header34#endif35 36_LIBCPP_PUSH_MACROS37#include <__undef_macros>38 39#if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM40 41_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM42 43class directory_entry {44  typedef filesystem::path _Path;45 46public:47  // constructors and destructors48  _LIBCPP_HIDE_FROM_ABI directory_entry() noexcept                  = default;49  _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry const&)     = default;50  _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry&&) noexcept = default;51 52  _LIBCPP_HIDE_FROM_ABI explicit directory_entry(_Path const& __p) : __p_(__p) {53    error_code __ec;54    __refresh(&__ec);55  }56 57  _LIBCPP_HIDE_FROM_ABI directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) { __refresh(&__ec); }58 59  _LIBCPP_HIDE_FROM_ABI ~directory_entry() {}60 61  _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry const&)     = default;62  _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry&&) noexcept = default;63 64  _LIBCPP_HIDE_FROM_ABI void assign(_Path const& __p) {65    __p_ = __p;66    error_code __ec;67    __refresh(&__ec);68  }69 70  _LIBCPP_HIDE_FROM_ABI void assign(_Path const& __p, error_code& __ec) {71    __p_ = __p;72    __refresh(&__ec);73  }74 75  _LIBCPP_HIDE_FROM_ABI void replace_filename(_Path const& __p) {76    __p_.replace_filename(__p);77    error_code __ec;78    __refresh(&__ec);79  }80 81  _LIBCPP_HIDE_FROM_ABI void replace_filename(_Path const& __p, error_code& __ec) {82    __p_ = __p_.parent_path() / __p;83    __refresh(&__ec);84  }85 86  _LIBCPP_HIDE_FROM_ABI void refresh() { __refresh(); }87 88  _LIBCPP_HIDE_FROM_ABI void refresh(error_code& __ec) noexcept { __refresh(&__ec); }89 90  _LIBCPP_HIDE_FROM_ABI _Path const& path() const noexcept { return __p_; }91 92  _LIBCPP_HIDE_FROM_ABI operator const _Path&() const noexcept { return __p_; }93 94  _LIBCPP_HIDE_FROM_ABI bool exists() const { return filesystem::exists(file_status{__get_ft()}); }95 96  _LIBCPP_HIDE_FROM_ABI bool exists(error_code& __ec) const noexcept {97    return filesystem::exists(file_status{__get_ft(&__ec)});98  }99 100  _LIBCPP_HIDE_FROM_ABI bool is_block_file() const { return __get_ft() == file_type::block; }101 102  _LIBCPP_HIDE_FROM_ABI bool is_block_file(error_code& __ec) const noexcept {103    return __get_ft(&__ec) == file_type::block;104  }105 106  _LIBCPP_HIDE_FROM_ABI bool is_character_file() const { return __get_ft() == file_type::character; }107 108  _LIBCPP_HIDE_FROM_ABI bool is_character_file(error_code& __ec) const noexcept {109    return __get_ft(&__ec) == file_type::character;110  }111 112  _LIBCPP_HIDE_FROM_ABI bool is_directory() const { return __get_ft() == file_type::directory; }113 114  _LIBCPP_HIDE_FROM_ABI bool is_directory(error_code& __ec) const noexcept {115    return __get_ft(&__ec) == file_type::directory;116  }117 118  _LIBCPP_HIDE_FROM_ABI bool is_fifo() const { return __get_ft() == file_type::fifo; }119 120  _LIBCPP_HIDE_FROM_ABI bool is_fifo(error_code& __ec) const noexcept { return __get_ft(&__ec) == file_type::fifo; }121 122  _LIBCPP_HIDE_FROM_ABI bool is_other() const { return filesystem::is_other(file_status{__get_ft()}); }123 124  _LIBCPP_HIDE_FROM_ABI bool is_other(error_code& __ec) const noexcept {125    return filesystem::is_other(file_status{__get_ft(&__ec)});126  }127 128  _LIBCPP_HIDE_FROM_ABI bool is_regular_file() const { return __get_ft() == file_type::regular; }129 130  _LIBCPP_HIDE_FROM_ABI bool is_regular_file(error_code& __ec) const noexcept {131    return __get_ft(&__ec) == file_type::regular;132  }133 134  _LIBCPP_HIDE_FROM_ABI bool is_socket() const { return __get_ft() == file_type::socket; }135 136  _LIBCPP_HIDE_FROM_ABI bool is_socket(error_code& __ec) const noexcept { return __get_ft(&__ec) == file_type::socket; }137 138  _LIBCPP_HIDE_FROM_ABI bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }139 140  _LIBCPP_HIDE_FROM_ABI bool is_symlink(error_code& __ec) const noexcept {141    return __get_sym_ft(&__ec) == file_type::symlink;142  }143  _LIBCPP_HIDE_FROM_ABI uintmax_t file_size() const { return __get_size(); }144 145  _LIBCPP_HIDE_FROM_ABI uintmax_t file_size(error_code& __ec) const noexcept { return __get_size(&__ec); }146 147  _LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count() const { return __get_nlink(); }148 149  _LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count(error_code& __ec) const noexcept { return __get_nlink(&__ec); }150 151  _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time() const { return __get_write_time(); }152 153  _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(error_code& __ec) const noexcept {154    return __get_write_time(&__ec);155  }156 157  _LIBCPP_HIDE_FROM_ABI file_status status() const { return __get_status(); }158 159  _LIBCPP_HIDE_FROM_ABI file_status status(error_code& __ec) const noexcept { return __get_status(&__ec); }160 161  _LIBCPP_HIDE_FROM_ABI file_status symlink_status() const { return __get_symlink_status(); }162 163  _LIBCPP_HIDE_FROM_ABI file_status symlink_status(error_code& __ec) const noexcept {164    return __get_symlink_status(&__ec);165  }166 167  _LIBCPP_HIDE_FROM_ABI bool operator==(directory_entry const& __rhs) const noexcept { return __p_ == __rhs.__p_; }168 169#  if _LIBCPP_STD_VER <= 17170  _LIBCPP_HIDE_FROM_ABI bool operator!=(directory_entry const& __rhs) const noexcept { return __p_ != __rhs.__p_; }171 172  _LIBCPP_HIDE_FROM_ABI bool operator<(directory_entry const& __rhs) const noexcept { return __p_ < __rhs.__p_; }173 174  _LIBCPP_HIDE_FROM_ABI bool operator<=(directory_entry const& __rhs) const noexcept { return __p_ <= __rhs.__p_; }175 176  _LIBCPP_HIDE_FROM_ABI bool operator>(directory_entry const& __rhs) const noexcept { return __p_ > __rhs.__p_; }177 178  _LIBCPP_HIDE_FROM_ABI bool operator>=(directory_entry const& __rhs) const noexcept { return __p_ >= __rhs.__p_; }179 180#  else // _LIBCPP_STD_VER <= 17181 182  _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const directory_entry& __rhs) const noexcept {183    return __p_ <=> __rhs.__p_;184  }185 186#  endif // _LIBCPP_STD_VER <= 17187 188  template <class _CharT, class _Traits>189  _LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&190  operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) {191    return __os << __d.path();192  }193 194private:195  friend class directory_iterator;196  friend class recursive_directory_iterator;197  friend class _LIBCPP_HIDDEN __dir_stream;198 199  enum _CacheType : unsigned char {200    _Empty,201    _IterSymlink,202    _IterNonSymlink,203    _RefreshSymlink,204    _RefreshSymlinkUnresolved,205    _RefreshNonSymlink,206    _IterCachedSymlink,207    _IterCachedNonSymlink208  };209 210  struct __cached_data {211    uintmax_t __size_;212    uintmax_t __nlink_;213    file_time_type __write_time_;214    perms __sym_perms_;215    perms __non_sym_perms_;216    file_type __type_;217    _CacheType __cache_type_;218 219    _LIBCPP_HIDE_FROM_ABI __cached_data() noexcept { __reset(); }220 221    _LIBCPP_HIDE_FROM_ABI void __reset() {222      __cache_type_ = _Empty;223      __type_       = file_type::none;224      __sym_perms_ = __non_sym_perms_ = perms::unknown;225      __size_ = __nlink_ = uintmax_t(-1);226      __write_time_      = file_time_type::min();227    }228  };229 230  _LIBCPP_HIDE_FROM_ABI static __cached_data __create_iter_result(file_type __ft) {231    __cached_data __data;232    __data.__type_       = __ft;233    __data.__cache_type_ = [&]() {234      switch (__ft) {235      case file_type::none:236        return _Empty;237      case file_type::symlink:238        return _IterSymlink;239      default:240        return _IterNonSymlink;241      }242    }();243    return __data;244  }245 246  _LIBCPP_HIDE_FROM_ABI static __cached_data247  __create_iter_cached_result(file_type __ft, uintmax_t __size, perms __perm, file_time_type __write_time) {248    __cached_data __data;249    __data.__type_       = __ft;250    __data.__size_       = __size;251    __data.__write_time_ = __write_time;252    if (__ft == file_type::symlink)253      __data.__sym_perms_ = __perm;254    else255      __data.__non_sym_perms_ = __perm;256    __data.__cache_type_ = [&]() {257      switch (__ft) {258      case file_type::none:259        return _Empty;260      case file_type::symlink:261        return _IterCachedSymlink;262      default:263        return _IterCachedNonSymlink;264      }265    }();266    return __data;267  }268 269  _LIBCPP_HIDE_FROM_ABI void __assign_iter_entry(_Path&& __p, __cached_data __dt) {270    __p_    = std::move(__p);271    __data_ = __dt;272  }273 274  _LIBCPP_EXPORTED_FROM_ABI error_code __do_refresh() noexcept;275 276  _LIBCPP_HIDE_FROM_ABI static bool __is_dne_error(error_code const& __ec) {277    return !__ec || __ec == errc::no_such_file_or_directory || __ec == errc::not_a_directory;278  }279 280  _LIBCPP_HIDE_FROM_ABI void281  __handle_error(const char* __msg, error_code* __dest_ec, error_code const& __ec, bool __allow_dne = false) const {282    if (__dest_ec) {283      *__dest_ec = __ec;284      return;285    }286    if (__ec && (!__allow_dne || !__is_dne_error(__ec)))287      filesystem::__throw_filesystem_error(__msg, __p_, __ec);288  }289 290  _LIBCPP_HIDE_FROM_ABI void __refresh(error_code* __ec = nullptr) {291    __handle_error("in directory_entry::refresh",292                   __ec,293                   __do_refresh(),294                   /*allow_dne*/ true);295  }296 297  _LIBCPP_HIDE_FROM_ABI file_type __get_sym_ft(error_code* __ec = nullptr) const {298    switch (__data_.__cache_type_) {299    case _Empty:300      return __symlink_status(__p_, __ec).type();301    case _IterSymlink:302    case _IterCachedSymlink:303    case _RefreshSymlink:304    case _RefreshSymlinkUnresolved:305      if (__ec)306        __ec->clear();307      return file_type::symlink;308    case _IterCachedNonSymlink:309    case _IterNonSymlink:310    case _RefreshNonSymlink: {311      file_status __st(__data_.__type_);312      if (__ec && !filesystem::exists(__st))313        *__ec = make_error_code(errc::no_such_file_or_directory);314      else if (__ec)315        __ec->clear();316      return __data_.__type_;317    }318    }319    __libcpp_unreachable();320  }321 322  _LIBCPP_HIDE_FROM_ABI file_type __get_ft(error_code* __ec = nullptr) const {323    switch (__data_.__cache_type_) {324    case _Empty:325    case _IterSymlink:326    case _IterCachedSymlink:327    case _RefreshSymlinkUnresolved:328      return __status(__p_, __ec).type();329    case _IterCachedNonSymlink:330    case _IterNonSymlink:331    case _RefreshNonSymlink:332    case _RefreshSymlink: {333      file_status __st(__data_.__type_);334      if (__ec && !filesystem::exists(__st))335        *__ec = make_error_code(errc::no_such_file_or_directory);336      else if (__ec)337        __ec->clear();338      return __data_.__type_;339    }340    }341    __libcpp_unreachable();342  }343 344  _LIBCPP_HIDE_FROM_ABI file_status __get_status(error_code* __ec = nullptr) const {345    switch (__data_.__cache_type_) {346    case _Empty:347    case _IterNonSymlink:348    case _IterSymlink:349    case _IterCachedSymlink:350    case _RefreshSymlinkUnresolved:351      return __status(__p_, __ec);352    case _IterCachedNonSymlink:353    case _RefreshNonSymlink:354    case _RefreshSymlink:355      return file_status(__get_ft(__ec), __data_.__non_sym_perms_);356    }357    __libcpp_unreachable();358  }359 360  _LIBCPP_HIDE_FROM_ABI file_status __get_symlink_status(error_code* __ec = nullptr) const {361    switch (__data_.__cache_type_) {362    case _Empty:363    case _IterNonSymlink:364    case _IterSymlink:365      return __symlink_status(__p_, __ec);366    case _IterCachedNonSymlink:367    case _RefreshNonSymlink:368      return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);369    case _IterCachedSymlink:370    case _RefreshSymlink:371    case _RefreshSymlinkUnresolved:372      return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);373    }374    __libcpp_unreachable();375  }376 377  _LIBCPP_HIDE_FROM_ABI uintmax_t __get_size(error_code* __ec = nullptr) const {378    switch (__data_.__cache_type_) {379    case _Empty:380    case _IterNonSymlink:381    case _IterSymlink:382    case _IterCachedSymlink:383    case _RefreshSymlinkUnresolved:384      return filesystem::__file_size(__p_, __ec);385    case _IterCachedNonSymlink:386    case _RefreshSymlink:387    case _RefreshNonSymlink: {388      error_code __m_ec;389      file_status __st(__get_ft(&__m_ec));390      __handle_error("in directory_entry::file_size", __ec, __m_ec);391      if (filesystem::exists(__st) && !filesystem::is_regular_file(__st)) {392        errc __err_kind = filesystem::is_directory(__st) ? errc::is_a_directory : errc::not_supported;393        __handle_error("in directory_entry::file_size", __ec, make_error_code(__err_kind));394      }395      return __data_.__size_;396    }397    }398    __libcpp_unreachable();399  }400 401  _LIBCPP_HIDE_FROM_ABI uintmax_t __get_nlink(error_code* __ec = nullptr) const {402    switch (__data_.__cache_type_) {403    case _Empty:404    case _IterNonSymlink:405    case _IterSymlink:406    case _IterCachedNonSymlink:407    case _IterCachedSymlink:408    case _RefreshSymlinkUnresolved:409      return filesystem::__hard_link_count(__p_, __ec);410    case _RefreshSymlink:411    case _RefreshNonSymlink: {412      error_code __m_ec;413      (void)__get_ft(&__m_ec);414      __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);415      return __data_.__nlink_;416    }417    }418    __libcpp_unreachable();419  }420 421  _LIBCPP_HIDE_FROM_ABI file_time_type __get_write_time(error_code* __ec = nullptr) const {422    switch (__data_.__cache_type_) {423    case _Empty:424    case _IterNonSymlink:425    case _IterSymlink:426    case _IterCachedSymlink:427    case _RefreshSymlinkUnresolved:428      return filesystem::__last_write_time(__p_, __ec);429    case _IterCachedNonSymlink:430    case _RefreshSymlink:431    case _RefreshNonSymlink: {432      error_code __m_ec;433      file_status __st(__get_ft(&__m_ec));434      __handle_error("in directory_entry::last_write_time", __ec, __m_ec);435      if (filesystem::exists(__st) && __data_.__write_time_ == file_time_type::min())436        __handle_error("in directory_entry::last_write_time", __ec, make_error_code(errc::value_too_large));437      return __data_.__write_time_;438    }439    }440    __libcpp_unreachable();441  }442 443private:444  _Path __p_;445  __cached_data __data_;446};447 448class __dir_element_proxy {449public:450  inline _LIBCPP_HIDE_FROM_ABI directory_entry operator*() { return std::move(__elem_); }451 452private:453  friend class directory_iterator;454  friend class recursive_directory_iterator;455  _LIBCPP_HIDE_FROM_ABI explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}456  _LIBCPP_HIDE_FROM_ABI __dir_element_proxy(__dir_element_proxy&& __o) : __elem_(std::move(__o.__elem_)) {}457  directory_entry __elem_;458};459 460_LIBCPP_END_NAMESPACE_FILESYSTEM461 462#endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM463 464_LIBCPP_POP_MACROS465 466#endif // _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H467