This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.
filesystem::copy()
won't create a symlink to a directorySection: 31.12.13.4 [fs.op.copy] Status: C++20 Submitter: Jonathan Wakely Opened: 2016-04-19 Last modified: 2021-02-25
Priority: 2
View all other issues in [fs.op.copy].
View all issues with C++20 status.
Discussion:
(First raised in c++std-lib-38544)
filesystem::copy
doesn't create a symlink to a directory in this case:
copy("/", "root", copy_options::create_symlinks);
If the first path is a file then a symlink is created, but I think my
implementation is correct to do nothing for a directory. We get to
bullet 31.12.13.4 [fs.op.copy] (3.6) where is_directory(f)
is true, but options
== create_symlinks
, so we go to the next bullet (3.7) which says
"Otherwise, no effects."
create_symlink
to create a symlink to a directory.
[2016-05 Issues Telecon]
This is related to 2681(i); and should be considered together.
[2016-08 Chicago]
Wed AM: Move to Tentatively Ready
Previous resolution [SUPERSEDED]:
Add a new bullet following (3.6) in 31.12.13.4 [fs.op.copy] as shown:
If
!exists(t)
, thencreate_directory(to, from)
.Then, iterate over the files in
from
, as if byfor (directory_entry& x : directory_iterator(from))
, and for each iterationcopy(x.path(), to/x.path().filename(), options | copy_options::unspecified )
Otherwise, if
is_directory(f) && (options & copy_options::create_symlinks) != copy_options::none
, then report an error with anerror_code
argument equal tomake_error_code(errc::is_a_directory)
.Otherwise, no effects.
[2016-10-16, Eric reopens and provides improved wording]
The current PR makes using copy(...)
to copy/create a directory symlink an error. For example, the following
is now an error:
copy("/", "root", copy_options::create_symlinks);
However the current PR doesn't handle the case where both copy_options::create_symlinks
and
copy_options::recursive
are specified. This case is still incorrectly handled by bullet (3.6) [fs.op.copy].
3.6 Otherwise if
is_directory(f) && (bool(options & copy_options::recursive) || ...)
3.X Otherwise ifis_directory(f) && bool(options & copy_options::create_symlinks)
So 3.6 catches create_symlinks | recursive
but I believe we want 3.X to handle it instead.
[2018-01-26 issues processing telecon]
Status to 'Review'; we think this is OK but want some implementation experience before adopting it.
[2018-01-29 Jonathan says]
The proposed resolution for LWG 2682 has been in GCC's Filesystem TS implementation for more than a year.
It's also in our std::filesystem
implementation on the subversion trunk.
[2018-06; Rapperswil Wednesday evening]
JW: can we use the words we are shipping already since two years?
BO: what we got is better than what we had before
no objection to moving to Ready
ACTION move to Ready
ACTION link 2682 and LWG 3057(i) and set a priority 2 and look at 3057 in San Diego
[2018-11, Adopted in San Diego]
Proposed resolution:
This wording is relative to N4750.
Add a new bullet before (4.8) in 31.12.13.4 [fs.op.copy] as shown:
(4.7) — Otherwise, if
is_regular_file(f)
, then:[…](4.?) — Otherwise, if
is_directory(f) && (options & copy_options::create_symlinks) != copy_options::nonethen report an error with an
error_code
argument equal tomake_error_code(errc::is_a_directory)
.(4.8) — Otherwise, if
is_directory(f) && ((options & copy_options::recursive) != copy_options::none || options == copy_options::none)then:
(4.8.1) — If
exists(t)
isfalse
, thencreate_directory(to, from)
.(4.8.2) — Then, iterate over the files in
from
, as if byfor (const directory_entry& x : directory_iterator(from)) copy(x.path(), to/x.path().filename(), options | copy_options::in-recursive-copy);where
in-recursive-copy
is a bitmask element ofcopy_options
that is not one of the elements in 31.12.8.3 [fs.enum.copy.opts].(4.9) — Otherwise, for the signature with argument
ec
,ec.clear()
.(4.10) — Otherwise, no effects.