aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
diff options
context:
space:
mode:
authormikhnenko <mikhnenko@yandex-team.com>2025-01-20 01:34:08 +0300
committermikhnenko <mikhnenko@yandex-team.com>2025-01-20 01:51:09 +0300
commit2ab2ef14e493133a483a7210a0133c1d8918eee2 (patch)
treeb25a613d75999386160a0ffe41a4f69282a592b3 /contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
parent11def371ff569cef09101fa40c00e6180c3885bc (diff)
downloadydb-2ab2ef14e493133a483a7210a0133c1d8918eee2.tar.gz
Update libcxx to 5 Mar 2024 80f9458cf30d13eef21b09042ea590945c5e64db
commit_hash:c45aa2ed98c2a01fa86b69bac97f40a32bd68ae2
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp')
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp31
1 files changed, 23 insertions, 8 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
index 1b9f2605805..fa31f05b2d2 100644
--- a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
+++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp
@@ -460,8 +460,21 @@ path __current_path(error_code* ec) {
typedef decltype(&::free) Deleter;
Deleter deleter = &::free;
#else
+ errno = 0; // Note: POSIX mandates that modifying `errno` is thread-safe.
auto size = ::pathconf(".", _PC_PATH_MAX);
- _LIBCPP_ASSERT_UNCATEGORIZED(size >= 0, "pathconf returned a 0 as max size");
+ if (size == -1) {
+ if (errno != 0) {
+ return err.report(capture_errno(), "call to pathconf failed");
+
+ // `pathconf` returns `-1` without an error to indicate no limit.
+ } else {
+# if defined(__MVS__) && !defined(PATH_MAX)
+ size = _XOPEN_PATH_MAX + 1;
+# else
+ size = PATH_MAX + 1;
+# endif
+ }
+ }
auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]);
path::value_type* ptr = buff.get();
@@ -608,10 +621,9 @@ void __permissions(const path& p, perms prms, perm_options opts, error_code* ec)
const bool resolve_symlinks = !has_opt(perm_options::nofollow);
const bool add_perms = has_opt(perm_options::add);
const bool remove_perms = has_opt(perm_options::remove);
- _LIBCPP_ASSERT_UNCATEGORIZED(
+ _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
(add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
- "One and only one of the perm_options constants replace, add, or remove "
- "is present in opts");
+ "One and only one of the perm_options constants 'replace', 'add', or 'remove' must be present in opts");
bool set_sym_perms = false;
prms &= perms::mask;
@@ -621,7 +633,9 @@ void __permissions(const path& p, perms prms, perm_options opts, error_code* ec)
set_sym_perms = is_symlink(st);
if (m_ec)
return err.report(m_ec);
- _LIBCPP_ASSERT_UNCATEGORIZED(st.permissions() != perms::unknown, "Permissions unexpectedly unknown");
+ // TODO(hardening): double-check this assertion -- it might be a valid (if rare) case when the permissions are
+ // unknown.
+ _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(st.permissions() != perms::unknown, "Permissions unexpectedly unknown");
if (add_perms)
prms |= st.permissions();
else if (remove_perms)
@@ -668,7 +682,7 @@ path __read_symlink(const path& p, error_code* ec) {
detail::SSizeT ret;
if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1)
return err.report(capture_errno());
- _LIBCPP_ASSERT_UNCATEGORIZED(ret > 0, "TODO");
+ // Note that `ret` returning `0` would work, resulting in a valid empty string being returned.
if (static_cast<size_t>(ret) >= size)
return err.report(errc::value_too_large);
buff[ret] = 0;
@@ -801,8 +815,9 @@ uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) {
// If opening `p` failed because it wasn't a directory, remove it as
// a normal file instead. Note that `openat()` can return either ENOTDIR
- // or ELOOP depending on the exact reason of the failure.
- if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels) {
+ // or ELOOP depending on the exact reason of the failure. On FreeBSD it
+ // may return EMLINK instead of ELOOP, contradicting POSIX.
+ if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels || ec == errc::too_many_links) {
ec.clear();
if (::unlinkat(parent_directory, p.c_str(), /* flags = */ 0) == -1) {
ec = detail::capture_errno();