From 9ada18b3392b89876b2315b0a5e35088f9d6e0fb Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sat, 15 Oct 2016 23:05:04 +0000 Subject: [PATCH] Implement LWG 2672. llvm-svn: 284314 --- .../experimental/filesystem/operations.cpp | 22 ++++++++++---- .../fs.op.is_empty/is_empty.pass.cpp | 29 +++++++++++++++++++ libcxx/www/upcoming_meeting.html | 4 +-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/libcxx/src/experimental/filesystem/operations.cpp b/libcxx/src/experimental/filesystem/operations.cpp index 5d0a9a9dd30c..eba7ae368e26 100644 --- a/libcxx/src/experimental/filesystem/operations.cpp +++ b/libcxx/src/experimental/filesystem/operations.cpp @@ -472,13 +472,25 @@ bool __fs_is_empty(const path& p, std::error_code *ec) std::error_code m_ec; struct ::stat pst; auto st = detail::posix_stat(p, pst, &m_ec); - if (is_directory(st)) - return directory_iterator(p) == directory_iterator{}; + if (m_ec) { + set_or_throw(m_ec, ec, "is_empty", p); + return false; + } + else if (!is_directory(st) && !is_regular_file(st)) { + m_ec = make_error_code(errc::not_supported); + set_or_throw(m_ec, ec, "is_empty"); + return false; + } + else if (is_directory(st)) { + auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p); + if (ec && *ec) + return false; + return it == directory_iterator{}; + } else if (is_regular_file(st)) return static_cast(pst.st_size) == 0; - // else - set_or_throw(m_ec, ec, "is_empty", p); - return false; + + _LIBCPP_UNREACHABLE(); } diff --git a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp index ba07d09d10d9..bc62086c2cff 100644 --- a/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp +++ b/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp @@ -77,4 +77,33 @@ TEST_CASE(test_is_empty_fails) TEST_CHECK_THROW(filesystem_error, is_empty(dir2)); } +TEST_CASE(test_directory_access_denied) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file1 = env.create_file("dir/file", 42); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + TEST_CHECK(is_empty(dir, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + + TEST_CHECK_THROW(filesystem_error, is_empty(dir)); +} + + +TEST_CASE(test_fifo_fails) +{ + scoped_test_env env; + const path fifo = env.create_fifo("fifo"); + + std::error_code ec = GetTestEC(); + TEST_CHECK(is_empty(fifo, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + + TEST_CHECK_THROW(filesystem_error, is_empty(fifo)); +} + TEST_SUITE_END() diff --git a/libcxx/www/upcoming_meeting.html b/libcxx/www/upcoming_meeting.html index 4b58c7e48573..7c1dac04c0fb 100644 --- a/libcxx/www/upcoming_meeting.html +++ b/libcxx/www/upcoming_meeting.html @@ -90,7 +90,7 @@ 2598addressof works on temporariesIssaquahPatch ready 2664operator/ (and other append) semantics not useful if argument has rootIssaquahNothing to do 2665remove_filename() post condition is incorrectIssaquahSee Below - 2672Should is_empty use error_code in its specification?Issaquah + 2672Should is_empty use error_code in its specification?IssaquahWe already do this 2678std::filesystem enum classes overspecifiedIssaquahNothing to do 2679Inconsistent Use of Effects and Equivalent ToIssaquahNothing to do 2680Add "Equivalent to" to filesystemIssaquah @@ -168,7 +168,7 @@
  • 2598 - Patch and tests ready
  • 2664 - No change needed. _LIBCPP_DEBUG mode tests the new requirements.
  • 2665 - PR is incorrect as-is. We implement a modified version
  • -
  • 2672 - File System; Eric?
  • +
  • 2672 - Patch and tests in tree.
  • 2678 - File System; Eric?
  • 2679 - This is just wording cleanup.
  • 2680 - File System; Eric?