On the initial call to copy_internal, we must use an invalid device number. As of linux 3.14, the mount table has shifted slightly, causing the initramfs filesystem to have a devno of 0. This is valid, but confuses cp when attempting to copy only a single filesystem (cp -x). Since dev_t is defined to be an integer type, we can simply use a negative value to identify the unknown device.
* src/copy.c (copy_internal): Make initial callers pass -1, compare to -1 instead of 0, and update documentation. --- Hi, This fixes a bug in Arch Linux's early userspace. We call 'cp -ax' to copy some files from the early userspace into real root. Since 3.14, this is broken and cp ignores the filesystem boundaries because it expects that 0 is an invalid device number. If you're curious about why this changed, please see my analysis on the util-linux mailing list: http://www.spinics.net/lists/util-linux-ng/msg09074.html Cheers, Dave src/copy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/copy.c b/src/copy.c index 781cc1e..472e5f7 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1726,7 +1726,7 @@ should_dereference (const struct cp_options *x, bool command_line_arg) any type. NEW_DST should be true if the file DST_NAME cannot exist because its parent directory was just created; NEW_DST should be false if DST_NAME might already exist. DEVICE is the device - number of the parent directory, or 0 if the parent of this file is + number of the parent directory, or -1 if the parent of this file is not known. ANCESTORS points to a linked, null terminated list of devices and inodes of parent directories of SRC_NAME. COMMAND_LINE_ARG is true iff SRC_NAME was specified on the command line. @@ -2434,7 +2434,7 @@ copy_internal (char const *src_name, char const *dst_name, } /* Decide whether to copy the contents of the directory. */ - if (x->one_file_system && device != 0 && device != src_sb.st_dev) + if (x->one_file_system && device != -1 && device != src_sb.st_dev) { /* Here, we are crossing a file system boundary and cp's -x option is in effect: so don't copy the contents of this directory. */ @@ -2827,7 +2827,7 @@ copy (char const *src_name, char const *dst_name, top_level_dst_name = dst_name; bool first_dir_created_per_command_line_arg = false; - return copy_internal (src_name, dst_name, nonexistent_dst, 0, NULL, + return copy_internal (src_name, dst_name, nonexistent_dst, -1, NULL, options, true, &first_dir_created_per_command_line_arg, copy_into_self, rename_succeeded); -- 1.9.1
