xref: /freebsd/tests/sys/cddl/zfs/bin/file_trunc.c (revision 06c3fb27)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <limits.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/fcntl.h>
35 #include <sys/stat.h>
36 #include <sys/statvfs.h>
37 #include <sys/errno.h>
38 #include <sys/time.h>
39 #include <sys/ioctl.h>
40 #include <sys/wait.h>
41 #include <sys/param.h>
42 #include <string.h>
43 
44 #define	FSIZE	256*1024*1024
45 #define	BSIZE	512
46 
47 /* Initialize Globals */
48 static long 	fsize = FSIZE;
49 static size_t 	bsize = BSIZE;
50 static int	count = 0;
51 static int	rflag = 0;
52 static int	seed = 0;
53 static int	vflag = 0;
54 static int	errflag = 0;
55 static off_t	offset = 0;
56 static char	*filename = NULL;
57 
58 static void usage(char *execname);
59 static void parse_options(int argc, char *argv[]);
60 static void do_write(int fd);
61 static void do_trunc(int fd);
62 
63 static void
64 usage(char *execname)
65 {
66 	(void) fprintf(stderr,
67 	    "usage: %s [-b blocksize] [-c count] [-f filesize]"
68 	    " [-o offset] [-s seed] [-r] [-v] filename\n", execname);
69 	(void) exit(1);
70 }
71 
72 int
73 main(int argc, char *argv[])
74 {
75 	int i = 0;
76 	int fd = -1;
77 
78 	parse_options(argc, argv);
79 
80 	fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
81 	if (fd < 0) {
82 		perror("open");
83 		exit(3);
84 	}
85 
86 	while (i < count) {
87 		(void) do_write(fd);
88 		(void) do_trunc(fd);
89 
90 		i++;
91 	}
92 
93 	(void) close(fd);
94 	return (0);
95 }
96 
97 static void
98 parse_options(int argc, char *argv[])
99 {
100 	int c;
101 
102 	extern char *optarg;
103 	extern int optind, optopt;
104 
105 	count = fsize / bsize;
106 	seed = time(NULL);
107 	while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) {
108 		switch (c) {
109 			case 'b':
110 				bsize = atoi(optarg);
111 				break;
112 
113 			case 'c':
114 				count = atoi(optarg);
115 				break;
116 
117 			case 'f':
118 				fsize = atoi(optarg);
119 				break;
120 
121 			case 'o':
122 				offset = atoi(optarg);
123 				break;
124 
125 			case 'r':
126 				rflag++;
127 				break;
128 
129 			case 's':
130 				seed = atoi(optarg);
131 				break;
132 
133 			case 'v':
134 				vflag++;
135 				break;
136 
137 			case ':':
138 				(void) fprintf(stderr,
139 				    "Option -%c requires an operand\n", optopt);
140 				errflag++;
141 				break;
142 
143 			case '?':
144 				(void) fprintf(stderr,
145 				    "Unrecognized option: -%c\n", optopt);
146 				errflag++;
147 				break;
148 		}
149 
150 		if (errflag) {
151 			(void) usage(argv[0]);
152 		}
153 	}
154 	if (argc <= optind) {
155 		(void) fprintf(stderr,
156 		    "No filename specified\n");
157 		usage(argv[0]);
158 	}
159 	filename = argv[optind];
160 
161 	if (vflag) {
162 		(void) fprintf(stderr, "Seed = %d\n", seed);
163 	}
164 	srandom(seed);
165 }
166 
167 static void
168 do_write(int fd)
169 {
170 	off_t	roffset = 0;
171 	char 	*buf = NULL;
172 	char 	*rbuf = NULL;
173 
174 	buf = (char *)calloc(1, bsize);
175 	rbuf = (char *)calloc(1, bsize);
176 	if (buf == NULL || rbuf == NULL) {
177 		perror("malloc");
178 		exit(4);
179 	}
180 
181 	roffset = random() % fsize;
182 	if (lseek(fd, (offset + roffset), SEEK_SET) < 0) {
183 		perror("lseek");
184 		exit(5);
185 	}
186 
187 	strcpy(buf, "ZFS Test Suite Truncation Test");
188 	if (write(fd, buf, bsize) < bsize) {
189 		perror("write");
190 		exit(6);
191 	}
192 
193 	if (rflag) {
194 		if (lseek(fd, (offset + roffset), SEEK_SET) < 0) {
195 			perror("lseek");
196 			exit(7);
197 		}
198 
199 		if (read(fd, rbuf, bsize) < bsize) {
200 			perror("read");
201 			exit(8);
202 		}
203 
204 		if (memcmp(buf, rbuf, bsize) != 0) {
205 			perror("memcmp");
206 			exit(9);
207 		}
208 	}
209 	if (vflag) {
210 		(void) fprintf(stderr,
211 		    "Wrote to offset %ld\n", (offset + roffset));
212 		if (rflag) {
213 			(void) fprintf(stderr,
214 			    "Read back from offset %ld\n", (offset + roffset));
215 		}
216 	}
217 
218 	(void) free(buf);
219 	(void) free(rbuf);
220 }
221 
222 static void
223 do_trunc(int fd)
224 {
225 	off_t   roffset = 0;
226 
227 	roffset = random() % fsize;
228 	if (ftruncate(fd, (offset + roffset))  < 0) {
229 		perror("truncate");
230 		exit(7);
231 	}
232 
233 	if (vflag) {
234 		(void) fprintf(stderr,
235 		    "Truncated at offset %ld\n",
236 		    (offset + roffset));
237 	}
238 }
239