1#!/bin/sh 2# Verify that cp -p preserves GID when it is possible. 3 4# Copyright (C) 2007-2023 Free Software Foundation, Inc. 5 6# This program is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <https://www.gnu.org/licenses/>. 18 19. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src 20print_ver_ cp 21 22require_perl_ 23require_root_ 24 25# Some of the tests expect a umask that grants group and/or world read access. 26working_umask_or_skip_ 27 28# Record primary group number, usually 0. 29# This is the group ID used when cp (without -p) creates a new file. 30primary_group_num=$(id -g) 31 32create() { 33 echo "$1" > "$1" || exit 1 34 chown "+$2:+$3" "$1" || exit 1 35} 36 37t0() { 38 f=$1; shift 39 u=$1; shift 40 g=$1; shift 41 rm -f b || exit 1 42 "$@" "$f" b || exit 1 43 s=$(stat -c '%u %g' b) 44 if test "x$s" != "x$u $g"; then 45 # Allow the actual group to match that of the parent directory 46 # (it was set to 0 above). 47 if test "x$s" = "x$u $primary_group_num"; then 48 : 49 else 50 echo "$0: $* $f b: $u $g != $s" 1>&2 51 Exit 1 52 fi 53 fi 54} 55 56nameless_uid=$($PERL -le ' 57 foreach my $i (1000..16*1024-1) 58 { 59 getpwuid $i or (print $i), exit 60 } 61') 62nameless_gid1=$($PERL -le ' 63 foreach my $i (1000..16*1024) 64 { 65 getgrgid $i or (print $i), exit 66 } 67') 68nameless_gid2=$($PERL -le ' 69 foreach my $i ('"$nameless_gid1"'+1..16*1024) 70 { 71 getgrgid $i or (print $i), exit 72 } 73') 74 75if test -z "$nameless_uid" \ 76 || test -z "$nameless_gid1" \ 77 || test -z "$nameless_gid2"; then 78 skip_ "couldn't find a nameless UID or GID" 79fi 80 81chown "+$nameless_uid:+0" . 82 83create a0 0 0 84create b0 "$nameless_uid" "$nameless_gid1" 85create b1 "$nameless_uid" "$nameless_gid2" 86create c0 0 "$nameless_gid1" 87create c1 0 "$nameless_gid2" 88 89t0 a0 0 0 cp 90t0 b0 0 0 cp 91t0 b1 0 0 cp 92t0 c0 0 0 cp 93t0 c1 0 0 cp 94 95t0 a0 0 0 cp -p 96t0 b0 "$nameless_uid" "$nameless_gid1" cp -p 97t0 b1 "$nameless_uid" "$nameless_gid2" cp -p 98t0 c0 0 "$nameless_gid1" cp -p 99t0 c1 0 "$nameless_gid2" cp -p 100 101# For the remaining tests, we need a cp binary that is accessible to a user 102# with UID of $nameless_uid. The build directory may not be accessible, 103# so create a temporary directory and copy cp into it, ensure that 104# $nameless_uid can access it and then make that directory the search path. 105tmp_path= 106cleanup_() { rm -rf "$tmp_path"; } 107 108# Cause mktemp to create a directory directly under /tmp. 109# Setting TMPDIR explicitly is required here, in case $TMPDIR 110# is not readable by our nameless IDs. 111test -d /tmp && TMPDIR=/tmp 112tmp_path=$(mktemp -d) || fail_ "failed to create temporary directory" 113if test -x "$abs_path_dir_/coreutils" && 114 { test -L "$abs_path_dir_/cp" || 115 test $(wc -l < "$abs_path_dir_/cp") = 1; } then 116 # if configured with --enable-single-binary we need to use the single binary 117 cp "$abs_path_dir_/coreutils" "$tmp_path/cp" || framework_failure_ 118else 119 cp "$abs_path_dir_/cp" "$tmp_path" 120fi 121chmod -R a+rx "$tmp_path" 122 123t1() { 124 f=$1; shift 125 u=$1; shift 126 g=$1; shift 127 t0 "$f" "$u" "$g" \ 128 chroot --skip-chdir \ 129 --user=+$nameless_uid:+$nameless_gid1 \ 130 --groups="+$nameless_gid1,+$nameless_gid2" \ 131 / env PATH="$tmp_path" "$@" 132} 133 134t1 a0 "$nameless_uid" "$nameless_gid1" cp 135t1 b0 "$nameless_uid" "$nameless_gid1" cp 136t1 b1 "$nameless_uid" "$nameless_gid1" cp 137t1 c0 "$nameless_uid" "$nameless_gid1" cp 138t1 c1 "$nameless_uid" "$nameless_gid1" cp 139 140t1 a0 "$nameless_uid" "$nameless_gid1" cp -p 141t1 b0 "$nameless_uid" "$nameless_gid1" cp -p 142t1 b1 "$nameless_uid" "$nameless_gid2" cp -p 143t1 c0 "$nameless_uid" "$nameless_gid1" cp -p 144t1 c1 "$nameless_uid" "$nameless_gid2" cp -p 145 146Exit $fail 147