xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/cmd/file/randfree_file.c (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or https://opensource.org/licenses/CDDL-1.0.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 /*
29  * Copyright (c) 2012 by Delphix. All rights reserved.
30  */
31 
32 #include "file_common.h"
33 #include <sys/types.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <linux/falloc.h>
38 
39 /*
40  * Create a file with assigned size and then free the specified
41  * section of the file
42  */
43 
44 static void usage(char *progname);
45 
46 static void
47 usage(char *progname)
48 {
49 	(void) fprintf(stderr,
50 	    "usage: %s [-l filesize] [-s start-offset]"
51 	    "[-n section-len] filename\n", progname);
52 	exit(1);
53 }
54 
55 int
56 main(int argc, char *argv[])
57 {
58 	char *filename = NULL;
59 	char *buf = NULL;
60 	size_t filesize = 0;
61 	off_t start_off = 0;
62 	off_t off_len = 0;
63 	int  fd, ch;
64 	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
65 
66 	while ((ch = getopt(argc, argv, "l:s:n:")) != EOF) {
67 		switch (ch) {
68 		case 'l':
69 			filesize = atoll(optarg);
70 			break;
71 		case 's':
72 			start_off = atoll(optarg);
73 			break;
74 		case 'n':
75 			off_len = atoll(optarg);
76 			break;
77 		default:
78 			usage(argv[0]);
79 			break;
80 		}
81 	}
82 
83 	if (optind == argc - 1)
84 		filename = argv[optind];
85 	else
86 		usage(argv[0]);
87 
88 	if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0) {
89 		perror("open");
90 		return (1);
91 	}
92 
93 	buf = (char *)calloc(1, filesize);
94 	if (buf == NULL) {
95 		perror("write");
96 		close(fd);
97 		return (1);
98 	}
99 	memset(buf, 'c', filesize);
100 
101 	if (write(fd, buf, filesize) < filesize) {
102 		free(buf);
103 		perror("write");
104 		close(fd);
105 		return (1);
106 	}
107 
108 	free(buf);
109 
110 #if defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)
111 	if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
112 	    start_off, off_len) < 0) {
113 		perror("fallocate");
114 		close(fd);
115 		return (1);
116 	}
117 #else /* !(defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)) */
118 	{
119 		perror("FALLOC_FL_PUNCH_HOLE unsupported");
120 		close(fd);
121 		return (1);
122 	}
123 #endif /* defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) */
124 	close(fd);
125 	return (0);
126 }
127