HardenedBSD/bin/cp/tests/sparse.c
Dag-Erling Smørgrav 8b418c83d1 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
2023-02-08 16:49:50 +00:00

74 lines
1.2 KiB
C

/*-
* 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);
}