Page MenuHomeFreeBSD

cp: Clarify that -P now only modifies how source_file is treated
AbandonedPublic

Authored by jrm on Thu, Oct 23, 6:17 PM.
Tags
None
Referenced Files
F133401268: D53302.diff
Sat, Oct 25, 12:46 PM
Unknown Object (File)
Fri, Oct 24, 6:16 AM
Unknown Object (File)
Fri, Oct 24, 6:05 AM
Unknown Object (File)
Fri, Oct 24, 1:07 AM
Unknown Object (File)
Thu, Oct 23, 11:37 PM
Unknown Object (File)
Thu, Oct 23, 10:51 PM
Unknown Object (File)
Thu, Oct 23, 10:12 PM
Subscribers

Details

Reviewers
des
emaste
ashish
Summary

After 82fc0d09e862, in order to conform to POSIX, symbolic links in target_file are followed.

Before 82fc0d09e862:
% ln -sf /nonexistent/bar
% touch foo
% cp -P foo bar
% ls
bar foo

After 82fc0d09e862:
% ln -sf /nonexistent/bar
% touch foo
% cp -P foo bar
cp: bar: No such file or directory

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 68052
Build 64935: arc lint + arc unit

Event Timeline

jrm requested review of this revision.Thu, Oct 23, 6:17 PM

Example in commit message needs a line break: touch foo cp -P foo bar

Example in commit message needs a line break: touch foo cp -P foo bar

Already cleaned up the example.

Example in commit message needs a line break: touch foo cp -P foo bar

Your update and this comment crossed paths...

In D53302#1217405, @jrm wrote:

Already cleaned up the example.

Yeah, your reply and my reply also crossed paths :)

bin/cp/cp.1
95

This is incorrect, please refer to POSIX.

Example in commit message needs a line break: touch foo cp -P foo bar

Your update and this comment crossed paths...

bin/cp/cp.1
95

I think these are the relevant parts of the POSIX standard:

If source_file is a file of type symbolic link:

If the -R option was not specified, cp shall take actions based on the type and contents of the file referenced by the symbolic link, and not by the symbolic link itself, unless the -P option was specified.

If the -R option was specified:

If none of the options -H, -L, nor -P were specified, it is unspecified which of -H, -L, or -P will be used as a default.

This is what we're doing:

% ln -sf /nonexistent/foo
% cp foo bar
cp: foo: No such file or directory
% cp -R foo bar
% ls
bar foo

Unless I'm missing something, the behaviour hasn't changed, so I didn't (effectively) change that sentence.

bin/cp/cp.1
95

No, the relevant excerpts are

If the -P option was specified, cp shall copy any symbolic link specified as a source_file operand and any symbolic links encountered during traversal of a file hierarchy, and shall not follow any symbolic links.

and

-P
Take actions on any symbolic link specified as a source_file operand or any symbolic link encountered during traversal of a file hierarchy.

and you most definitely did change that.

bin/cp/cp.1
95

You highlighted the line This is the default when the, which didn't change other than a s/if/when/.

The only real change here is s/No symbolic links are followed./When source_file is a symbolic link, do not follow it./

bin/cp/cp.1
95

Yes. And that is incorrect.

bin/cp/cp.1
95

and you most definitely did change that.

I did not.

Yes. And that is incorrect.

Maybe you can elaborate a little, given the example I shared above.

% ln -sf /nonexistent/foo
% cp foo bar
cp: foo: No such file or directory
% cp -R foo bar
% ls
bar foo
bin/cp/cp.1
95

If you're unable or unwilling to read and understand the spec (which I quoted above) and / or the code, then perhaps you should leave well enough alone.

bin/cp/cp.1
95

Excerpt from the email notification, I received:

INLINE COMMENTS

des wrote in cp.1:95
This is incorrect, please refer to POSIX.

I think these are the relevant parts of the "POSIX standard" <https://reviews.freebsd.org/w/url/>:

If source_file is a file of type symbolic link:

  If the -R option was not specified, cp shall take actions based on the type and contents of the file referenced by the symbolic link, and not by the symbolic link itself, unless the -P option was specified.

I tried to look, but I'm not sure which POSIX standard is hosted at https://reviews.freebsd.org/w/url/ ;-). How about you provide the right one in the first place

Thanks!

bin/cp/cp.1
94

Also, this documentation change looks good to me.

Previous version mentioned "symbolic links" without implying any position, which can mean in either source or destination field, which is not what the code handling this flag/switch considers, it only considers the symbolic links in the source field.

This version clarifies any symbolic links in the source_file field are not followed.

This revision is now accepted and ready to land.Fri, Oct 24, 5:42 PM

I read the part of the specification you quoted several times.

  • The first sentence applies when the -R option is specified. I interpret it as: When both -P and -R are specified and a symbolic link is encountered (either as an explicit source file or while traversing a directory), cp copies the link itself rather than the file or directory it points to.
  • I interpret the second sentence as: If any of the source files or any files inside a copied directory are symbolic links, copy the links themselves instead of the files they point to.

This aligns with what I see when I test.

% ln -sf /nonexisten/foo
% cp foo bar
cp: foo: No such file or directory
% cp -P foo bar
% ls -lah
total 26 KB
drwxr-xr-x   2 jrm jrm uarch    4B Oct 24 14:19 ./
drwxr-xr-x  17 jrm jrm uarch   36B Oct 23 10:46 ../
lrwxr-xr-x   1 jrm jrm uarch   15B Oct 24 14:19 bar@ -> /nonexisten/foo
lrwxr-xr-x   1 jrm jrm uarch   15B Oct 24 14:19 foo@ -> /nonexisten/foo

I think the old version of the description that simply says, "No symbolic links are followed." is flawed because after your changes, symbolic links for target are now followed. Perhaps it's too specific to say "When *source_file* is a symbolic link..." because we also have to account for the "while traversing a directory" in the sources. Then again, this isn't even the line you flagged as incorrect.

I'm unsure what happened to the link to the POSIX specification in that quoted post. In any case, it's https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/cp.html.

This clearly isn't helpful for anyone.

bin/cp/cp.1
95

There is only one POSIX standard, and it is trivial to find. I would argue that if you're not already familiar with it and not even willing to google it (or follow the link from the Wikipedia article) then you have no business making conformance edits to our documentation. But we all have to start somewhere, so here it is: https://pubs.opengroup.org/onlinepubs/9799919799/

The proposed edit is wildly incorrect; -H only applies to symlinks given on the command line, but -L and -P apply to all symlinks encountered while traversing source hierarchies when -R is in effect.

I've spent the last two years getting cp into something resembling conformance and adding tests to ensure that it stays that way. I'm aware that the manual page is unclear in its current state (and somewhat incomplete as it does not discuss symbolic links in the destination at all), but as long as you don't take individual sentences out of context, it is not outright incorrect, and I prefer to leave well enough alone until I find the time to revise it from top to bottom.