xref: /freebsd/usr.sbin/extattr/tests/extattr_test.sh (revision a907c6914c5879870b2597a63253cea0a5b7bdb8)
1#
2# Copyright (c) 2016 Spectra Logic Corp
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# $FreeBSD$
27
28atf_test_case bad_namespace
29bad_namespace_head() {
30	atf_set "descr" "Can't set attributes for nonexistent namespaces"
31}
32bad_namespace_body() {
33	touch foo
34	atf_check -s not-exit:0 -e match:"Invalid argument" \
35		setextattr badnamespace myattr X foo
36	atf_check -s not-exit:0 -e match:"Invalid argument" \
37		lsextattr -q badnamespace foo
38}
39
40atf_test_case hex
41hex_head() {
42	atf_set "descr" "Set and get attribute values in hexadecimal"
43}
44hex_body() {
45	touch foo
46	atf_check -s exit:0 -o empty setextattr user myattr1 XYZ foo
47	atf_check -s exit:0 -o inline:"58 59 5a\n" \
48		getextattr -qx user myattr1 foo
49}
50
51atf_test_case long_name
52long_name_head() {
53	atf_set "descr" "A maximum length attribute name"
54}
55long_name_body() {
56	# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208965
57	atf_expect_fail "BUG 208965 extattr(2) doesn't allow maxlen attr names"
58
59	ATTRNAME=`jot -b X -s "" 255 0`
60	touch foo
61	atf_check -s exit:0 -o empty setextattr user $ATTRNAME myvalue foo
62	atf_check -s exit:0 -o inline:"${ATTRNAME}\n" lsextattr -q user foo
63	atf_check -s exit:0 -o inline:"myvalue\n" \
64		getextattr -q user ${ATTRNAME} foo
65	atf_check -s exit:0 -o empty rmextattr user ${ATTRNAME} foo
66	atf_check -s exit:0 -o empty lsextattr -q user foo
67}
68
69atf_test_case noattrs
70noattrs_head() {
71	atf_set "descr" "A file with no extended attributes"
72}
73noattrs_body() {
74	touch foo
75	atf_check -s exit:0 -o empty lsextattr -q user foo
76}
77
78atf_test_case nonexistent_file
79nonexistent_file_head() {
80	atf_set "descr" "A file that does not exist"
81}
82nonexistent_file_body() {
83	atf_check -s exit:1 -e match:"No such file or directory" \
84		lsextattr user foo
85	atf_check -s exit:1 -e match:"No such file or directory" \
86		setextattr user myattr myvalue foo
87	atf_check -s exit:1 -e match:"No such file or directory" \
88		getextattr user myattr foo
89	atf_check -s exit:1 -e match:"No such file or directory" \
90		rmextattr user myattr foo
91}
92
93atf_test_case null
94null_head() {
95	atf_set "descr" "NUL-terminate an attribute value"
96}
97null_body() {
98	touch foo
99	atf_check -s exit:0 -o empty setextattr -n user myattr myvalue foo
100	atf_check -s exit:0 -o inline:"myvalue\0\n" getextattr -q user myattr foo
101}
102
103atf_test_case one_user_attr
104one_user_attr_head() {
105	atf_set "descr" "A file with one extended attribute"
106}
107one_user_attr_body() {
108	touch foo
109	atf_check -s exit:0 -o empty setextattr user myattr myvalue foo
110	atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q user foo
111	atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q user myattr foo
112	atf_check -s exit:0 -o empty rmextattr user myattr foo
113	atf_check -s exit:0 -o empty lsextattr -q user foo
114}
115
116atf_test_case one_system_attr
117one_system_attr_head() {
118	atf_set "descr" "A file with one extended attribute"
119	atf_set "require.user" "root"
120}
121one_system_attr_body() {
122	touch foo
123	atf_check -s exit:0 -o empty setextattr system myattr myvalue foo
124	atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q system foo
125	atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q system myattr foo
126	atf_check -s exit:0 -o empty rmextattr system myattr foo
127	atf_check -s exit:0 -o empty lsextattr -q system foo
128}
129
130atf_test_case stringify
131stringify_head() {
132	atf_set "descr" "Stringify the output of getextattr"
133}
134stringify_body() {
135	touch foo
136	atf_check -s exit:0 -o empty setextattr user myattr "my value" foo
137	atf_check -s exit:0 -o inline:"\"my\\\040value\"\n" \
138		getextattr -qs user myattr foo
139}
140
141atf_test_case symlink
142symlink_head() {
143	atf_set "descr" "A symlink to an ordinary file"
144}
145symlink_body() {
146	touch foo
147	ln -s foo foolink
148	atf_check -s exit:0 -o empty setextattr user myattr myvalue foolink
149	atf_check -s exit:0 -o inline:"myvalue\n" \
150		getextattr -q user myattr foolink
151	atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q user myattr foo
152}
153
154atf_test_case symlink_nofollow
155symlink_nofollow_head() {
156	atf_set "descr" "Operating directly on a symlink"
157}
158symlink_nofollow_body() {
159	touch foo
160	ln -s foo foolink
161	# Check that with -h we can operate directly on the link
162	atf_check -s exit:0 -o empty setextattr -h user myattr myvalue foolink
163	atf_check -s exit:0 -o inline:"myvalue\n" \
164		getextattr -qh user myattr foolink
165	atf_check -s exit:1 -e match:"Attribute not found" \
166		getextattr user myattr foolink
167	atf_check -s exit:1 -e match:"Attribute not found" \
168		getextattr user myattr foo
169
170	# Check that with -h we cannot operate on the destination file
171	atf_check -s exit:0 -o empty setextattr user otherattr othervalue foo
172	atf_check -s exit:1 getextattr -qh user otherattr foolink
173}
174
175atf_test_case system_and_user_attrs
176system_and_user_attrs_head() {
177	atf_set "descr" "A file with both system and user extended attributes"
178	atf_set "require.user" "root"
179}
180system_and_user_attrs_body() {
181	touch foo
182	atf_check -s exit:0 -o empty setextattr user userattr userval foo
183	atf_check -s exit:0 -o empty setextattr system sysattr sysval foo
184	atf_check -s exit:0 -o inline:"userattr\n" lsextattr -q user foo
185	atf_check -s exit:0 -o inline:"sysattr\n" lsextattr -q system foo
186
187	atf_check -s exit:0 -o inline:"userval\n" getextattr -q user userattr foo
188	atf_check -s exit:0 -o inline:"sysval\n" getextattr -q system sysattr foo
189	atf_check -s exit:0 -o empty rmextattr user userattr foo
190	atf_check -s exit:0 -o empty rmextattr system sysattr foo
191	atf_check -s exit:0 -o empty lsextattr -q user foo
192	atf_check -s exit:0 -o empty lsextattr -q system foo
193}
194
195atf_test_case two_files
196two_files_head() {
197	atf_set "descr" "Manipulate two files"
198}
199two_files_body() {
200	touch foo bar
201	atf_check -s exit:0 -o empty setextattr user myattr myvalue foo bar
202	atf_check -s exit:0 -o inline:"foo\tmyattr\nbar\tmyattr\n" \
203		lsextattr user foo bar
204	atf_check -s exit:0 \
205		-o inline:"foo\tmyvalue\nbar\tmyvalue\n" \
206		getextattr user myattr foo bar
207	atf_check -s exit:0 -o empty rmextattr user myattr foo bar
208	atf_check -s exit:0 -o empty lsextattr -q user foo bar
209}
210
211atf_test_case two_files_force
212two_files_force_head() {
213	atf_set "descr" "Manipulate two files.  The first does not exist"
214}
215two_files_force_body() {
216	touch bar
217	atf_check -s exit:1 -e match:"No such file or directory" \
218		setextattr user myattr myvalue foo bar
219	atf_check -s exit:0 -e ignore setextattr -f user myattr myvalue foo bar
220	atf_check -s exit:1 -e match:"No such file or directory" \
221		lsextattr user foo bar
222	atf_check -s exit:0 -e ignore -o inline:"bar\tmyattr\n" \
223		lsextattr -f user foo bar
224	atf_check -s exit:1 -e match:"No such file or directory" \
225		getextattr user myattr foo bar
226	atf_check -s exit:0 -e ignore \
227		-o inline:"bar\tmyvalue\n" \
228		getextattr -f user myattr foo bar
229	atf_check -s exit:1 -e match:"No such file or directory" \
230		rmextattr user myattr foo bar
231	atf_check -s exit:0 -e ignore \
232		rmextattr -f user myattr foo bar
233	atf_check -s exit:0 -o empty lsextattr -q user bar
234}
235
236atf_test_case two_user_attrs
237two_user_attrs_head() {
238	atf_set "descr" "A file with two extended attributes"
239}
240two_user_attrs_body() {
241	touch foo
242	atf_check -s exit:0 -o empty setextattr user myattr1 myvalue1 foo
243	atf_check -s exit:0 -o empty setextattr user myattr2 myvalue2 foo
244	# lsextattr could return the attributes in any order, so we must be
245	# careful how we compare them.
246	raw_output=`lsextattr -q user foo` || atf_fail "lsextattr failed"
247	tabless_output=`printf "%s %s" ${raw_output}`
248	if [ "myattr1 myattr2" != "${tabless_output}" -a \
249	     "myattr2 myattr1" != "${tabless_output}" ]; then
250		atf_fail "lsextattr printed ${tabless_output}"
251	fi
252	atf_check -s exit:0 -o inline:"myvalue1\n" getextattr -q user myattr1 foo
253	atf_check -s exit:0 -o inline:"myvalue2\n" getextattr -q user myattr2 foo
254	atf_check -s exit:0 -o empty rmextattr user myattr2 foo
255	atf_check -s exit:0 -o empty rmextattr user myattr1 foo
256	atf_check -s exit:0 -o empty lsextattr -q user foo
257}
258
259atf_test_case unprivileged_user_cannot_set_system_attr
260unprivileged_user_cannot_set_system_attr_head() {
261	atf_set "descr" "Unprivileged users can't set system attributes"
262        atf_set "require.user" "unprivileged"
263}
264unprivileged_user_cannot_set_system_attr_body() {
265	touch foo
266	atf_check -s exit:1 -e match:"Operation not permitted" \
267		setextattr system myattr myvalue foo
268}
269
270
271atf_init_test_cases() {
272	# TODO: add test cases for verbose output (without -q)
273	atf_add_test_case bad_namespace
274	atf_add_test_case hex
275	atf_add_test_case long_name
276	atf_add_test_case noattrs
277	atf_add_test_case nonexistent_file
278	atf_add_test_case null
279	atf_add_test_case symlink_nofollow
280	atf_add_test_case one_user_attr
281	atf_add_test_case one_system_attr
282	atf_add_test_case stringify
283	atf_add_test_case symlink
284	atf_add_test_case symlink_nofollow
285	atf_add_test_case system_and_user_attrs
286	atf_add_test_case two_files
287	atf_add_test_case two_files_force
288	atf_add_test_case two_user_attrs
289	atf_add_test_case unprivileged_user_cannot_set_system_attr
290}
291