diff --git a/libcxx/docs/Cxx2aStatusIssuesStatus.csv b/libcxx/docs/Cxx2aStatusIssuesStatus.csv --- a/libcxx/docs/Cxx2aStatusIssuesStatus.csv +++ b/libcxx/docs/Cxx2aStatusIssuesStatus.csv @@ -15,7 +15,7 @@ "","","","","" "`2779 `__","[networking.ts] Relax requirements on buffer sequence iterators","Albuquerque","","" "`2870 `__","Default value of parameter theta of polar should be dependent","Albuquerque","|Complete|","" -"`2935 `__","What should create_directories do when p already exists but is not a directory?","Albuquerque","","" +"`2935 `__","What should create_directories do when p already exists but is not a directory?","Albuquerque","|Nothing To Do|","" "`2941 `__","[thread.req.timing] wording should apply to both member and namespace-level functions","Albuquerque","|Nothing To Do|","" "`2944 `__","LWG 2905 accidentally removed requirement that construction of the deleter doesn't throw an exception","Albuquerque","|Nothing To Do|","" "`2945 `__","Order of template parameters in optional comparisons","Albuquerque","|Complete|","" @@ -83,7 +83,7 @@ "`3071 `__","[networking.ts] read_until still refers to ""input sequence""","Rapperswil","|Nothing To Do|","" "`3074 `__","Non-member functions for valarray should only deduce from the valarray","Rapperswil","","" "`3076 `__","basic_string CTAD ambiguity","Rapperswil","|Complete|","" -"`3079 `__","LWG 2935 forgot to fix the existing_p overloads of create_directory","Rapperswil","","" +"`3079 `__","LWG 2935 forgot to fix the existing_p overloads of create_directory","Rapperswil","|Nothing To Do|","" "`3080 `__","Floating point from_chars pattern specification breaks round-tripping","Rapperswil","","" "`3083 `__","What should ios::iword(-1) do?","Rapperswil","|Nothing To Do|","" "`3094 `__","[time.duration.io]p4 makes surprising claims about encoding","Rapperswil","","" diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv --- a/libcxx/docs/Cxx2aStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv @@ -87,7 +87,7 @@ "`P0920R2 `__","LWG","Precalculated hash values in lookup","Kona","Reverted by `P1661 `__","" "`P1001R2 `__","LWG","Target Vectorization Policies from Parallelism V2 TS to C++20","Kona","","" "`P1024R3 `__","LWG","Usability Enhancements for std::span","Kona","|Complete|","9.0" -"`P1164R1 `__","LWG","Make create_directory() Intuitive","Kona","","" +"`P1164R1 `__","LWG","Make create_directory() Intuitive","Kona","|Complete|","12.0" "`P1227R2 `__","LWG","Signed ssize() functions, unsigned size() functions","Kona","|Complete|","9.0" "`P1252R2 `__","LWG","Ranges Design Cleanup","Kona","","" "`P1286R2 `__","CWG","Contra CWG DR1778","Kona","","" diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -849,8 +849,17 @@ if (::mkdir(p.c_str(), static_cast(perms::all)) == 0) return true; - if (errno != EEXIST) + + if (errno == EEXIST) { + error_code mec = capture_errno(); + error_code ignored_ec; + const file_status st = status(p, ignored_ec); + if (!is_directory(st)) { + err.report(mec); + } + } else { err.report(capture_errno()); + } return false; } @@ -868,8 +877,17 @@ if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) return true; - if (errno != EEXIST) + + if (errno == EEXIST) { + error_code mec = capture_errno(); + error_code ignored_ec; + const file_status st = status(p, ignored_ec); + if (!is_directory(st)) { + err.report(mec); + } + } else { err.report(capture_errno()); + } return false; } diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp @@ -8,6 +8,9 @@ // UNSUPPORTED: c++03 +// This test requires the dylib support introduced in D92769. +// XFAIL: with_system_cxx_lib=macosx10.15 + // // bool create_directory(const path& p); @@ -95,8 +98,40 @@ const path file = env.create_file("file", 42); std::error_code ec = GetTestEC(); TEST_CHECK(fs::create_directory(file, ec) == false); - TEST_CHECK(!ec); + TEST_CHECK(ec); + TEST_CHECK(is_regular_file(file)); +} + +TEST_CASE(dest_part_is_file) +{ + scoped_test_env env; + const path file = env.create_file("file"); + const path dir = env.make_env_path("file/dir1"); + std::error_code ec = GetTestEC(); + TEST_CHECK(fs::create_directory(dir, ec) == false); + TEST_CHECK(ec); TEST_CHECK(is_regular_file(file)); + TEST_CHECK(!exists(dir)); +} + +TEST_CASE(dest_is_symlink_to_dir) +{ + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path sym = env.create_symlink(dir, "sym_name"); + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directory(sym, ec) == false); + TEST_CHECK(!ec); +} + +TEST_CASE(dest_is_symlink_to_file) +{ + scoped_test_env env; + const path file = env.create_file("file"); + const path sym = env.create_symlink(file, "sym_name"); + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directory(sym, ec) == false); + TEST_CHECK(ec); } TEST_SUITE_END() diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp @@ -8,6 +8,9 @@ // UNSUPPORTED: c++03 +// This test requires the dylib support introduced in D92769. +// XFAIL: with_system_cxx_lib=macosx10.15 + // // bool create_directory(const path& p, const path& attr); @@ -95,10 +98,23 @@ const path attr_dir = env.create_dir("attr_dir"); std::error_code ec = GetTestEC(); TEST_CHECK(fs::create_directory(file, attr_dir, ec) == false); - TEST_CHECK(!ec); + TEST_CHECK(ec); TEST_CHECK(is_regular_file(file)); } +TEST_CASE(dest_part_is_file) +{ + scoped_test_env env; + const path file = env.create_file("file", 42); + const path dir = env.make_env_path("file/dir1"); + const path attr_dir = env.create_dir("attr_dir"); + std::error_code ec = GetTestEC(); + TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(is_regular_file(file)); + TEST_CHECK(!exists(dir)); +} + TEST_CASE(attr_dir_is_invalid) { scoped_test_env env; const path file = env.create_file("file", 42); @@ -117,15 +133,39 @@ } } -TEST_CASE(dest_is_symlink) { +TEST_CASE(dest_is_symlink_to_unexisting) { scoped_test_env env; - const path dir = env.create_dir("dir"); + const path attr_dir = env.create_dir("attr_dir"); const path sym = env.create_symlink("dne_sym", "dne_sym_name"); { std::error_code ec = GetTestEC(); - TEST_CHECK(create_directory(sym, dir, ec) == false); + TEST_CHECK(create_directory(sym, attr_dir, ec) == false); + TEST_CHECK(ec); + } +} + +TEST_CASE(dest_is_symlink_to_dir) { + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path sym = env.create_symlink(dir, "sym_name"); + const path attr_dir = env.create_dir("attr_dir"); + { + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directory(sym, attr_dir, ec) == false); TEST_CHECK(!ec); } } +TEST_CASE(dest_is_symlink_to_file) { + scoped_test_env env; + const path file = env.create_file("file"); + const path sym = env.create_symlink(file, "sym_name"); + const path attr_dir = env.create_dir("attr_dir"); + { + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directory(sym, attr_dir, ec) == false); + TEST_CHECK(ec); + } +} + TEST_SUITE_END()