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.

Reply via email to