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