mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-06 16:40:47 +00:00
cp: Adjust the sparse file tests.
* The sparsity check was ineffective: it compared the apparent size in bytes to the actual size in blocks. Instead, write a tool that reliably detects sparseness. * Some of the seq commands were missing an argument. * Based on empirical evidence, 1 MB holes are not necessarily large enough to be preserved by the underlying filesystem. Increase the hole size to 16 MB. MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: cracauer Differential Revision: https://reviews.freebsd.org/D38414
This commit is contained in:
parent
9df6eeabb3
commit
8b418c83d1
|
@ -3,5 +3,7 @@
|
|||
PACKAGE= tests
|
||||
|
||||
ATF_TESTS_SH= cp_test
|
||||
PROGS+= sparse
|
||||
BINDIR= ${TESTSDIR}
|
||||
|
||||
.include <bsd.test.mk>
|
||||
|
|
|
@ -201,7 +201,7 @@ recursive_link_Lflag_body()
|
|||
|
||||
file_is_sparse()
|
||||
{
|
||||
atf_check test "$(stat -f "%b" "$1")" != "$(stat -f "%z" "$1")"
|
||||
atf_check ${0%/*}/sparse "$1"
|
||||
}
|
||||
|
||||
files_are_equal()
|
||||
|
@ -213,8 +213,8 @@ files_are_equal()
|
|||
atf_test_case sparse_leading_hole
|
||||
sparse_leading_hole_body()
|
||||
{
|
||||
# A one-megabyte hole followed by one megabyte of data
|
||||
truncate -s 1M foo
|
||||
# A 16-megabyte hole followed by one megabyte of data
|
||||
truncate -s 16M foo
|
||||
seq -f%015g 65536 >>foo
|
||||
file_is_sparse foo
|
||||
|
||||
|
@ -227,14 +227,14 @@ atf_test_case sparse_multiple_holes
|
|||
sparse_multiple_holes_body()
|
||||
{
|
||||
# Three one-megabyte blocks of data preceded, separated, and
|
||||
# followed by one-megabyte holes
|
||||
truncate -s 1M foo
|
||||
seq -f%015g >>foo
|
||||
truncate -s 3M foo
|
||||
seq -f%015g >>foo
|
||||
truncate -s 5M foo
|
||||
seq -f%015g >>foo
|
||||
truncate -s 7M foo
|
||||
# followed by 16-megabyte holes
|
||||
truncate -s 16M foo
|
||||
seq -f%015g 65536 >>foo
|
||||
truncate -s 33M foo
|
||||
seq -f%015g 65536 >>foo
|
||||
truncate -s 50M foo
|
||||
seq -f%015g 65536 >>foo
|
||||
truncate -s 67M foo
|
||||
file_is_sparse foo
|
||||
|
||||
atf_check cp foo bar
|
||||
|
@ -245,8 +245,8 @@ sparse_multiple_holes_body()
|
|||
atf_test_case sparse_only_hole
|
||||
sparse_only_hole_body()
|
||||
{
|
||||
# A one-megabyte hole
|
||||
truncate -s 1M foo
|
||||
# A 16-megabyte hole
|
||||
truncate -s 16M foo
|
||||
file_is_sparse foo
|
||||
|
||||
atf_check cp foo bar
|
||||
|
@ -258,14 +258,14 @@ atf_test_case sparse_to_dev
|
|||
sparse_to_dev_body()
|
||||
{
|
||||
# Three one-megabyte blocks of data preceded, separated, and
|
||||
# followed by one-megabyte holes
|
||||
truncate -s 1M foo
|
||||
seq -f%015g >>foo
|
||||
truncate -s 3M foo
|
||||
seq -f%015g >>foo
|
||||
truncate -s 5M foo
|
||||
seq -f%015g >>foo
|
||||
truncate -s 7M foo
|
||||
# followed by 16-megabyte holes
|
||||
truncate -s 16M foo
|
||||
seq -f%015g 65536 >>foo
|
||||
truncate -s 33M foo
|
||||
seq -f%015g 65536 >>foo
|
||||
truncate -s 50M foo
|
||||
seq -f%015g 65536 >>foo
|
||||
truncate -s 67M foo
|
||||
file_is_sparse foo
|
||||
|
||||
atf_check -o file:foo cp foo /dev/stdout
|
||||
|
@ -274,9 +274,9 @@ sparse_to_dev_body()
|
|||
atf_test_case sparse_trailing_hole
|
||||
sparse_trailing_hole_body()
|
||||
{
|
||||
# One megabyte of data followed by a one-megabyte hole
|
||||
# One megabyte of data followed by a 16-megabyte hole
|
||||
seq -f%015g 65536 >foo
|
||||
truncate -s 2M foo
|
||||
truncate -s 17M foo
|
||||
file_is_sparse foo
|
||||
|
||||
atf_check cp foo bar
|
||||
|
|
73
bin/cp/tests/sparse.c
Normal file
73
bin/cp/tests/sparse.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*-
|
||||
* Copyright (c) 2023 Klara, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static bool verbose;
|
||||
|
||||
/*
|
||||
* Returns true if the file named by its argument is sparse, i.e. if
|
||||
* seeking to SEEK_HOLE returns a different value than seeking to
|
||||
* SEEK_END.
|
||||
*/
|
||||
static bool
|
||||
sparse(const char *filename)
|
||||
{
|
||||
off_t hole, end;
|
||||
int fd;
|
||||
|
||||
if ((fd = open(filename, O_RDONLY)) < 0 ||
|
||||
(hole = lseek(fd, 0, SEEK_HOLE)) < 0 ||
|
||||
(end = lseek(fd, 0, SEEK_END)) < 0)
|
||||
err(1, "%s", filename);
|
||||
close(fd);
|
||||
if (end > hole) {
|
||||
if (verbose)
|
||||
printf("%s: hole at %zu\n", filename, (size_t)hole);
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: sparse [-v] file [...]\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int opt, rv;
|
||||
|
||||
while ((opt = getopt(argc, argv, "v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc == 0)
|
||||
usage();
|
||||
rv = EXIT_SUCCESS;
|
||||
while (argc-- > 0)
|
||||
if (!sparse(*argv++))
|
||||
rv = EXIT_FAILURE;
|
||||
exit(rv);
|
||||
}
|
Loading…
Reference in a new issue