xref: /freebsd/usr.sbin/chown/tests/chown_test.sh (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1#
2# Copyright (c) 2017 Dell EMC
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.
13#
14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24# SUCH DAMAGE.
25#
26
27get_filesystem()
28{
29	local mountpoint=$1
30
31	df -T $mountpoint | tail -n 1 | cut -wf 2
32}
33
34atf_test_case RH_flag
35RH_flag_head()
36{
37	atf_set	"descr" "Verify that setting ownership recursively via -R doesn't " \
38			"affect symlinks specified via the arguments when -H " \
39			"is specified"
40	atf_set "require.user" "root"
41}
42RH_flag_body()
43{
44	atf_check mkdir -p A/B
45	atf_check ln -s B A/C
46	atf_check chown -h 42:42 A/C
47	atf_check -o inline:'0:0\n0:0\n42:42\n' stat -f '%u:%g' A A/B A/C
48	atf_check chown -RH 84:84 A
49	atf_check -o inline:'84:84\n84:84\n84:84\n' stat -f '%u:%g' A A/B A/C
50	atf_check chown -RH 126:126 A/C
51	atf_check -o inline:'84:84\n126:126\n84:84\n' stat -f '%u:%g' A A/B A/C
52}
53
54atf_test_case RL_flag
55RL_flag_head()
56{
57	atf_set	"descr" "Verify that setting ownership recursively via -R doesn't " \
58			"affect symlinks specified via the arguments when -L " \
59			"is specified"
60	atf_set "require.user" "root"
61}
62RL_flag_body()
63{
64	atf_check mkdir -p A/B
65	atf_check ln -s B A/C
66	atf_check chown -h 42:42 A/C
67	atf_check -o inline:'0:0\n0:0\n42:42\n' stat -f '%u:%g' A A/B A/C
68	atf_check chown -RL 84:84 A
69	atf_check -o inline:'84:84\n84:84\n42:42\n' stat -f '%u:%g' A A/B A/C
70	atf_check chown -RL 126:126 A/C
71	atf_check -o inline:'84:84\n126:126\n42:42\n' stat -f '%u:%g' A A/B A/C
72}
73
74atf_test_case RP_flag
75RP_flag_head()
76{
77	atf_set	"descr" "Verify that setting ownership recursively via -R " \
78			"doesn't affect symlinks specified via the arguments " \
79			"when -P is specified"
80	atf_set "require.user" "root"
81}
82RP_flag_body()
83{
84	atf_check mkdir -p A/B
85	atf_check ln -s B A/C
86	atf_check chown -h 42:42 A/C
87	atf_check -o inline:'0:0\n0:0\n42:42\n' stat -f '%u:%g' A A/B A/C
88	atf_check chown -RP 84:84 A
89	atf_check -o inline:'84:84\n84:84\n84:84\n' stat -f '%u:%g' A A/B A/C
90	atf_check chown -RP 126:126 A/C
91	atf_check -o inline:'84:84\n84:84\n126:126\n' stat -f '%u:%g' A A/B A/C
92}
93
94atf_test_case f_flag cleanup
95f_flag_head()
96{
97	atf_set	"descr" "Verify that setting a mode for a file with -f " \
98			"doesn't emit an error message/exit with a non-zero " \
99			"code"
100	atf_set "require.user" "root"
101}
102
103f_flag_body()
104{
105	atf_check truncate -s 0 foo bar
106	atf_check chown 0:0 foo bar
107	case "$(get_filesystem .)" in
108	zfs)
109		atf_expect_fail "ZFS does not support UF_IMMUTABLE; returns EPERM"
110		;;
111	esac
112	atf_check chflags uchg foo
113	atf_check -e not-empty -s not-exit:0 chown 42:42 foo bar
114	atf_check -o inline:'0:0\n42:42\n' stat -f '%u:%g' foo bar
115	atf_check -s exit:0 chown -f 84:84 foo bar
116	atf_check -o inline:'0:0\n84:84\n' stat -f '%u:%g' foo bar
117}
118
119f_flag_cleanup()
120{
121	chflags 0 foo || :
122}
123
124atf_test_case h_flag
125h_flag_head()
126{
127	atf_set	"descr" "Verify that setting a mode for a file with -f " \
128			"doesn't emit an error message/exit with a non-zero " \
129			"code"
130	atf_set "require.user" "root"
131}
132
133h_flag_body()
134{
135	atf_check truncate -s 0 foo
136	atf_check -o inline:'0:0\n' stat -f '%u:%g' foo
137	atf_check ln -s foo bar
138	atf_check -o inline:'0:0\n0:0\n' stat -f '%u:%g' foo bar
139	atf_check chown -h 42:42 bar
140	atf_check -o inline:'0:0\n42:42\n' stat -f '%u:%g' foo bar
141	atf_check chown 84:84 bar
142	atf_check -o inline:'84:84\n42:42\n' stat -f '%u:%g' foo bar
143}
144
145atf_test_case v_flag
146v_flag_head()
147{
148	atf_set	"descr" "Verify that setting ownership with -v emits the " \
149			"file doesn't emit an error message/exit with a " \
150			"non-zero code"
151	atf_set "require.user" "root"
152}
153v_flag_body()
154{
155	atf_check truncate -s 0 foo bar
156	atf_check chown 0:0 foo
157	atf_check chown 42:42 bar
158	atf_check -o 'inline:bar\n' chown -v 0:0 foo bar
159	atf_check chown -v 0:0 foo bar
160	for f in foo bar; do
161		echo "$f: 0:0 -> 84:84";
162	done > output.txt
163	atf_check -o file:output.txt chown -vv 84:84 foo bar
164	atf_check chown -vv 84:84 foo bar
165}
166
167md_file="md.out"
168atf_test_case x_flag cleanup
169x_flag_head()
170{
171	atf_set	"descr" "Verify that setting a mode with -x doesn't set " \
172			"ownership across mountpoints"
173	atf_set "require.user" "root"
174}
175x_flag_body()
176{
177	atf_check -o save:$md_file mdconfig -a -t malloc -s 20m
178	if ! md_device=$(cat $md_file); then
179		atf_fail "cat $md_file failed"
180	fi
181	atf_check -o not-empty newfs /dev/$md_device
182	atf_check mkdir mnt
183	atf_check mount /dev/$md_device mnt
184	atf_check truncate -s 0 foo bar mnt/bazbaz
185	atf_check ln -s bar mnt/barbaz
186	atf_check ln -s ../foo mnt/foobaz
187	cd mnt
188	test_files="../foo ../bar barbaz bazbaz foobaz"
189	atf_check -o inline:'0:0\n0:0\n0:0\n0:0\n0:0\n' \
190	    stat -f '%u:%g' $test_files
191	atf_check chown -Rx 42:42 .
192	atf_check -o inline:'0:0\n0:0\n42:42\n42:42\n42:42\n' \
193	    stat -f '%u:%g' $test_files
194	atf_check chown -R 84:84 .
195	atf_check -o inline:'0:0\n0:0\n84:84\n84:84\n84:84\n' \
196	    stat -f '%u:%g' $test_files
197}
198x_flag_cleanup()
199{
200	if ! md_device=$(cat $md_file) || [ -z "$md_device" ]; then
201		echo "Couldn't get device from $md_file"
202		exit 0
203	fi
204	umount mnt
205	mdconfig -d -u $md_device
206}
207
208atf_init_test_cases()
209{
210	atf_add_test_case RH_flag
211	atf_add_test_case RL_flag
212	atf_add_test_case RP_flag
213	atf_add_test_case f_flag
214	atf_add_test_case h_flag
215	atf_add_test_case v_flag
216	atf_add_test_case x_flag
217}
218