View | Details | Raw Unified | Return to bug 190735
Collapse All | Expand All

(-)Makefile (+4 lines)
Lines 4-7 Link Here
4
DPADD=		${LIBUTIL}
4
DPADD=		${LIBUTIL}
5
LDADD=		-lutil
5
LDADD=		-lutil
6
6
7
.if ${MK_TESTS} != "no"
8
SUBDIR+= tests
9
.endif
10
7
.include <bsd.prog.mk>
11
.include <bsd.prog.mk>
(-)tests/Makefile (+6 lines)
Line 0 Link Here
1
# $FreeBSD$
2
3
TESTSDIR=	${TESTSBASE}/usr.bin/truncate
4
ATF_TESTS_SH=	truncate_test 
5
6
.include <bsd.test.mk>
(-)tests/truncate_test.sh (+411 lines)
Line 0 Link Here
1
#
2
# Copyright 2014, Google Inc. All rights reserved.
3
#
4
# Redistribution and use in source and binary forms, with or without
5
# modification, are permitted provided that the following conditions are
6
# met:
7
#
8
# * Redistributions of source code must retain the above copyright
9
#   notice, this list of conditions and the following disclaimer.
10
# * 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
# * Neither the name of Google Inc. nor the names of its
14
#   contributors may be used to endorse or promote products derived from
15
#   this software without specific written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
# Helper function that is always used to create and fill stderr.txt for these
30
# tests.
31
_custom_create_file()
32
{
33
	# The first argument is a command.
34
	# The second is just a string.
35
	case "${1}" in
36
		creat) > stderr.txt ;;
37
		print) [ "${2}" ] && \
38
		    printf "%s\n" "${2}" >> stderr.txt ;;
39
	esac
40
}
41
42
# Helper function that create the file stderr.txt that contains the string
43
# passed in as the first argument.
44
create_stderr_file()
45
{
46
	_custom_create_file creat
47
	_custom_create_file print "${1}"
48
}
49
50
# Helper function that create the file stderr.txt that contains the expected
51
# truncate utility usage message.
52
create_stderr_usage_file()
53
{
54
	_custom_create_file creat
55
	_custom_create_file print "${1}"
56
	_custom_create_file print \
57
	    "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g|T|t] file ..."
58
	_custom_create_file print "       truncate [-c] -r rfile file ..."
59
}
60
61
atf_test_case illegal_option
62
illegal_option_head()
63
{
64
	atf_set "descr" "Verifies that truncate exits >0 when passed an" \
65
	    "invalid command line option"
66
}
67
illegal_option_body()
68
{
69
	create_stderr_usage_file 'truncate: illegal option -- 7'
70
71
	# We expect the error message, with no new files.
72
	atf_check -s not-exit:0 -e file:stderr.txt truncate -7 -s0 output.txt
73
	[ ! -e output.txt ] || atf_fail "output.txt should not exist"
74
}
75
76
atf_test_case illegal_size
77
illegal_size_head()
78
{
79
	atf_set "descr" "Verifies that truncate exits >0 when passed an" \
80
	    "invalid power of two convention"
81
}
82
illegal_size_body()
83
{
84
	create_stderr_file "truncate: invalid size argument \`+1L'"
85
86
	# We expect the error message, with no new files.
87
	atf_check -s not-exit:0 -e file:stderr.txt truncate -s+1L output.txt
88
	[ ! -e output.txt ] || atf_fail "output.txt should not exist"
89
}
90
91
atf_test_case too_large_size
92
too_large_size_head()
93
{
94
	atf_set "descr" "Verifies that truncate exits >0 when passed an" \
95
	    "a size that is INT64_MAX < size <= UINT64_MAX"
96
}
97
too_large_size_body()
98
{
99
	create_stderr_file "truncate: invalid size argument \`8388608t'"
100
101
	# We expect the error message, with no new files.
102
	atf_check -s not-exit:0 -e file:stderr.txt \
103
	    truncate -s8388608t output.txt
104
	[ ! -e output.txt ] || atf_fail "output.txt should not exist"
105
}
106
107
atf_test_case opt_c
108
opt_c_head()
109
{
110
	atf_set "descr" "Verifies that -c prevents creation of new files"
111
}
112
opt_c_body()
113
{
114
	# No new files and truncate returns 0 as if this is a success.
115
	atf_check truncate -c -s 0 doesnotexist.txt
116
	[ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist"
117
	> reference
118
	atf_check truncate -c -r reference doesnotexist.txt
119
	[ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist"
120
121
	create_stderr_file
122
123
	# The existing file will be altered by truncate.
124
	> exists.txt
125
	atf_check -e file:stderr.txt truncate -c -s1 exists.txt
126
	[ -s exists.txt ] || atf_fail "exists.txt be larger than zero bytes"
127
}
128
129
atf_test_case opt_rs
130
opt_rs_head()
131
{
132
	atf_set "descr" "Verifies that truncate command line flags" \
133
	    "-s and -r cannot be specifed together"
134
}
135
opt_rs_body()
136
{
137
	create_stderr_usage_file
138
139
	# Force an error due to the use of both -s and -r.
140
	> afile
141
	atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile
142
}
143
144
atf_test_case opt_rs
145
opt_rs_head()
146
{
147
	atf_set "descr" "Verifies that truncate command line" \
148
	    "flags -s and -r cannot be specifed together"
149
}
150
opt_rs_body()
151
{
152
	create_stderr_usage_file
153
154
	# Force an error due to the use of both -s and -r.
155
	> afile
156
	atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile
157
}
158
159
atf_test_case no_files
160
no_files_head()
161
{
162
	atf_set "descr" "Verifies that truncate needs a list of files on" \
163
	    "the command line"
164
}
165
no_files_body()
166
{
167
	create_stderr_usage_file
168
169
	# A list of files must be present on the command line.
170
	atf_check -s not-exit:0 -e file:stderr.txt truncate -s1
171
}
172
173
atf_test_case bad_refer
174
bad_refer_head()
175
{
176
	atf_set "descr" "Verifies that truncate needs a list of files on" \
177
	    "the command line"
178
}
179
bad_refer_body()
180
{
181
	create_stderr_file "truncate: afile: No such file or directory"
182
183
	# The reference file must exist before you try to use it.
184
	atf_check -s not-exit:0 -e file:stderr.txt truncate -r afile afile
185
	[ ! -e afile ] || atf_fail "afile should not exist"
186
}
187
188
atf_test_case bad_truncate cleanup
189
bad_truncate_head()
190
{
191
	atf_set "descr" "Verifies that truncate needs a list of files on" \
192
	    "the command line"
193
}
194
bad_truncate_body()
195
{
196
	create_stderr_file "truncate: exists.txt: Operation not permitted"
197
198
	# Trying to get the ftruncate() call to return -1.
199
	> exists.txt
200
	atf_check chflags uimmutable exists.txt
201
202
	atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt
203
}
204
bad_truncate_cleanup()
205
{
206
	chflags 0 exists.txt
207
}
208
209
atf_test_case new_absolute_grow
210
new_absolute_grow_head()
211
{
212
	atf_set "descr" "Verifies truncate can make and grow a new 1m file"
213
}
214
new_absolute_grow_body()
215
{
216
	create_stderr_file
217
218
	# Create a new file and grow it to 1024 bytes.
219
	atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt
220
	atf_check -s exit:1 cmp -s output.txt /dev/zero
221
	eval $(stat -s output.txt)
222
	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
223
224
	create_stderr_file
225
226
	# Grow the existing file to 1M.  We are using absolute sizes.
227
	atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt
228
	atf_check -s exit:1 cmp -s output.txt /dev/zero
229
	eval $(stat -s output.txt)
230
	[ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
231
}
232
233
atf_test_case new_absolute_shrink
234
new_absolute_shrink_head()
235
{
236
	atf_set "descr" "Verifies that truncate can make and" \
237
	    "shrink a new 1m file"
238
}
239
new_absolute_shrink_body()
240
{
241
	create_stderr_file
242
243
	# Create a new file and grow it to 1048576 bytes.
244
	atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt
245
	atf_check -s exit:1 cmp -s output.txt /dev/zero
246
	eval $(stat -s output.txt)
247
	[ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
248
249
	create_stderr_file
250
251
	# Shrink the existing file to 1k.  We are using absolute sizes.
252
	atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt
253
	atf_check -s exit:1 cmp -s output.txt /dev/zero
254
	eval $(stat -s output.txt)
255
	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
256
}
257
258
atf_test_case new_relative_grow
259
new_relative_grow_head()
260
{
261
	atf_set "descr" "Verifies truncate can make and grow a new 1m file"
262
}
263
new_relative_grow_body()
264
{
265
	create_stderr_file
266
267
	# Create a new file and grow it to 1024 bytes.
268
	atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt
269
	atf_check -s exit:1 cmp -s output.txt /dev/zero
270
	eval $(stat -s output.txt)
271
	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
272
273
	create_stderr_file
274
275
	# Grow the existing file to 1M.  We are using relative sizes.
276
	atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt
277
	atf_check -s exit:1 cmp -s output.txt /dev/zero
278
	eval $(stat -s output.txt)
279
	[ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
280
}
281
282
atf_test_case new_relative_shrink
283
new_relative_shrink_head()
284
{
285
	atf_set "descr" "Verifies truncate can make and shrink a new 1m file"
286
}
287
new_relative_shrink_body()
288
{
289
	create_stderr_file
290
291
	# Create a new file and grow it to 1049600 bytes.
292
	atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt
293
	atf_check -s exit:1 cmp -s output.txt /dev/zero
294
	eval $(stat -s output.txt)
295
	[ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m"
296
297
	create_stderr_file
298
299
	# Shrink the existing file to 1k.  We are using relative sizes.
300
	atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt
301
	atf_check -s exit:1 cmp -s output.txt /dev/zero
302
	eval $(stat -s output.txt)
303
	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
304
}
305
306
atf_test_case cannot_open
307
cannot_open_head()
308
{
309
	atf_set "descr" "Verifies truncate can make and grow a new 1m file"
310
	atf_set "require.user" "unprivileged"
311
}
312
cannot_open_body()
313
{
314
	# Create three files -- the middle file cannot allow writes.
315
	> before
316
	> 0000
317
	> after
318
	atf_check chmod 0000 0000
319
320
	create_stderr_file "truncate: 0000: Permission denied"
321
322
	# Create a new file and grow it to 1024 bytes.
323
	atf_check -s not-exit:0 -e file:stderr.txt \
324
	truncate -c -s1k before 0000 after
325
	eval $(stat -s before)
326
	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
327
	eval $(stat -s after)
328
	[ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
329
	eval $(stat -s 0000)
330
	[ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
331
}
332
333
atf_test_case reference
334
reference_head()
335
{
336
	atf_set "descr" "Verifies that truncate can use a reference file"
337
}
338
reference_body()
339
{
340
	# Create a 4 byte reference file.
341
	printf "123\n" > reference
342
	eval $(stat -s reference)
343
	[ ${st_size} -eq 4 ] || atf_fail "reference file should be 4 bytes"
344
345
	create_stderr_file
346
347
	# Create a new file and grow it to 4 bytes.
348
	atf_check -e file:stderr.txt truncate -r reference afile
349
	eval $(stat -s afile)
350
	[ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes"
351
}
352
353
atf_test_case new_zero
354
new_zero_head()
355
{
356
	atf_set "descr" "Verifies truncate can make and grow zero byte file"
357
}
358
new_zero_body()
359
{
360
	create_stderr_file
361
362
	# Create a new file and grow it to zero bytes.
363
	atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt
364
	eval $(stat -s output.txt)
365
	[ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
366
367
	# Pretend to grow the file.
368
	atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt
369
	eval $(stat -s output.txt)
370
	[ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
371
}
372
373
atf_test_case negative
374
negative_head()
375
{
376
	atf_set "descr" "Verifies truncate treats negative sizes as zero"
377
}
378
negative_body()
379
{
380
	# Create a 5 byte file.
381
	printf "abcd\n" > afile
382
	eval $(stat -s afile)
383
	[ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
384
385
	create_stderr_file
386
387
	# Create a new file and do a 100 byte negative relative shrink.
388
	atf_check -e file:stderr.txt truncate -s-100 afile
389
	eval $(stat -s afile)
390
	[ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes"
391
}
392
393
atf_init_test_cases()
394
{
395
	atf_add_test_case illegal_option
396
	atf_add_test_case illegal_size
397
	atf_add_test_case too_large_size
398
	atf_add_test_case opt_c
399
	atf_add_test_case opt_rs
400
	atf_add_test_case no_files
401
	atf_add_test_case bad_refer
402
	atf_add_test_case bad_truncate
403
	atf_add_test_case cannot_open
404
	atf_add_test_case new_absolute_grow
405
	atf_add_test_case new_absolute_shrink
406
	atf_add_test_case new_relative_grow
407
	atf_add_test_case new_relative_shrink
408
	atf_add_test_case reference
409
	atf_add_test_case new_zero
410
	atf_add_test_case negative
411
}
(-)truncate.c (-5 / +7 lines)
Lines 54-61 Link Here
54
{
54
{
55
	struct stat	sb;
55
	struct stat	sb;
56
	mode_t	omode;
56
	mode_t	omode;
57
	off_t	oflow, rsize, tsize;
57
	off_t	oflow, rsize, sz, tsize;
58
	int64_t sz;
58
	uint64_t usz;
59
	int	ch, error, fd, oflags;
59
	int	ch, error, fd, oflags;
60
	char   *fname, *rname;
60
	char   *fname, *rname;
61
61
Lines 73-83 Link Here
73
			rname = optarg;
73
			rname = optarg;
74
			break;
74
			break;
75
		case 's':
75
		case 's':
76
			if (expand_number(optarg, &sz) == -1)
76
			do_relative = *optarg == '+' || *optarg == '-';
77
			if ((expand_number(do_relative ? optarg+1 : optarg,
78
			    &usz) == -1) || ((off_t)usz < 0))
77
				errx(EXIT_FAILURE,
79
				errx(EXIT_FAILURE,
78
				    "invalid size argument `%s'", optarg);
80
				    "invalid size argument `%s'", optarg);
79
			if (*optarg == '+' || *optarg == '-')
81
80
				do_relative = 1;
82
			sz = (*optarg == '-') ? -(off_t)usz : (off_t)usz;
81
			got_size = 1;
83
			got_size = 1;
82
			break;
84
			break;
83
		default:
85
		default:

Return to bug 190735