1#
2# Copyright (c) 2016 Jilles Tjoelker
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#
27
28copy_to_nonexistent_with_opts() {
29	printf 'test\n123\r456\r\n789\0z' >testf
30	atf_check install "$@" testf copyf
31	cmp testf copyf || atf_fail "bad copy"
32	[ ! testf -nt copyf ] || atf_fail "bad timestamp"
33	[ ! -e copyf.bak ] || atf_fail "no backup expected"
34}
35
36atf_test_case copy_to_nonexistent
37copy_to_nonexistent_body() {
38	copy_to_nonexistent_with_opts
39}
40
41atf_test_case copy_to_nonexistent_safe
42copy_to_nonexistent_safe_body() {
43	copy_to_nonexistent_with_opts -S
44}
45
46atf_test_case copy_to_nonexistent_comparing
47copy_to_nonexistent_comparing_body() {
48	copy_to_nonexistent_with_opts -C
49}
50
51atf_test_case copy_to_nonexistent_safe_comparing
52copy_to_nonexistent_safe_comparing_body() {
53	copy_to_nonexistent_with_opts -S -C
54}
55
56atf_test_case copy_to_nonexistent_backup
57copy_to_nonexistent_backup_body() {
58	copy_to_nonexistent_with_opts -b -B.bak
59}
60
61atf_test_case copy_to_nonexistent_backup_safe
62copy_to_nonexistent_backup_safe_body() {
63	copy_to_nonexistent_with_opts -b -B.bak -S
64}
65
66atf_test_case copy_to_nonexistent_preserving
67copy_to_nonexistent_preserving_body() {
68	copy_to_nonexistent_with_opts -p
69	[ ! testf -ot copyf ] || atf_fail "bad timestamp 2"
70}
71
72copy_self_with_opts() {
73	printf 'test\n123\r456\r\n789\0z' >testf
74	printf 'test\n123\r456\r\n789\0z' >testf2
75	atf_check -s not-exit:0 -o empty -e match:. install "$@" testf testf
76	cmp testf testf2 || atf_fail "file changed after self-copy attempt"
77}
78
79atf_test_case copy_self
80copy_self_body() {
81	copy_self_with_opts
82}
83
84atf_test_case copy_self_safe
85copy_self_safe_body() {
86	copy_self_with_opts -S
87}
88
89atf_test_case copy_self_comparing
90copy_self_comparing_body() {
91	copy_self_with_opts -C
92}
93
94atf_test_case copy_self_safe_comparing
95copy_self_safe_comparing_body() {
96	copy_self_with_opts -S -C
97}
98
99overwrite_with_opts() {
100	printf 'test\n123\r456\r\n789\0z' >testf
101	printf 'test\n123\r456\r\n789\0w' >otherf
102	atf_check install "$@" testf otherf
103	cmp testf otherf || atf_fail "bad overwrite"
104	[ ! testf -nt otherf ] || atf_fail "bad timestamp"
105}
106
107atf_test_case overwrite
108overwrite_body() {
109	overwrite_with_opts
110}
111
112atf_test_case overwrite_safe
113overwrite_safe_body() {
114	overwrite_with_opts -S
115}
116
117atf_test_case overwrite_comparing
118overwrite_comparing_body() {
119	overwrite_with_opts -C
120}
121
122atf_test_case overwrite_safe_comparing
123overwrite_safe_comparing_body() {
124	overwrite_with_opts -S -C
125}
126
127overwrite_eq_with_opts() {
128	printf 'test\n123\r456\r\n789\0z' >testf
129	printf 'test\n123\r456\r\n789\0z' >otherf
130	atf_check install "$@" testf otherf
131	cmp testf otherf || atf_fail "bad overwrite"
132	[ ! testf -nt otherf ] || atf_fail "bad timestamp"
133}
134
135atf_test_case overwrite_eq
136overwrite_eq_body() {
137	overwrite_eq_with_opts
138}
139
140atf_test_case overwrite_eq_safe
141overwrite_eq_safe_body() {
142	overwrite_eq_with_opts -S
143}
144
145atf_test_case overwrite_eq_comparing
146overwrite_eq_comparing_body() {
147	overwrite_eq_with_opts -C
148}
149
150atf_test_case overwrite_eq_safe_comparing
151overwrite_eq_safe_comparing_body() {
152	overwrite_eq_with_opts -S -C
153}
154
155overwrite_backup_with_opts() {
156	printf 'test\n123\r456\r\n789\0z' >testf
157	printf 'test\n123\r456\r\n789\0w' >otherf
158	printf 'test\n123\r456\r\n789\0w' >otherf2
159	atf_check install -b -B.bak "$@" testf otherf
160	cmp testf otherf || atf_fail "bad overwrite"
161	[ ! testf -nt otherf ] || atf_fail "bad timestamp"
162	cmp otherf.bak otherf2 || atf_fail "bad backup"
163}
164
165atf_test_case overwrite_backup
166overwrite_backup_body() {
167	overwrite_backup_with_opts
168}
169
170atf_test_case overwrite_backup_safe
171overwrite_backup_safe_body() {
172	overwrite_backup_with_opts -S
173}
174
175atf_test_case overwrite_backup_comparing
176overwrite_backup_comparing_body() {
177	overwrite_backup_with_opts -C
178}
179
180atf_test_case overwrite_backup_safe_comparing
181overwrite_backup_safe_comparing_body() {
182	overwrite_backup_with_opts -S -C
183}
184
185setup_stripbin() {
186	cat <<\STRIPBIN >stripbin
187#!/bin/sh
188[ "$1" = "-o" ] && dst="$2" && shift 2
189[ "$1" = "--" ] && shift
190[ -z "$dst" ] && dst="$1"
191STRIPBIN
192	[ "$1" = "true" ] && cmd="cat" || cmd="tr z @"
193	echo $cmd '<"$1" >"$1.new" && mv -- "$1.new" "$dst"' >>stripbin
194	chmod 755 stripbin
195	export STRIPBIN="$PWD/stripbin"
196}
197
198strip_changing_with_opts() {
199	setup_stripbin
200	printf 'test\n123\r456\r\n789\0z' >testf
201	atf_check install -s "$@" testf copyf
202	[ ! testf -nt copyf ] || atf_fail "bad timestamp"
203	printf 'test\n123\r456\r\n789\0@' >otherf
204	cmp otherf copyf || atf_fail "bad stripped copy"
205}
206
207atf_test_case strip_changing
208strip_changing_body() {
209	strip_changing_with_opts
210}
211
212atf_test_case strip_changing_comparing
213strip_changing_comparing_body() {
214	strip_changing_with_opts -C
215}
216
217strip_changing_overwrite_with_opts() {
218	setup_stripbin
219	printf 'test\n123\r456\r\n789\0z' >testf
220	printf 'test\n123\r456\r\n789\0w' >copyf
221	atf_check install -s "$@" testf copyf
222	[ ! testf -nt copyf ] || atf_fail "bad timestamp"
223	printf 'test\n123\r456\r\n789\0@' >otherf
224	cmp otherf copyf || atf_fail "bad stripped copy"
225}
226
227atf_test_case strip_changing_overwrite
228strip_changing_overwrite_body() {
229	strip_changing_overwrite_with_opts
230}
231
232atf_test_case strip_changing_overwrite_comparing
233strip_changing_overwrite_comparing_body() {
234	strip_changing_overwrite_with_opts -C
235}
236
237strip_changing_overwrite_eq_with_opts() {
238	setup_stripbin
239	printf 'test\n123\r456\r\n789\0z' >testf
240	printf 'test\n123\r456\r\n789\0@' >copyf
241	atf_check install -s "$@" testf copyf
242	[ ! testf -nt copyf ] || atf_fail "bad timestamp"
243	printf 'test\n123\r456\r\n789\0@' >otherf
244	cmp otherf copyf || atf_fail "bad stripped copy"
245}
246
247atf_test_case strip_changing_overwrite_eq
248strip_changing_overwrite_eq_body() {
249	strip_changing_overwrite_eq_with_opts
250}
251
252atf_test_case strip_changing_overwrite_eq_comparing
253strip_changing_overwrite_eq_comparing_body() {
254	strip_changing_overwrite_eq_with_opts -C
255}
256
257atf_test_case strip_noop
258strip_noop_body() {
259	setup_stripbin true
260	printf 'test\n123\r456\r\n789\0z' >testf
261	atf_check install -s testf copyf
262	[ ! testf -nt copyf ] || atf_fail "bad timestamp"
263	printf 'test\n123\r456\r\n789\0z' >otherf
264	cmp otherf copyf || atf_fail "bad stripped copy"
265}
266
267atf_test_case hard_link
268hard_link_body() {
269	printf 'test\n123\r456\r\n789\0z' >testf
270	atf_check install -l h testf copyf
271	[ testf -ef copyf ] || atf_fail "not same file"
272	[ ! -L copyf ] || atf_fail "copy is symlink"
273}
274
275atf_test_case symbolic_link
276symbolic_link_body() {
277	printf 'test\n123\r456\r\n789\0z' >testf
278	atf_check install -l s testf copyf
279	[ testf -ef copyf ] || atf_fail "not same file"
280	[ -L copyf ] || atf_fail "copy is not symlink"
281}
282
283atf_test_case symbolic_link_absolute
284symbolic_link_absolute_body() {
285	printf 'test\n123\r456\r\n789\0z' >testf
286	atf_check install -l sa testf copyf
287	[ testf -ef copyf ] || atf_fail "not same file"
288	[ -L copyf ] || atf_fail "copy is not symlink"
289	copyf_path=$(readlink copyf)
290	testf_path="$(pwd -P)/testf"
291	if [ "$copyf_path" != "$testf_path" ]; then
292		atf_fail "unexpected symlink contents ('$copyf_path' != '$testf_path')"
293	fi
294}
295
296atf_test_case symbolic_link_relative
297symbolic_link_relative_body() {
298	printf 'test\n123\r456\r\n789\0z' >testf
299	atf_check install -l sr testf copyf
300	[ testf -ef copyf ] || atf_fail "not same file"
301	[ -L copyf ] || atf_fail "copy is not symlink"
302	copyf_path=$(readlink copyf)
303	testf_path="testf"
304	if [ "$copyf_path" != "$testf_path" ]; then
305		atf_fail "unexpected symlink contents ('$copyf_path' != '$testf_path')"
306	fi
307}
308
309atf_test_case symbolic_link_relative_absolute_source_and_dest1
310symbolic_link_relative_absolute_source_and_dest1_head() {
311	atf_set "descr" "Verify -l rs with absolute paths (.../copyf -> .../a/b/c/testf)"
312}
313symbolic_link_relative_absolute_source_and_dest1_body() {
314	src_path=a/b/c/testf
315	src_path_prefixed=$PWD/$src_path
316	dest_path=$PWD/copyf
317
318	atf_check mkdir -p a/b/c
319	atf_check touch $src_path
320	atf_check install -l sr $src_path_prefixed $dest_path
321	[ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file"
322	[ -L $dest_path ] || atf_fail "copy is not symlink"
323	dest_path_relative=$(readlink $dest_path)
324	src_path_relative="$src_path"
325	if [ "$src_path_relative" != "$dest_path_relative" ]; then
326		atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
327	fi
328}
329
330atf_test_case symbolic_link_relative_absolute_source_and_dest1_double_slash
331symbolic_link_relative_absolute_source_and_dest1_double_slash_head() {
332	atf_set "descr" "Verify -l rs with absolute paths (.../copyf -> .../a/b/c/testf), using double-slashes"
333}
334symbolic_link_relative_absolute_source_and_dest1_double_slash_body() {
335	src_path=a//b//c//testf
336	src_path_prefixed=$PWD/$src_path
337	dest_path=$PWD/copyf
338
339	atf_check mkdir -p a/b/c
340	atf_check touch $src_path
341	atf_check install -l sr $src_path_prefixed $dest_path
342	[ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file"
343	[ -L $dest_path ] || atf_fail "copy is not symlink"
344	dest_path_relative=$(readlink $dest_path)
345	src_path_relative="$(echo $src_path | sed -e 's,//,/,g')"
346	if [ "$src_path_relative" != "$dest_path_relative" ]; then
347		atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
348	fi
349}
350
351atf_test_case symbolic_link_relative_absolute_source_and_dest2
352symbolic_link_relative_absolute_source_and_dest2_head() {
353	atf_set "descr" "Verify -l rs with absolute paths (.../a/b/c/copyf -> .../testf)"
354}
355symbolic_link_relative_absolute_source_and_dest2_body() {
356	src_path=testf
357	src_path_prefixed=$PWD/$src_path
358	dest_path=$PWD/a/b/c/copyf
359
360	atf_check mkdir -p a/b/c
361	atf_check touch $src_path
362	atf_check install -l sr $src_path_prefixed $dest_path
363	[ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file"
364	[ -L $dest_path ] || atf_fail "copy is not symlink"
365	dest_path_relative=$(readlink $dest_path)
366	src_path_relative="../../../$src_path"
367	if [ "$src_path_relative" != "$dest_path_relative" ]; then
368		atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
369	fi
370}
371
372atf_test_case mkdir_simple
373mkdir_simple_body() {
374	atf_check install -d dir1/dir2
375	[ -d dir1 ] || atf_fail "dir1 missing"
376	[ -d dir1/dir2 ] || atf_fail "dir2 missing"
377	atf_check install -d dir1/dir2/dir3
378	[ -d dir1/dir2/dir3 ] || atf_fail "dir3 missing"
379	atf_check install -d dir1
380	atf_check install -d dir1/dir2/dir3
381}
382
383atf_test_case symbolic_link_relative_absolute_common
384symbolic_link_relative_absolute_common_head() {
385	atf_set "descr" "Verify -l rs with absolute paths having common components"
386}
387symbolic_link_relative_absolute_common_body() {
388	filename=foo.so
389	src_path=lib
390	src_path_prefixed=$PWD/$src_path
391	dest_path=$PWD/libexec/
392	src_file=$src_path_prefixed/$filename
393	dest_file=$dest_path/$filename
394
395	atf_check mkdir $src_path_prefixed $dest_path
396	atf_check touch $src_file
397	atf_check install -l sr $src_file $dest_path
398
399	dest_path_relative=$(readlink $dest_file)
400	src_path_relative="../lib/$filename"
401	if [ "$src_path_relative" != "$dest_path_relative" ]; then
402		atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
403	fi
404}
405
406atf_test_case set_owner_group_mode
407set_owner_group_mode_head() {
408	atf_set "require.user" "root"
409}
410set_owner_group_mode_body() {
411	local fu=65531 fg=65531
412	local cu=65532 cg=65532
413	local u="$(id -u)"
414	local g="$(id -g)"
415	local m=0755 cm=4444
416	printf "test" >testf
417	atf_check chown "$fu:$fg" testf
418	atf_check chmod "$m" testf
419
420	atf_check install testf testc
421	atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
422
423	atf_check install -o "$cu" testf testc
424	atf_check_equal "$cu:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
425
426	atf_check install -g "$cg" testf testc
427	atf_check_equal "$u:$cg:10$m" "$(stat -f"%u:%g:%p" testc)"
428
429	atf_check install -o "$cu" -g "$cg" testf testc
430	atf_check_equal "$cu:$cg:10$m" "$(stat -f"%u:%g:%p" testc)"
431
432	atf_check install -m "$cm" testf testc
433	atf_check_equal "$u:$g:10$cm" "$(stat -f"%u:%g:%p" testc)"
434
435	atf_check install -o "$cu" -m "$cm" testf testc
436	atf_check_equal "$cu:$g:10$cm" "$(stat -f"%u:%g:%p" testc)"
437
438	atf_check install -g "$cg" -m "$cm" testf testc
439	atf_check_equal "$u:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)"
440
441	atf_check install -o "$cu" -g "$cg" -m "$cm" testf testc
442	atf_check_equal "$cu:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)"
443}
444
445atf_test_case set_owner_group_mode_unpriv
446set_owner_group_mode_unpriv_head() {
447	atf_set "require.user" "root"
448}
449set_owner_group_mode_unpriv_body() {
450	local fu=65531 fg=65531
451	local cu=65532 cg=65532
452	local u="$(id -u)"
453	local g="$(id -g)"
454	local m=0755 cm=4444 cM=0444
455	printf "test" >testf
456	atf_check chown "$fu:$fg" testf
457	atf_check chmod "$m" testf
458
459	atf_check install -U testf testc
460	atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
461
462	atf_check install -U -o "$cu" testf testc
463	atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
464
465	atf_check install -U -g "$cg" testf testc
466	atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
467
468	atf_check install -U -o "$cu" -g "$cg" testf testc
469	atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
470
471	atf_check install -U -m "$cm" testf testc
472	atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
473
474	atf_check install -U -o "$cu" -m "$cm" testf testc
475	atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
476
477	atf_check install -U -g "$cg" -m "$cm" testf testc
478	atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
479
480	atf_check install -U -o "$cu" -g "$cg" -m "$cm" testf testc
481	atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
482}
483
484atf_test_case set_optional_exec
485set_optional_exec_head() {
486	atf_set "require.user" "unprivileged"
487}
488set_optional_exec_body()
489{
490	echo "abc" > testfile.src
491
492	atf_check install -d -m ug+rX testdir
493	atf_check test -x testdir
494
495	atf_check install -m ug+rX testfile.src testfile
496	atf_check test ! -x testfile
497}
498
499atf_init_test_cases() {
500	atf_add_test_case copy_to_nonexistent
501	atf_add_test_case copy_to_nonexistent_safe
502	atf_add_test_case copy_to_nonexistent_comparing
503	atf_add_test_case copy_to_nonexistent_safe_comparing
504	atf_add_test_case copy_to_nonexistent_backup
505	atf_add_test_case copy_to_nonexistent_backup_safe
506	atf_add_test_case copy_to_nonexistent_preserving
507	atf_add_test_case copy_self
508	atf_add_test_case copy_self_safe
509	atf_add_test_case copy_self_comparing
510	atf_add_test_case copy_self_safe_comparing
511	atf_add_test_case overwrite
512	atf_add_test_case overwrite_safe
513	atf_add_test_case overwrite_comparing
514	atf_add_test_case overwrite_safe_comparing
515	atf_add_test_case overwrite_eq
516	atf_add_test_case overwrite_eq_safe
517	atf_add_test_case overwrite_eq_comparing
518	atf_add_test_case overwrite_eq_safe_comparing
519	atf_add_test_case overwrite_backup
520	atf_add_test_case overwrite_backup_safe
521	atf_add_test_case overwrite_backup_comparing
522	atf_add_test_case overwrite_backup_safe_comparing
523	atf_add_test_case strip_changing
524	atf_add_test_case strip_changing_comparing
525	atf_add_test_case strip_changing_overwrite
526	atf_add_test_case strip_changing_overwrite_comparing
527	atf_add_test_case strip_changing_overwrite_eq
528	atf_add_test_case strip_changing_overwrite_eq_comparing
529	atf_add_test_case strip_noop
530	atf_add_test_case hard_link
531	atf_add_test_case symbolic_link
532	atf_add_test_case symbolic_link_absolute
533	atf_add_test_case symbolic_link_relative
534	atf_add_test_case symbolic_link_relative_absolute_source_and_dest1
535	atf_add_test_case symbolic_link_relative_absolute_source_and_dest1_double_slash
536	atf_add_test_case symbolic_link_relative_absolute_source_and_dest2
537	atf_add_test_case symbolic_link_relative_absolute_common
538	atf_add_test_case mkdir_simple
539	atf_add_test_case set_owner_group_mode
540	atf_add_test_case set_owner_group_mode_unpriv
541	atf_add_test_case set_optional_exec
542}
543