cplusplus/draft

A contradictory statement in `std::filesystem::copy`

Closed this issue · 4 comments

std::filesystem::copy (clause 31.12.13.4, main latest 458b16a) has a contradictory statement in handling source being a symbolic link. When copy_options is set to none for symbolic link behavior (i.e., not given any), copy_options states that copy operation should follow symbolic links. However, std::filesystem::copy states that it should result in an error when source (i.e., f) is a symbolic link and no options are given.

Summary

Expected: std::filesystem::copy should follow source symbolic link when no symbolic link copy_options is given (i.e., none).
Actual: std::filesystem::copy reports an error

Detailed breakdown

Assume f (i.e., source), and no copy_options for symbolic link behavior is given. The copy_options::none would be set.

  • Looking into std::filesystem::copy
    • is_symlink(f) is true --> yes
      • If (options & copy_options::skip_symlinks) != copy_options::none then return --> no
      • !exists(t) && (options & copy_options::copy_symlinks) != copy_options::none --> no
      • Report an error as specified in 31.12.5
  • This contradicts the statement in std::filesystem::copy_options
    • none --> follow symlinks (instead, std::filesystem::copy states that this should error)

This doesn't sound like an editorial issue to me. Please double-check with existing LWG issues. A possible relevant existing candidate is LWG 3057, otherwise you can submit an LWG as issue as described here.

Thanks for informing me about LWG. I'll check it and send this issue there.

There is no contradiction here. When copy_symlinks is not set in copy_options then (4.3) says auto f = status(from); and so is_symlink(f) is always false.

Detailed breakdown

Assume f (i.e., source), and no copy_options for symbolic link behavior is given. The copy_options::none would be set.

If options == copy_options::none then auto f = status(from);

* Looking into `std::filesystem::copy`
  
  * `is_symlink(f)` is true --> yes

Your mistake is here. This is always false, because status(from) follows symlinks and gives you the status of the file the symlink points to. i.e. is_symlink(status(from)) is never true, so is_symlink(f) is not true.

So we continue down the ladder of conditions until (4.7.5) and then copy the file.