Skip to content

cp: when doing hardlink copy of symlink, should replace a technically-different symlink #6531

@BenWiederhake

Description

@BenWiederhake

Let's say we have a regular file regularfile, and two symlinks to it, symlink and hop. Then we have an additional symlink indirect_symlink which points to hop. For most intents and purposes, indirect_symlink points to regularfile, but technically it doesn't, and this difference is visible in ls and would also change completely if hop ever points somewhere else or becomes a (different) regular file.

Now cp should replace indirect_symlink by a hardlink-copy of symlink, but our current implementation says "Eh, everything is fine!" and does nothing, which is just wrong. The -v in the example below is just for illustration.

$ ln -s README.md symlink
$ ln -s README.md hop
$ rm -f indirect_symlink && ln -s hop indirect_symlink && ls -1i README.md symlink hop indirect_symlink && cp -vlP symlink indirect_symlink && ls -1i README.md symlink hop indirect_symlink
20092600 README.md
20074249 hop
20074347 indirect_symlink
20074037 symlink
removed 'indirect_symlink'
'symlink' -> 'indirect_symlink'
20092600 README.md
20074249 hop
20074037 indirect_symlink
20074037 symlink
$ readlink indirect_symlink  # Points directly to README.md
README.md
$ rm -f indirect_symlink && ln -s hop indirect_symlink && ls -1i README.md symlink hop indirect_symlink && cargo run -q cp -vlP symlink indirect_symlink && ls -1i README.md symlink hop indirect_symlink
20092600 README.md
20074249 hop
20074347 indirect_symlink
20074037 symlink
20092600 README.md
20074249 hop
20074347 indirect_symlink
20074037 symlink
$ readlink indirect_symlink  # It didn't even get rewritten!
hop

Found while reading #6496, but only remotely related.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions