cp -x one file system

Version:

coreutils-6.7

Bug Link:

http://lists.gnu.org/archive/html/bug-coreutils/2007-03/msg00012.html

Symptom:

when using cp with -x/--one-file-system option, permissions of mount point directories did not get preserved properly.

Failure type:

incorrect computation (result)

Is there log messages (default verbosity level) printed?

No

How it is diagnosed (reproduced or source analysis)?

reproduced!

How to reproduce?

# mkdir /foo /foo/bar
# mount /dev/sdb1 /foo/bar
# ls -l /foo
total 4
drwxrwxrwt   3 root     root         4096 Mar  3 06:09 bar
# mkdir /quux
# cp -ax /foo /quux/
# ls -l /quux/foo
total 4
drwx-----T   2 root     root         4096 Mar  3 06:36 bar

Root cause:

Right after the directory is created  and it detects one_file_system flag and it’s crossing file system boundary, it returns.

So there is no opportunity to set any permission bits which may have been masked out by the umask.

    if (x->one_file_system && device != 0 && device != src_sb.st_dev)
       return true;

--- a/src/copy.c
+++ b/src/copy.c
@@ -1604,19 +1604,20 @@ copy_internal (char const *src_name, char const
*dst_name,
           emit_verbose (src_name, dst_name, NULL);
       }

-      /* Are we crossing a file system boundary?  */
+      /* Decide whether to copy the contents of the directory.  */
      if (x->one_file_system && device != 0 && device != src_sb.st_dev)
-       return true;

+     {

+         /* 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. */

+    }

+      else
+       {
+         /* Copy the contents of the directory.  Don't just return if
+            this fails -- otherwise, the failure to read a single file
+            in a source directory would cause the containing destination
+            directory not to have owner/perms set properly.  */
+         delayed_ok = copy_dir (src_name, dst_name, new_dst, &src_sb, dir, x,
+                                copy_into_self);

}
-
-      /* Copy the contents of the directory.  */
-
-      if (! copy_dir (src_name, dst_name, new_dst, &src_sb, dir, x,
-                     copy_into_self))
       {
-         delayed_ok = false;
-       }
 }
  else if (x->symbolic_link)

   ...

}

Can Errlog insert an error message?

Yes. Log the untested branch decision. The following branch decision is not tested and should

b e logged:  

if (x->one_file_system && device != 0 && device != src_sb.st_dev)