1#!/bin/sh 2# Ensure that mv, cp -a and cp --preserve=xattr(all) options do work 3# as expected on file systems without their support and do show correct 4# diagnostics when required 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 23 24require_root_ 25 26cwd=$(pwd) 27cleanup_() { cd /; umount "$cwd/noxattr"; umount "$cwd/xattr"; } 28 29skip=0 30 31# Mount an ext2 loopback file system at $WHERE with $OPTS 32make_fs() { 33 where="$1" 34 opts="$2" 35 36 fs="$where.bin" 37 38 dd if=/dev/zero of="$fs" bs=8192 count=200 > /dev/null 2>&1 \ 39 || skip=1 40 mkdir "$where" || skip=1 41 mkfs -t ext2 -F "$fs" || 42 skip_ "failed to create ext2 file system" 43 mount -oloop,$opts "$fs" "$where" || skip=1 44 echo test > "$where"/f || skip=1 45 test -s "$where"/f || skip=1 46 47 test $skip = 1 && 48 skip_ "insufficient mount/ext2 support" 49} 50 51make_fs noxattr nouser_xattr 52make_fs xattr user_xattr 53 54# testing xattr name-value pair 55xattr_name="user.foo" 56xattr_value="bar" 57xattr_pair="$xattr_name=\"$xattr_value\"" 58 59echo test > xattr/a || framework_failure_ 60getfattr -d xattr/a >out_a || skip_ "failed to get xattr of file" 61grep -F "$xattr_pair" out_a >/dev/null && framework_failure_ 62setfattr -n "$xattr_name" -v "$xattr_value" xattr/a >out_a \ 63 || skip_ "failed to set xattr of file" 64getfattr -d xattr/a >out_a || skip_ "failed to get xattr of file" 65grep -F "$xattr_pair" out_a >/dev/null \ 66 || skip_ "failed to set xattr of file" 67 68 69# This should pass without diagnostics 70cp -a xattr/a noxattr/ 2>err || fail=1 71test -s noxattr/a || fail=1 # destination file must not be empty 72compare /dev/null err || fail=1 73 74rm -f err noxattr/a 75 76# This should pass without diagnostics (new file) 77cp --preserve=all xattr/a noxattr/ 2>err || fail=1 78test -s noxattr/a || fail=1 # destination file must not be empty 79compare /dev/null err || fail=1 80 81# This should pass without diagnostics (existing file) 82cp --preserve=all xattr/a noxattr/ 2>err || fail=1 83test -s noxattr/a || fail=1 # destination file must not be empty 84compare /dev/null err || fail=1 85 86rm -f err noxattr/a 87 88# This should fail with corresponding diagnostics 89cp -a --preserve=xattr xattr/a noxattr/ 2>err && fail=1 90if grep '^#define USE_XATTR 1' $CONFIG_HEADER > /dev/null; then 91cat <<\EOF > exp 92cp: setting attributes for 'noxattr/a': Operation not supported 93EOF 94else 95cat <<\EOF > exp 96cp: cannot preserve extended attributes, cp is built without xattr support 97EOF 98fi 99 100compare exp err || fail=1 101 102rm -f err noxattr/a 103 104# This should pass without diagnostics 105mv xattr/a noxattr/ 2>err || fail=1 106test -s noxattr/a || fail=1 # destination file must not be empty 107compare /dev/null err || fail=1 108 109# This should pass and copy xattrs of the symlink 110# since the xattrs used here are not in the 'user.' namespace. 111# Up to and including coreutils-8.22 xattrs of symlinks 112# were not copied across file systems. 113ln -s 'foo' xattr/symlink || framework_failure_ 114# Note 'user.' namespace is only supported on regular files/dirs 115# so use the 'trusted.' namespace here 116txattr='trusted.overlay.whiteout' 117if setfattr -hn "$txattr" -v y xattr/symlink; then 118 # Note only root can read the 'trusted.' namespace 119 if getfattr -h -m- -d xattr/symlink | grep -F "$txattr"; then 120 mv xattr/symlink noxattr/ 2>err || fail=1 121 if grep '^#define USE_XATTR 1' $CONFIG_HEADER > /dev/null; then 122 getfattr -h -m- -d noxattr/symlink | grep -F "$txattr" || fail=1 123 fi 124 compare /dev/null err || fail=1 125 else 126 echo "failed to get '$txattr' xattr. skipping symlink check" >&2 127 fi 128else 129 echo "failed to set '$txattr' xattr. skipping symlink check" >&2 130fi 131 132Exit $fail 133