1#!/bin/sh
2# Ensure that cp --preserve=xattr, cp --preserve=all and mv preserve extended
3# attributes and install does not preserve extended attributes.
4# cp -a should preserve xattr, error diagnostics should not be displayed
5
6# Copyright (C) 2009-2023 Free Software Foundation, Inc.
7
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17
18# You should have received a copy of the GNU General Public License
19# along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
21. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
22print_ver_ cp mv ginstall
23
24# Skip this test if cp was built without xattr support:
25touch src dest || framework_failure_
26cp --preserve=xattr -n src dest \
27  || skip_ "coreutils built without xattr support"
28
29# this code was taken from test mv/backup-is-src
30cleanup_() { rm -rf "$other_partition_tmpdir"; }
31. "$abs_srcdir/tests/other-fs-tmpdir"
32b_other="$other_partition_tmpdir/b"
33rm -f "$b_other" || framework_failure_
34
35# testing xattr name-value pair
36xattr_name="user.foo"
37xattr_value="bar"
38xattr_pair="$xattr_name=\"$xattr_value\""
39
40# create new file and check its xattrs
41touch a || framework_failure_
42getfattr -d a >out_a || skip_ "failed to get xattr of file"
43grep -F "$xattr_pair" out_a && framework_failure_
44
45# try to set user xattr on file
46setfattr -n "$xattr_name" -v "$xattr_value" a >out_a \
47  || skip_ "failed to set xattr of file"
48getfattr -d a >out_a || skip_ "failed to get xattr of file"
49grep -F "$xattr_pair" out_a \
50  || skip_ "failed to set xattr of file"
51
52
53# cp should not preserve xattr by default
54cp a b || fail=1
55getfattr -d b >out_b || skip_ "failed to get xattr of file"
56grep -F "$xattr_pair" out_b && fail=1
57
58# test if --preserve=xattr option works
59cp --preserve=xattr a b || fail=1
60getfattr -d b >out_b || skip_ "failed to get xattr of file"
61grep -F "$xattr_pair" out_b || fail=1
62
63# test if --preserve=all option works
64cp --preserve=all a c || fail=1
65getfattr -d c >out_c || skip_ "failed to get xattr of file"
66grep -F "$xattr_pair" out_c || fail=1
67
68# cp's -a option must produce no diagnostics.
69cp -a a d 2>err && { compare /dev/null err || fail=1; }
70getfattr -d d >out_d || skip_ "failed to get xattr of file"
71grep -F "$xattr_pair" out_d || fail=1
72
73# test if --preserve=xattr works even for files without write access
74chmod a-w a || framework_failure_
75rm -f e
76cp --preserve=xattr a e || fail=1
77getfattr -d e >out_e || skip_ "failed to get xattr of file"
78grep -F "$xattr_pair" out_e || fail=1
79
80# Ensure that permission bits are preserved, too.
81src_perm=$(stat --format=%a a)
82dst_perm=$(stat --format=%a e)
83test "$dst_perm" = "$src_perm" || fail=1
84
85chmod u+w a || framework_failure_
86
87rm b || framework_failure_
88
89# install should never preserve xattr
90ginstall a b || fail=1
91getfattr -d b >out_b || skip_ "failed to get xattr of file"
92grep -F "$xattr_pair" out_b && fail=1
93
94# mv should preserve xattr when renaming within a file system.
95# This is implicitly done by rename () and doesn't need explicit
96# xattr support in mv.
97mv a b || fail=1
98getfattr -d b >out_b || skip_ "failed to get xattr of file"
99grep -F "$xattr_pair" out_b || cat >&2 <<EOF
100=================================================================
101$0: WARNING!!!
102rename () does not preserve extended attributes
103=================================================================
104EOF
105
106# try to set user xattr on file on other partition
107test_mv=1
108touch "$b_other" || framework_failure_
109setfattr -n "$xattr_name" -v "$xattr_value" "$b_other" >out_a \
110  || test_mv=0
111getfattr -d "$b_other" >out_b || test_mv=0
112grep -F "$xattr_pair" out_b || test_mv=0
113rm -f "$b_other" || framework_failure_
114
115if test $test_mv -eq 1; then
116  # mv should preserve xattr when copying content from one partition to another
117  mv b "$b_other" || fail=1
118  getfattr -d "$b_other" >out_b ||
119    skip_ "failed to get xattr of file"
120  grep -F "$xattr_pair" out_b || fail=1
121else
122  cat >&2 <<EOF
123=================================================================
124$0: WARNING!!!
125failed to set xattr of file $b_other
126=================================================================
127EOF
128fi
129
130Exit $fail
131