diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2023-02-08 16:49:29 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2023-02-08 16:49:50 +0000 |
commit | 8b418c83d175fde3b1f65210509ddcf2ac248d9f (patch) | |
tree | dcdd2ce74e28e43b8814a57f5296e025684320a5 /bin | |
parent | 9df6eeabb379b0816d58b05a4de24fc0478e1dba (diff) | |
download | src-8b418c83d175fde3b1f65210509ddcf2ac248d9f.tar.gz src-8b418c83d175fde3b1f65210509ddcf2ac248d9f.zip |
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
Diffstat (limited to 'bin')
-rw-r--r-- | bin/cp/tests/Makefile | 2 | ||||
-rwxr-xr-x | bin/cp/tests/cp_test.sh | 46 | ||||
-rw-r--r-- | bin/cp/tests/sparse.c | 73 |
3 files changed, 98 insertions, 23 deletions
diff --git a/bin/cp/tests/Makefile b/bin/cp/tests/Makefile index faad22df713a..1e480ad706d1 100644 --- a/bin/cp/tests/Makefile +++ b/bin/cp/tests/Makefile @@ -3,5 +3,7 @@ PACKAGE= tests ATF_TESTS_SH= cp_test +PROGS+= sparse +BINDIR= ${TESTSDIR} .include <bsd.test.mk> diff --git a/bin/cp/tests/cp_test.sh b/bin/cp/tests/cp_test.sh index 932bd2221ba3..559a5ecc3c00 100755 --- a/bin/cp/tests/cp_test.sh +++ b/bin/cp/tests/cp_test.sh @@ -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 diff --git a/bin/cp/tests/sparse.c b/bin/cp/tests/sparse.c new file mode 100644 index 000000000000..78957581a56c --- /dev/null +++ b/bin/cp/tests/sparse.c @@ -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); +} |