Bug 2755

Summary: Copy (cp) command handles hard links incorrectly
Product: Busybox Reporter: Nigel Hathaway <nhathaway>
Component: Standard ComplianceAssignee: unassigned
Status: NEW ---    
Severity: major CC: busybox-cvs
Priority: P5    
Version: 1.14.x   
Target Milestone: ---   
Hardware: PC   
OS: Windows   
Host: Target:
Build:

Description Nigel Hathaway 2010-10-29 12:57:13 UTC
We did the following tests on Ubuntu 9.10 (non-BusyBox) Centos 5.4 (non-BusyBox) and BusyBox 1.14.1 compiled from source:

mkdir dir1
echo "Hello" > dir1/file1
ln dir1/file1 dir1/file2
stat dir1/*
cp -r dir1 dir2
stat dir2/*
cp -a dir1 dir3
stat dir3/*

On the two non-BusyBox systems, the first copy did NOT create hard links for the two files whereas the second copy did.

On the BusyBox system, BOTH of them created hard links.

We have checked through existing bugs and it seems very likely that this is the first reporting of this bug, and that it is still present in the latest (1.17.3) version.

We looked at the source code in coreutils/cp.c and there is a comment as follows (line 46 in 1.14.1 source):

	// -R (and therefore -r) turns on -d (coreutils does this)

We believe that this statement is in error and violates the standards. If it is the GNU coreutils that are being referred to, then it is likely that this was a bug fixed some time ago.

The upshot of this is that it is impossible to do reliable a recursive copy of a cramfs file system using BusyBox cp (we had to do a work-around using back-to-back tar for the time being). Cramfs, in order to save space presumably, creates had links for files that have identical contents. We do an update by copying the cramfs (from flash) to a temporary RAM directory, updating the files, doing a mkcramfs and then saving back to flash. We had 2 identical files, one of which we changed, but both got changed unexpectedly.
Comment 1 Denys Vlasenko 2010-10-30 01:59:25 UTC
Reproduced with GNU coreutils 8.4

Gosh... it seems "follow symlinks" and "follow hardlinks" are handled asymmetrically by it. Thy this:

#!/bin/sh
rm -rf dir1 dir2 dir3
mkdir dir1
echo "Hello" >dir1/file1
ln dir1/file1 dir1/file2
ln -s file1 dir1/file3
ls -li dir1/*
cp -r dir1 dir2
ls -li dir2/*
cp -a dir1 dir3
ls -li dir3/*

I am getting:

262180 -rw-r--r-- 2 root root 6 Oct 30 03:46 dir1/file1
262180 -rw-r--r-- 2 root root 6 Oct 30 03:46 dir1/file2
262183 lrwxrwxrwx 1 root root 5 Oct 30 03:46 dir1/file3 -> file1
262239 -rw-r--r-- 1 root root 6 Oct 30 03:46 dir2/file1
262238 -rw-r--r-- 1 root root 6 Oct 30 03:46 dir2/file2
262217 lrwxrwxrwx 1 root root 5 Oct 30 03:46 dir2/file3 -> file1
262250 -rw-r--r-- 2 root root 6 Oct 30 03:46 dir3/file1
262250 -rw-r--r-- 2 root root 6 Oct 30 03:46 dir3/file2
262246 lrwxrwxrwx 1 root root 5 Oct 30 03:46 dir3/file3 -> file1


cp -r preserves symlinks, but not hardlinks!
Comment 2 Nigel Hathaway 2010-11-01 08:48:07 UTC
The POSIX standard on this is here:

http://www.opengroup.org/onlinepubs/009695399/utilities/cp.html

The standard itself is silent on hard links as far as its prescriptions are concerned, but in the Rationale section it says that cp does NOT maintain the hard-link structure of the source, contrasting this with the operation of pax.
Comment 3 Denys Vlasenko 2011-01-16 21:17:55 UTC
I am not arguing with you. I agree that this needs to be made compatible with coreutils...