[libcxx-commits] [libcxx] [libcxx] Correct and clean-up filesystem error_code paths (PR #88341)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Apr 12 00:13:49 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Rodrigo Salazar (4-rodrigo-salazar)
<details>
<summary>Changes</summary>
3 error_code related cleanups/corrections in the std::filesystem operations functions.
1. In `__copy`, the `ec->clear()` is unnecessary as `ErrorHandler` at the start of the each function clears the error_code as part of it's initialization.
2. In `__copy`, in the recursive codepath we are not checking the error_code result of `it.increment(m_ec2)` immediately after use in the for loop condition (and we aren't checking it after the final increment when we don't enter the loop).
3. In `__weakly_canonical`, it makes calls to `__canonical` (which internally uses OS apis implementing posix `realpath`) and we are not checking the error code result from the `__canonical` call. Both `weakly_canonical` and `canonical` are supposed to set the error_code when underlying OS APIs result in an error (https://eel.is/c++draft/fs.err.report#<!-- -->3.1). With this change we propagate up the error_code from `__canonical` caused by any underlying OS api failure up to the `__weakly_canonical`. Essentially, if `__canonical` thinks an error code should be set, then `__weakly_canonical` must as well. Before this change it would be throwing an exception in the non-error_code form of the function when `__canonical` fails, while not setting the error code in the error_code form of the function (an inconsistency).
Added a little coverage in weakly_canonical.pass.cpp for the error_code forms of the api that was missing. Though I am lacking utilities in libcxx testing to add granular testing of the failure scenarios (like forcing realpath to fail for a given path, as it could if you had something like a flaky remote filesystem).
---
Full diff: https://github.com/llvm/llvm-project/pull/88341.diff
2 Files Affected:
- (modified) libcxx/src/filesystem/operations.cpp (+15-13)
- (modified) libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp (+8)
``````````diff
diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
index 62bb248d5eca9b..6a8e42d2090c40 100644
--- a/libcxx/src/filesystem/operations.cpp
+++ b/libcxx/src/filesystem/operations.cpp
@@ -126,9 +126,6 @@ void __copy(const path& from, const path& to, copy_options options, error_code*
return err.report(errc::function_not_supported);
}
- if (ec)
- ec->clear();
-
if (is_symlink(f)) {
if (bool(copy_options::skip_symlinks & options)) {
// do nothing
@@ -166,15 +163,15 @@ void __copy(const path& from, const path& to, copy_options options, error_code*
return;
}
error_code m_ec2;
- for (; it != directory_iterator(); it.increment(m_ec2)) {
- if (m_ec2) {
- return err.report(m_ec2);
- }
+ for (; !m_ec2 && it != directory_iterator(); it.increment(m_ec2)) {
__copy(it->path(), to / it->path().filename(), options | copy_options::__in_recursive_copy, ec);
if (ec && *ec) {
return;
}
}
+ if (m_ec2) {
+ return err.report(m_ec2);
+ }
}
}
@@ -936,23 +933,28 @@ path __weakly_canonical(const path& p, error_code* ec) {
--PP;
vector<string_view_t> DNEParts;
+ error_code m_ec;
while (PP.State != PathParser::PS_BeforeBegin) {
tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
- error_code m_ec;
file_status st = __status(tmp, &m_ec);
if (!status_known(st)) {
return err.report(m_ec);
} else if (exists(st)) {
- result = __canonical(tmp, ec);
+ result = __canonical(tmp, &m_ec);
+ if (m_ec) {
+ return err.report(m_ec);
+ }
break;
}
DNEParts.push_back(*PP);
--PP;
}
- if (PP.State == PathParser::PS_BeforeBegin)
- result = __canonical("", ec);
- if (ec)
- ec->clear();
+ if (PP.State == PathParser::PS_BeforeBegin) {
+ result = __canonical("", &m_ec);
+ if (m_ec) {
+ return err.report(m_ec);
+ }
+ }
if (DNEParts.empty())
return result;
for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp
index 053bddcad9b43a..4e4f459f8cf364 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp
@@ -79,6 +79,14 @@ int main(int, char**) {
TEST_REQUIRE(PathEq(output, expect),
TEST_WRITE_CONCATENATED(
"Input: ", TC.input.string(), "\nExpected: ", expect.string(), "\nOutput: ", output.string()));
+
+ // Get coverage over the error_code form of the api.
+ std::error_code ec;
+ const fs::path output_c = fs::weakly_canonical(p, ec);
+
+ TEST_REQUIRE(PathEq(output_c, expect),
+ TEST_WRITE_CONCATENATED(
+ "Input: ", TC.input.string(), "\nExpected: ", expect.string(), "\nOutput: ", output_c.string()));
}
return 0;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/88341
More information about the libcxx-commits
mailing list