https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119289
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Your test would be a lot simpler if you just use filesystem::copy_file and skip
all the filesystem::copy logic that ends up with a call to copy_file.
#include <filesystem>
#include <fstream>
int main()
{
std::ofstream("src.txt") << "blah\n";
std::filesystem::create_symlink("asdf", "link_dst");
std::filesystem::copy_file("src.txt", "link_dst");
}
This seems like a defect in the standard. The assumption in the copy_file spec
seems to be that when exists(to) is false, we're just creating a new file.
But exists(symlink_status(to)) is true, so we can't just create a new file. We
would need to remove the symlink first, or resolve the symlink and create the
file with the target name.
Our implementation opens a file descriptor for the output file using:
int oflag = O_WRONLY | O_CREAT | common_flags;
if (options.overwrite || options.update)
oflag |= O_TRUNC;
else
oflag |= O_EXCL;
CloseFD out = { posix::open(to, oflag, S_IWUSR) };
if (out.fd == -1)
{
if (errno == EEXIST && options.skip)
ec.clear();
else
ec.assign(errno, std::generic_category());
return false;
}
The call to POSIX open fails and sets errno == EEXIST, because it does exist.
Libc++ behaves the same way.