Path: blob/main/contrib/llvm-project/libcxx/include/__filesystem/directory_entry.h
35262 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H10#define _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H1112#include <__chrono/time_point.h>13#include <__compare/ordering.h>14#include <__config>15#include <__filesystem/file_status.h>16#include <__filesystem/file_time_type.h>17#include <__filesystem/file_type.h>18#include <__filesystem/filesystem_error.h>19#include <__filesystem/operations.h>20#include <__filesystem/path.h>21#include <__filesystem/perms.h>22#include <__system_error/errc.h>23#include <__system_error/error_code.h>24#include <__utility/move.h>25#include <__utility/unreachable.h>26#include <cstdint>2728#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)29# pragma GCC system_header30#endif3132_LIBCPP_PUSH_MACROS33#include <__undef_macros>3435#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM)3637_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM3839_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH4041class directory_entry {42typedef filesystem::path _Path;4344public:45// constructors and destructors46_LIBCPP_HIDE_FROM_ABI directory_entry() noexcept = default;47_LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry const&) = default;48_LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry&&) noexcept = default;4950_LIBCPP_HIDE_FROM_ABI explicit directory_entry(_Path const& __p) : __p_(__p) {51error_code __ec;52__refresh(&__ec);53}5455_LIBCPP_HIDE_FROM_ABI directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) { __refresh(&__ec); }5657_LIBCPP_HIDE_FROM_ABI ~directory_entry() {}5859_LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry const&) = default;60_LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry&&) noexcept = default;6162_LIBCPP_HIDE_FROM_ABI void assign(_Path const& __p) {63__p_ = __p;64error_code __ec;65__refresh(&__ec);66}6768_LIBCPP_HIDE_FROM_ABI void assign(_Path const& __p, error_code& __ec) {69__p_ = __p;70__refresh(&__ec);71}7273_LIBCPP_HIDE_FROM_ABI void replace_filename(_Path const& __p) {74__p_.replace_filename(__p);75error_code __ec;76__refresh(&__ec);77}7879_LIBCPP_HIDE_FROM_ABI void replace_filename(_Path const& __p, error_code& __ec) {80__p_ = __p_.parent_path() / __p;81__refresh(&__ec);82}8384_LIBCPP_HIDE_FROM_ABI void refresh() { __refresh(); }8586_LIBCPP_HIDE_FROM_ABI void refresh(error_code& __ec) noexcept { __refresh(&__ec); }8788_LIBCPP_HIDE_FROM_ABI _Path const& path() const noexcept { return __p_; }8990_LIBCPP_HIDE_FROM_ABI operator const _Path&() const noexcept { return __p_; }9192_LIBCPP_HIDE_FROM_ABI bool exists() const { return filesystem::exists(file_status{__get_ft()}); }9394_LIBCPP_HIDE_FROM_ABI bool exists(error_code& __ec) const noexcept {95return filesystem::exists(file_status{__get_ft(&__ec)});96}9798_LIBCPP_HIDE_FROM_ABI bool is_block_file() const { return __get_ft() == file_type::block; }99100_LIBCPP_HIDE_FROM_ABI bool is_block_file(error_code& __ec) const noexcept {101return __get_ft(&__ec) == file_type::block;102}103104_LIBCPP_HIDE_FROM_ABI bool is_character_file() const { return __get_ft() == file_type::character; }105106_LIBCPP_HIDE_FROM_ABI bool is_character_file(error_code& __ec) const noexcept {107return __get_ft(&__ec) == file_type::character;108}109110_LIBCPP_HIDE_FROM_ABI bool is_directory() const { return __get_ft() == file_type::directory; }111112_LIBCPP_HIDE_FROM_ABI bool is_directory(error_code& __ec) const noexcept {113return __get_ft(&__ec) == file_type::directory;114}115116_LIBCPP_HIDE_FROM_ABI bool is_fifo() const { return __get_ft() == file_type::fifo; }117118_LIBCPP_HIDE_FROM_ABI bool is_fifo(error_code& __ec) const noexcept { return __get_ft(&__ec) == file_type::fifo; }119120_LIBCPP_HIDE_FROM_ABI bool is_other() const { return filesystem::is_other(file_status{__get_ft()}); }121122_LIBCPP_HIDE_FROM_ABI bool is_other(error_code& __ec) const noexcept {123return filesystem::is_other(file_status{__get_ft(&__ec)});124}125126_LIBCPP_HIDE_FROM_ABI bool is_regular_file() const { return __get_ft() == file_type::regular; }127128_LIBCPP_HIDE_FROM_ABI bool is_regular_file(error_code& __ec) const noexcept {129return __get_ft(&__ec) == file_type::regular;130}131132_LIBCPP_HIDE_FROM_ABI bool is_socket() const { return __get_ft() == file_type::socket; }133134_LIBCPP_HIDE_FROM_ABI bool is_socket(error_code& __ec) const noexcept { return __get_ft(&__ec) == file_type::socket; }135136_LIBCPP_HIDE_FROM_ABI bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }137138_LIBCPP_HIDE_FROM_ABI bool is_symlink(error_code& __ec) const noexcept {139return __get_sym_ft(&__ec) == file_type::symlink;140}141_LIBCPP_HIDE_FROM_ABI uintmax_t file_size() const { return __get_size(); }142143_LIBCPP_HIDE_FROM_ABI uintmax_t file_size(error_code& __ec) const noexcept { return __get_size(&__ec); }144145_LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count() const { return __get_nlink(); }146147_LIBCPP_HIDE_FROM_ABI uintmax_t hard_link_count(error_code& __ec) const noexcept { return __get_nlink(&__ec); }148149_LIBCPP_HIDE_FROM_ABI file_time_type last_write_time() const { return __get_write_time(); }150151_LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(error_code& __ec) const noexcept {152return __get_write_time(&__ec);153}154155_LIBCPP_HIDE_FROM_ABI file_status status() const { return __get_status(); }156157_LIBCPP_HIDE_FROM_ABI file_status status(error_code& __ec) const noexcept { return __get_status(&__ec); }158159_LIBCPP_HIDE_FROM_ABI file_status symlink_status() const { return __get_symlink_status(); }160161_LIBCPP_HIDE_FROM_ABI file_status symlink_status(error_code& __ec) const noexcept {162return __get_symlink_status(&__ec);163}164165_LIBCPP_HIDE_FROM_ABI bool operator==(directory_entry const& __rhs) const noexcept { return __p_ == __rhs.__p_; }166167# if _LIBCPP_STD_VER <= 17168_LIBCPP_HIDE_FROM_ABI bool operator!=(directory_entry const& __rhs) const noexcept { return __p_ != __rhs.__p_; }169170_LIBCPP_HIDE_FROM_ABI bool operator<(directory_entry const& __rhs) const noexcept { return __p_ < __rhs.__p_; }171172_LIBCPP_HIDE_FROM_ABI bool operator<=(directory_entry const& __rhs) const noexcept { return __p_ <= __rhs.__p_; }173174_LIBCPP_HIDE_FROM_ABI bool operator>(directory_entry const& __rhs) const noexcept { return __p_ > __rhs.__p_; }175176_LIBCPP_HIDE_FROM_ABI bool operator>=(directory_entry const& __rhs) const noexcept { return __p_ >= __rhs.__p_; }177178# else // _LIBCPP_STD_VER <= 17179180_LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const directory_entry& __rhs) const noexcept {181return __p_ <=> __rhs.__p_;182}183184# endif // _LIBCPP_STD_VER <= 17185186template <class _CharT, class _Traits>187_LIBCPP_HIDE_FROM_ABI friend basic_ostream<_CharT, _Traits>&188operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) {189return __os << __d.path();190}191192private:193friend class directory_iterator;194friend class recursive_directory_iterator;195friend class _LIBCPP_HIDDEN __dir_stream;196197enum _CacheType : unsigned char {198_Empty,199_IterSymlink,200_IterNonSymlink,201_RefreshSymlink,202_RefreshSymlinkUnresolved,203_RefreshNonSymlink204};205206struct __cached_data {207uintmax_t __size_;208uintmax_t __nlink_;209file_time_type __write_time_;210perms __sym_perms_;211perms __non_sym_perms_;212file_type __type_;213_CacheType __cache_type_;214215_LIBCPP_HIDE_FROM_ABI __cached_data() noexcept { __reset(); }216217_LIBCPP_HIDE_FROM_ABI void __reset() {218__cache_type_ = _Empty;219__type_ = file_type::none;220__sym_perms_ = __non_sym_perms_ = perms::unknown;221__size_ = __nlink_ = uintmax_t(-1);222__write_time_ = file_time_type::min();223}224};225226_LIBCPP_HIDE_FROM_ABI static __cached_data __create_iter_result(file_type __ft) {227__cached_data __data;228__data.__type_ = __ft;229__data.__cache_type_ = [&]() {230switch (__ft) {231case file_type::none:232return _Empty;233case file_type::symlink:234return _IterSymlink;235default:236return _IterNonSymlink;237}238}();239return __data;240}241242_LIBCPP_HIDE_FROM_ABI void __assign_iter_entry(_Path&& __p, __cached_data __dt) {243__p_ = std::move(__p);244__data_ = __dt;245}246247_LIBCPP_EXPORTED_FROM_ABI error_code __do_refresh() noexcept;248249_LIBCPP_HIDE_FROM_ABI static bool __is_dne_error(error_code const& __ec) {250if (!__ec)251return true;252switch (static_cast<errc>(__ec.value())) {253case errc::no_such_file_or_directory:254case errc::not_a_directory:255return true;256default:257return false;258}259}260261_LIBCPP_HIDE_FROM_ABI void262__handle_error(const char* __msg, error_code* __dest_ec, error_code const& __ec, bool __allow_dne = false) const {263if (__dest_ec) {264*__dest_ec = __ec;265return;266}267if (__ec && (!__allow_dne || !__is_dne_error(__ec)))268__throw_filesystem_error(__msg, __p_, __ec);269}270271_LIBCPP_HIDE_FROM_ABI void __refresh(error_code* __ec = nullptr) {272__handle_error("in directory_entry::refresh",273__ec,274__do_refresh(),275/*allow_dne*/ true);276}277278_LIBCPP_HIDE_FROM_ABI file_type __get_sym_ft(error_code* __ec = nullptr) const {279switch (__data_.__cache_type_) {280case _Empty:281return __symlink_status(__p_, __ec).type();282case _IterSymlink:283case _RefreshSymlink:284case _RefreshSymlinkUnresolved:285if (__ec)286__ec->clear();287return file_type::symlink;288case _IterNonSymlink:289case _RefreshNonSymlink:290file_status __st(__data_.__type_);291if (__ec && !filesystem::exists(__st))292*__ec = make_error_code(errc::no_such_file_or_directory);293else if (__ec)294__ec->clear();295return __data_.__type_;296}297__libcpp_unreachable();298}299300_LIBCPP_HIDE_FROM_ABI file_type __get_ft(error_code* __ec = nullptr) const {301switch (__data_.__cache_type_) {302case _Empty:303case _IterSymlink:304case _RefreshSymlinkUnresolved:305return __status(__p_, __ec).type();306case _IterNonSymlink:307case _RefreshNonSymlink:308case _RefreshSymlink: {309file_status __st(__data_.__type_);310if (__ec && !filesystem::exists(__st))311*__ec = make_error_code(errc::no_such_file_or_directory);312else if (__ec)313__ec->clear();314return __data_.__type_;315}316}317__libcpp_unreachable();318}319320_LIBCPP_HIDE_FROM_ABI file_status __get_status(error_code* __ec = nullptr) const {321switch (__data_.__cache_type_) {322case _Empty:323case _IterNonSymlink:324case _IterSymlink:325case _RefreshSymlinkUnresolved:326return __status(__p_, __ec);327case _RefreshNonSymlink:328case _RefreshSymlink:329return file_status(__get_ft(__ec), __data_.__non_sym_perms_);330}331__libcpp_unreachable();332}333334_LIBCPP_HIDE_FROM_ABI file_status __get_symlink_status(error_code* __ec = nullptr) const {335switch (__data_.__cache_type_) {336case _Empty:337case _IterNonSymlink:338case _IterSymlink:339return __symlink_status(__p_, __ec);340case _RefreshNonSymlink:341return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);342case _RefreshSymlink:343case _RefreshSymlinkUnresolved:344return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);345}346__libcpp_unreachable();347}348349_LIBCPP_HIDE_FROM_ABI uintmax_t __get_size(error_code* __ec = nullptr) const {350switch (__data_.__cache_type_) {351case _Empty:352case _IterNonSymlink:353case _IterSymlink:354case _RefreshSymlinkUnresolved:355return filesystem::__file_size(__p_, __ec);356case _RefreshSymlink:357case _RefreshNonSymlink: {358error_code __m_ec;359file_status __st(__get_ft(&__m_ec));360__handle_error("in directory_entry::file_size", __ec, __m_ec);361if (filesystem::exists(__st) && !filesystem::is_regular_file(__st)) {362errc __err_kind = filesystem::is_directory(__st) ? errc::is_a_directory : errc::not_supported;363__handle_error("in directory_entry::file_size", __ec, make_error_code(__err_kind));364}365return __data_.__size_;366}367}368__libcpp_unreachable();369}370371_LIBCPP_HIDE_FROM_ABI uintmax_t __get_nlink(error_code* __ec = nullptr) const {372switch (__data_.__cache_type_) {373case _Empty:374case _IterNonSymlink:375case _IterSymlink:376case _RefreshSymlinkUnresolved:377return filesystem::__hard_link_count(__p_, __ec);378case _RefreshSymlink:379case _RefreshNonSymlink: {380error_code __m_ec;381(void)__get_ft(&__m_ec);382__handle_error("in directory_entry::hard_link_count", __ec, __m_ec);383return __data_.__nlink_;384}385}386__libcpp_unreachable();387}388389_LIBCPP_HIDE_FROM_ABI file_time_type __get_write_time(error_code* __ec = nullptr) const {390switch (__data_.__cache_type_) {391case _Empty:392case _IterNonSymlink:393case _IterSymlink:394case _RefreshSymlinkUnresolved:395return filesystem::__last_write_time(__p_, __ec);396case _RefreshSymlink:397case _RefreshNonSymlink: {398error_code __m_ec;399file_status __st(__get_ft(&__m_ec));400__handle_error("in directory_entry::last_write_time", __ec, __m_ec);401if (filesystem::exists(__st) && __data_.__write_time_ == file_time_type::min())402__handle_error("in directory_entry::last_write_time", __ec, make_error_code(errc::value_too_large));403return __data_.__write_time_;404}405}406__libcpp_unreachable();407}408409private:410_Path __p_;411__cached_data __data_;412};413414class __dir_element_proxy {415public:416inline _LIBCPP_HIDE_FROM_ABI directory_entry operator*() { return std::move(__elem_); }417418private:419friend class directory_iterator;420friend class recursive_directory_iterator;421_LIBCPP_HIDE_FROM_ABI explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}422_LIBCPP_HIDE_FROM_ABI __dir_element_proxy(__dir_element_proxy&& __o) : __elem_(std::move(__o.__elem_)) {}423directory_entry __elem_;424};425426_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP427428_LIBCPP_END_NAMESPACE_FILESYSTEM429430#endif // _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM)431432_LIBCPP_POP_MACROS433434#endif // _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H435436437