Title
filesystem::copy() won't create a symlink to a directory
Status
c++20
Section
[fs.op.copy]
Submitter
Jonathan Wakely

Created on 2016-04-19.00:00:00 last changed 38 months ago

Messages

Date: 2018-11-12.04:39:29

Proposed resolution:

This wording is relative to N4750.

  1. Add a new bullet before (4.8) in [fs.op.copy] as shown:

    1. (4.7) — Otherwise, if is_regular_file(f), then:

      […]
    2. (4.?) — Otherwise, if

      is_directory(f) && 
      (options & copy_options::create_symlinks) != copy_options::none
      

      then report an error with an error_code argument equal to make_error_code(errc::is_a_directory).

    3. (4.8) — Otherwise, if

      is_directory(f) &&
      ((options & copy_options::recursive) != copy_options::none ||
      options == copy_options::none)
      

      then:

      1. (4.8.1) — If exists(t) is false, then create_directory(to, from).

      2. (4.8.2) — Then, iterate over the files in from, as if by

        for (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 of copy_options that is not one of the elements in [fs.enum.copy.opts].

    4. (4.9) — Otherwise, for the signature with argument ec, ec.clear().

    5. (4.10) — Otherwise, no effects.

Date: 2018-11-12.04:39:29

[ 2018-11, Adopted in San Diego ]

Date: 2018-06-07.21:18:04

[ 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 and set a priority 2 and look at 3057 in San Diego

Daniel rebases wording to N4750.

Date: 2018-01-29.00:00:00

[ 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.

Date: 2018-01-26.00:00:00

[ 2018-01-26 issues processing telecon ]

Status to 'Review'; we think this is OK but want some implementation experience before adopting it.

Date: 2016-10-15.00:00:00

[ 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].

I suggest we move the PR before this bullet so that it catches the recursive copy case, since currently the conditions are ordered:

3.6 Otherwise if is_directory(f) && (bool(options & copy_options::recursive) || ...)
3.X Otherwise if is_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.

Date: 2016-10-16.12:34:03

[ 2016-08 Chicago ]

Wed AM: Move to Tentatively Ready

Previous resolution [SUPERSEDED]:

Add a new bullet following (3.6) in [fs.op.copy] as shown:

  • If !exists(t), then create_directory(to, from).

  • Then, iterate over the files in from, as if by for (directory_entry& x : directory_iterator(from)), and for each iteration copy(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 an error_code argument equal to make_error_code(errc::is_a_directory).

  • Otherwise, no effects.

Date: 2016-08-06.21:31:18

[ 2016-05 Issues Telecon ]

This is related to 2681; and should be considered together.

Date: 2016-04-19.00:00:00

(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 [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."

I think the case above should either create a symlink, or should report an error. GNU cp -s gives an error in this case, printing "omitting directory '/'". An error seems reasonable, you can use create_symlink to create a symlink to a directory.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2018-11-12 04:39:29adminsetmessages: + msg10179
2018-11-12 04:39:29adminsetstatus: voting -> wp
2018-10-08 05:13:59adminsetstatus: ready -> voting
2018-06-07 21:18:04adminsetmessages: + msg9875
2018-06-07 21:18:04adminsetstatus: review -> ready
2018-01-29 17:48:14adminsetmessages: + msg9664
2018-01-28 19:43:07adminsetmessages: + msg9646
2018-01-28 19:43:07adminsetstatus: open -> review
2016-10-16 12:34:03adminsetmessages: + msg8570
2016-10-16 12:34:03adminsetstatus: ready -> open
2016-08-04 02:52:49adminsetmessages: + msg8383
2016-08-04 02:52:49adminsetstatus: new -> ready
2016-05-22 15:38:38adminsetmessages: + msg8134
2016-05-08 12:33:07adminsetmessages: + msg8096
2016-04-19 00:00:00admincreate