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:
@@ -3,5 +3,7 @@
|
|||||||
PACKAGE= tests
|
PACKAGE= tests
|
||||||
|
|
||||||
ATF_TESTS_SH= cp_test
|
ATF_TESTS_SH= cp_test
|
||||||
|
PROGS+= sparse
|
||||||
|
BINDIR= ${TESTSDIR}
|
||||||
|
|
||||||
.include <bsd.test.mk>
|
.include <bsd.test.mk>
|
||||||
|
|||||||
+23
-23
@@ -201,7 +201,7 @@ recursive_link_Lflag_body()
|
|||||||
|
|
||||||
file_is_sparse()
|
file_is_sparse()
|
||||||
{
|
{
|
||||||
atf_check test "$(stat -f "%b" "$1")" != "$(stat -f "%z" "$1")"
|
atf_check ${0%/*}/sparse "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
files_are_equal()
|
files_are_equal()
|
||||||
@@ -213,8 +213,8 @@ files_are_equal()
|
|||||||
atf_test_case sparse_leading_hole
|
atf_test_case sparse_leading_hole
|
||||||
sparse_leading_hole_body()
|
sparse_leading_hole_body()
|
||||||
{
|
{
|
||||||
# A one-megabyte hole followed by one megabyte of data
|
# A 16-megabyte hole followed by one megabyte of data
|
||||||
truncate -s 1M foo
|
truncate -s 16M foo
|
||||||
seq -f%015g 65536 >>foo
|
seq -f%015g 65536 >>foo
|
||||||
file_is_sparse foo
|
file_is_sparse foo
|
||||||
|
|
||||||
@@ -227,14 +227,14 @@ atf_test_case sparse_multiple_holes
|
|||||||
sparse_multiple_holes_body()
|
sparse_multiple_holes_body()
|
||||||
{
|
{
|
||||||
# Three one-megabyte blocks of data preceded, separated, and
|
# Three one-megabyte blocks of data preceded, separated, and
|
||||||
# followed by one-megabyte holes
|
# followed by 16-megabyte holes
|
||||||
truncate -s 1M foo
|
truncate -s 16M foo
|
||||||
seq -f%015g >>foo
|
seq -f%015g 65536 >>foo
|
||||||
truncate -s 3M foo
|
truncate -s 33M foo
|
||||||
seq -f%015g >>foo
|
seq -f%015g 65536 >>foo
|
||||||
truncate -s 5M foo
|
truncate -s 50M foo
|
||||||
seq -f%015g >>foo
|
seq -f%015g 65536 >>foo
|
||||||
truncate -s 7M foo
|
truncate -s 67M foo
|
||||||
file_is_sparse foo
|
file_is_sparse foo
|
||||||
|
|
||||||
atf_check cp foo bar
|
atf_check cp foo bar
|
||||||
@@ -245,8 +245,8 @@ sparse_multiple_holes_body()
|
|||||||
atf_test_case sparse_only_hole
|
atf_test_case sparse_only_hole
|
||||||
sparse_only_hole_body()
|
sparse_only_hole_body()
|
||||||
{
|
{
|
||||||
# A one-megabyte hole
|
# A 16-megabyte hole
|
||||||
truncate -s 1M foo
|
truncate -s 16M foo
|
||||||
file_is_sparse foo
|
file_is_sparse foo
|
||||||
|
|
||||||
atf_check cp foo bar
|
atf_check cp foo bar
|
||||||
@@ -258,14 +258,14 @@ atf_test_case sparse_to_dev
|
|||||||
sparse_to_dev_body()
|
sparse_to_dev_body()
|
||||||
{
|
{
|
||||||
# Three one-megabyte blocks of data preceded, separated, and
|
# Three one-megabyte blocks of data preceded, separated, and
|
||||||
# followed by one-megabyte holes
|
# followed by 16-megabyte holes
|
||||||
truncate -s 1M foo
|
truncate -s 16M foo
|
||||||
seq -f%015g >>foo
|
seq -f%015g 65536 >>foo
|
||||||
truncate -s 3M foo
|
truncate -s 33M foo
|
||||||
seq -f%015g >>foo
|
seq -f%015g 65536 >>foo
|
||||||
truncate -s 5M foo
|
truncate -s 50M foo
|
||||||
seq -f%015g >>foo
|
seq -f%015g 65536 >>foo
|
||||||
truncate -s 7M foo
|
truncate -s 67M foo
|
||||||
file_is_sparse foo
|
file_is_sparse foo
|
||||||
|
|
||||||
atf_check -o file:foo cp foo /dev/stdout
|
atf_check -o file:foo cp foo /dev/stdout
|
||||||
@@ -274,9 +274,9 @@ sparse_to_dev_body()
|
|||||||
atf_test_case sparse_trailing_hole
|
atf_test_case sparse_trailing_hole
|
||||||
sparse_trailing_hole_body()
|
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
|
seq -f%015g 65536 >foo
|
||||||
truncate -s 2M foo
|
truncate -s 17M foo
|
||||||
file_is_sparse foo
|
file_is_sparse foo
|
||||||
|
|
||||||
atf_check cp foo bar
|
atf_check cp foo bar
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user