xref: /freebsd-src/contrib/llvm-project/libcxx/src/filesystem/directory_entry.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include <__config>
10*06c3fb27SDimitry Andric #include <cstdint>
11*06c3fb27SDimitry Andric #include <filesystem>
12*06c3fb27SDimitry Andric #include <system_error>
13*06c3fb27SDimitry Andric 
14*06c3fb27SDimitry Andric #include "file_descriptor.h"
15*06c3fb27SDimitry Andric #include "posix_compat.h"
16*06c3fb27SDimitry Andric #include "time_utils.h"
17*06c3fb27SDimitry Andric 
18*06c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
19*06c3fb27SDimitry Andric 
20*06c3fb27SDimitry Andric error_code directory_entry::__do_refresh() noexcept {
21*06c3fb27SDimitry Andric   __data_.__reset();
22*06c3fb27SDimitry Andric   error_code failure_ec;
23*06c3fb27SDimitry Andric 
24*06c3fb27SDimitry Andric   detail::StatT full_st;
25*06c3fb27SDimitry Andric   file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
26*06c3fb27SDimitry Andric   if (!status_known(st)) {
27*06c3fb27SDimitry Andric     __data_.__reset();
28*06c3fb27SDimitry Andric     return failure_ec;
29*06c3fb27SDimitry Andric   }
30*06c3fb27SDimitry Andric 
31*06c3fb27SDimitry Andric   if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
32*06c3fb27SDimitry Andric     __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
33*06c3fb27SDimitry Andric     __data_.__type_ = st.type();
34*06c3fb27SDimitry Andric     __data_.__non_sym_perms_ = st.permissions();
35*06c3fb27SDimitry Andric   } else { // we have a symlink
36*06c3fb27SDimitry Andric     __data_.__sym_perms_ = st.permissions();
37*06c3fb27SDimitry Andric     // Get the information about the linked entity.
38*06c3fb27SDimitry Andric     // Ignore errors from stat, since we don't want errors regarding symlink
39*06c3fb27SDimitry Andric     // resolution to be reported to the user.
40*06c3fb27SDimitry Andric     error_code ignored_ec;
41*06c3fb27SDimitry Andric     st = detail::posix_stat(__p_, full_st, &ignored_ec);
42*06c3fb27SDimitry Andric 
43*06c3fb27SDimitry Andric     __data_.__type_ = st.type();
44*06c3fb27SDimitry Andric     __data_.__non_sym_perms_ = st.permissions();
45*06c3fb27SDimitry Andric 
46*06c3fb27SDimitry Andric     // If we failed to resolve the link, then only partially populate the
47*06c3fb27SDimitry Andric     // cache.
48*06c3fb27SDimitry Andric     if (!status_known(st)) {
49*06c3fb27SDimitry Andric       __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
50*06c3fb27SDimitry Andric       return error_code{};
51*06c3fb27SDimitry Andric     }
52*06c3fb27SDimitry Andric     // Otherwise, we resolved the link, potentially as not existing.
53*06c3fb27SDimitry Andric     // That's OK.
54*06c3fb27SDimitry Andric     __data_.__cache_type_ = directory_entry::_RefreshSymlink;
55*06c3fb27SDimitry Andric   }
56*06c3fb27SDimitry Andric 
57*06c3fb27SDimitry Andric   if (_VSTD_FS::is_regular_file(st))
58*06c3fb27SDimitry Andric     __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
59*06c3fb27SDimitry Andric 
60*06c3fb27SDimitry Andric   if (_VSTD_FS::exists(st)) {
61*06c3fb27SDimitry Andric     __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
62*06c3fb27SDimitry Andric 
63*06c3fb27SDimitry Andric     // Attempt to extract the mtime, and fail if it's not representable using
64*06c3fb27SDimitry Andric     // file_time_type. For now we ignore the error, as we'll report it when
65*06c3fb27SDimitry Andric     // the value is actually used.
66*06c3fb27SDimitry Andric     error_code ignored_ec;
67*06c3fb27SDimitry Andric     __data_.__write_time_ =
68*06c3fb27SDimitry Andric         detail::__extract_last_write_time(__p_, full_st, &ignored_ec);
69*06c3fb27SDimitry Andric   }
70*06c3fb27SDimitry Andric 
71*06c3fb27SDimitry Andric   return failure_ec;
72*06c3fb27SDimitry Andric }
73*06c3fb27SDimitry Andric 
74*06c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_FILESYSTEM
75