From 6a4350f7d96cc1adf7c032b0edf5de583cb634fe Mon Sep 17 00:00:00 2001 From: Ondrej Vasik Date: Sep 16 2009 06:03:40 +0000 Subject: fix copying of extended attributes for read only source files --- diff --git a/coreutils-cpxattrreadonly.patch b/coreutils-cpxattrreadonly.patch new file mode 100644 index 0000000..2b28996 --- /dev/null +++ b/coreutils-cpxattrreadonly.patch @@ -0,0 +1,163 @@ +From cca83fafa69eb26db458714830b77498b88af8a4 Mon Sep 17 00:00:00 2001 +From: Ondřej Vašík +Date: Mon, 14 Sep 2009 13:12:01 +0000 +Subject: cp,mv: preserve extended attributes even for read-only files + +* src/copy.c (copy_reg): Temporarily set u+rw on the destination file +to allow GNU/Linux to set xattrs. +* tests/misc/xattr: Test that change. +Reported by Ernest N. Mamikonyan. +--- +diff --git a/src/copy.c b/src/copy.c +index f3ff5a2..ad2060b 100644 +--- a/src/copy.c ++++ b/src/copy.c +@@ -834,6 +834,24 @@ copy_reg (char const *src_name, char const *dst_name, + } + } + ++ /* To allow copying xattrs on read-only files, temporarily chmod u+rw. ++ This workaround is required as an inode permission check is done ++ by xattr_permission() in fs/xattr.c of the GNU/Linux kernel tree. */ ++ if (x->preserve_xattr) ++ { ++ bool access_changed = false; ++ ++ if (!(sb.st_mode & S_IWUSR) && geteuid() != 0) ++ access_changed = fchmod_or_lchmod (dest_desc, dst_name, 0600) == 0; ++ ++ if (!copy_attr_by_fd (src_name, source_desc, dst_name, dest_desc, x) ++ && x->require_preserve_xattr) ++ return_val = false; ++ ++ if (access_changed) ++ fchmod_or_lchmod (dest_desc, dst_name, dst_mode & ~omitted_permissions); ++ } ++ + if (x->preserve_ownership && ! SAME_OWNER_AND_GROUP (*src_sb, sb)) + { + switch (set_owner (x, dst_name, dest_desc, src_sb, *new_dst, &sb)) +@@ -850,11 +868,6 @@ copy_reg (char const *src_name, char const *dst_name, + + set_author (dst_name, dest_desc, src_sb); + +- if (x->preserve_xattr && ! copy_attr_by_fd (src_name, source_desc, +- dst_name, dest_desc, x) +- && x->require_preserve_xattr) +- return_val = false; +- + if (x->preserve_mode || x->move_mode) + { + if (copy_acl (src_name, source_desc, dst_name, dest_desc, src_mode) != 0 +diff --git a/tests/misc/xattr b/tests/misc/xattr +index a27e1f6..fcf7ceb 100755 +--- a/tests/misc/xattr ++++ b/tests/misc/xattr +@@ -29,7 +29,7 @@ fi + + # Skip this test if cp was built without xattr support: + touch src dest || framework_failure +-cp --preserve=xattr -n src dest 2>/dev/null \ ++cp --preserve=xattr -n src dest \ + || skip_test_ "coreutils built without xattr support" + + # this code was taken from test mv/backup-is-src +@@ -46,13 +46,13 @@ xattr_pair="$xattr_name=\"$xattr_value\"" + # create new file and check its xattrs + touch a || framework_failure + getfattr -d a >out_a || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_a >/dev/null && framework_failure ++grep -F "$xattr_pair" out_a && framework_failure + + # try to set user xattr on file + setfattr -n "$xattr_name" -v "$xattr_value" a >out_a \ + || skip_test_ "failed to set xattr of file" + getfattr -d a >out_a || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_a >/dev/null \ ++grep -F "$xattr_pair" out_a \ + || skip_test_ "failed to set xattr of file" + + fail=0 +@@ -60,36 +60,50 @@ fail=0 + # cp should not preserve xattr by default + cp a b || fail=1 + getfattr -d b >out_b || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_b >/dev/null && fail=1 ++grep -F "$xattr_pair" out_b && fail=1 + + # test if --preserve=xattr option works + cp --preserve=xattr a b || fail=1 + getfattr -d b >out_b || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_b >/dev/null || fail=1 ++grep -F "$xattr_pair" out_b || fail=1 + + #test if --preserve=all option works + cp --preserve=all a c || fail=1 + getfattr -d c >out_c || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_c >/dev/null || fail=1 ++grep -F "$xattr_pair" out_c || fail=1 + + #test if -a option works without any diagnostics + cp -a a d 2>err && test -s err && fail=1 + getfattr -d d >out_d || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_d >/dev/null || fail=1 ++grep -F "$xattr_pair" out_d || fail=1 ++ ++#test if --preserve=xattr works even for files without write access ++chmod a-w a || framework_failure ++rm -f e ++cp --preserve=xattr a e || fail=1 ++getfattr -d e >out_e || skip_test_ "failed to get xattr of file" ++grep -F "$xattr_pair" out_e || fail=1 ++ ++#Ensure that permission bits are preserved, too. ++src_perm=$(stat --format=%a a) ++dst_perm=$(stat --format=%a e) ++test "$dst_perm" = "$src_perm" || fail=1 ++ ++chmod u+w a || framework_failure + + rm b || framework_failure + + # install should never preserve xattr + ginstall a b || fail=1 + getfattr -d b >out_b || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_b >/dev/null && fail=1 ++grep -F "$xattr_pair" out_b && fail=1 + + # mv should preserve xattr when renaming within a file system. + # This is implicitly done by rename () and doesn't need explicit + # xattr support in mv. + mv a b || fail=1 + getfattr -d b >out_b || skip_test_ "failed to get xattr of file" +-grep -F "$xattr_pair" out_b >/dev/null || cat >&2 <&2 <out_a 2>/dev/null \ ++setfattr -n "$xattr_name" -v "$xattr_value" "$b_other" >out_a \ + || test_mv=0 +-getfattr -d "$b_other" >out_b 2>/dev/null || test_mv=0 +-grep -F "$xattr_pair" out_b >/dev/null || test_mv=0 ++getfattr -d "$b_other" >out_b || test_mv=0 ++grep -F "$xattr_pair" out_b || test_mv=0 + rm -f "$b_other" || framework_failure + + if test $test_mv -eq 1; then + # mv should preserve xattr when copying content from one partition to another + mv b "$b_other" || fail=1 +- getfattr -d "$b_other" >out_b 2>/dev/null || ++ getfattr -d "$b_other" >out_b || + skip_test_ "failed to get xattr of file" +- grep -F "$xattr_pair" out_b >/dev/null || fail=1 ++ grep -F "$xattr_pair" out_b || fail=1 + else + cat >&2 < - 7.6-2 +- fix copying of extended attributes for read only source + files + * Sat Sep 12 2009 Ondrej Vasik - 7.6-1 - new upstream bugfix release 7.6, removed applied patches, defuzzed the rest