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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <__config>
10#include <cstdint>
11#include <filesystem>
12#include <system_error>
13
14#include "file_descriptor.h"
15#include "posix_compat.h"
16#include "time_utils.h"
17
18_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
19_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
20
21error_code directory_entry::__do_refresh() noexcept {
22 __data_.__reset();
23 error_code failure_ec;
24
25 detail::StatT full_st;
26 file_status st = detail::posix_lstat(p: __p_, path_stat&: full_st, ec: &failure_ec);
27 if (!status_known(s: st)) {
28 __data_.__reset();
29 return failure_ec;
30 }
31
32 if (!filesystem::exists(s: st) || !filesystem::is_symlink(s: st)) {
33 __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
34 __data_.__type_ = st.type();
35 __data_.__non_sym_perms_ = st.permissions();
36 } else { // we have a symlink
37 __data_.__sym_perms_ = st.permissions();
38 // Get the information about the linked entity.
39 // Ignore errors from stat, since we don't want errors regarding symlink
40 // resolution to be reported to the user.
41 error_code ignored_ec;
42 st = detail::posix_stat(p: __p_, path_stat&: full_st, ec: &ignored_ec);
43
44 __data_.__type_ = st.type();
45 __data_.__non_sym_perms_ = st.permissions();
46
47 // If we failed to resolve the link, then only partially populate the
48 // cache.
49 if (!status_known(s: st)) {
50 __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
51 return error_code{};
52 }
53 // Otherwise, we resolved the link, potentially as not existing.
54 // That's OK.
55 __data_.__cache_type_ = directory_entry::_RefreshSymlink;
56 }
57
58 if (filesystem::is_regular_file(s: st))
59 __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
60
61 if (filesystem::exists(s: st)) {
62 __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
63
64 // Attempt to extract the mtime, and fail if it's not representable using
65 // file_time_type. For now we ignore the error, as we'll report it when
66 // the value is actually used.
67 error_code ignored_ec;
68 __data_.__write_time_ = detail::__extract_last_write_time(p: __p_, st: full_st, ec: &ignored_ec);
69 }
70
71 return failure_ec;
72}
73
74_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
75_LIBCPP_END_NAMESPACE_FILESYSTEM
76