2

When copying symbolic links from incremental backups, unexpected behavior can occur. For example:

# mkdir 0 1 2
# touch 0/a
# ln 0/a 0/b
# touch 1/a
# ln 1/b 1/a

So directory 0 looks like

a
b->a

And directory 1 looks like

a->b
b

Now we run

# cp -a 0/. 2
# cp -a 1/. 2

The expected/intended behavior would be that directory 2 would be indentical to 1, however it actually contains two links

a -> b
b -> a

This occured in practice when I was copying some rsync backups of a /usr/ directory. The /usr/share/zoneinfo directory has undergone a number of these various symbolic link switches in the last year. It seems that although cp -a does not follow symbolic links in SOURCE, it may be following them in DEST.

Is there a way to get the appropriate result here?

(As an aside, rsync does it correctly, but I want to use the --reflink=always flag of cp as well...)

1

When you do cp -a 1/. 2 it is doing b first, but since b -> a already exists the contents of b are written into a. Then a->b is considered which results in overwriting a with the symbolic link a->b. If you run cp -a 1/. 2 again, you should get "Too many levels of symbolic links".

So, yes, cp follows symbolic links in the destination. You can try --remove-destination which solves the problem correctly for your MWE. However, if you have symlinks as directory components in the destination, they won't be torn down by --remove-destination.

The real question is "why do something like this?" I only ever use cp -a with an empty directory as a target. Also, the filesystems that support --reflink=always also have more elegant ways to clone a directory tree as a backup.

  • Here's the situation in which I was doing this - I have a bunch of rsnapshot style directories (incremental backups via hardlinks) that I am converting to btrfs subvolume snapshots. I create a new snapshot from the oldest existing directory, for example btrfs subvolume create hourly.3, then cp -ax --reflink=always old_ver/hourly.3/. hourly.3, and then create snapshots btrfs subvolume snapshot hourly.3 hourly.2, run an rsync --delete --ignore-existing --ignore-non-existing old/hourly.2/. hourly.2, and then run cp -ax --reflink old_ver/hourly.2/. hourly.2. – process91 Jan 26 '17 at 4:26
  • I believe I had a misinterpretation that the btrfs subvolume snapshot SOURCE DEST command was doing something "fancier" than it was. It seems to me that an almost identical amount of space is saved by simply creating individual subvolumes out of the existing folders (since many of the files therein were hardlinked, btrfs still conserves the space when cp -ax --reflink=always is used) so I can simply convert each folder in turn, rather than "link them" using the snapshot feature. – process91 Jan 26 '17 at 4:58
  • I'll accept this as the answer, which is basically that yes, cp does have this behavior, and that's that. I disagree with the "why do something like this?" both in practice (I gave the example of why I am using it this way above which, while perhaps unconventional, is not all that crazy, and might still be relevant on non-btrfs systems) and in theory. In particular, I'd question why cp "does something like this" itself :) – process91 Jan 29 '17 at 1:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.