xref: /illumos-gate/usr/src/test/zfs-tests/cmd/file_trunc/file_trunc.c (revision 299625c6492013aa7bd163862f0d181854f69b3c)
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 /*
28  * Copyright (c) 2012 by Delphix. All rights reserved.
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <limits.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/fcntl.h>
39 #include <sys/stat.h>
40 #include <sys/statvfs.h>
41 #include <sys/errno.h>
42 #include <sys/time.h>
43 #include <sys/ioctl.h>
44 #include <sys/wait.h>
45 #include <sys/param.h>
46 #include <string.h>
47 
48 #define	FSIZE	256*1024*1024
49 #define	BSIZE	512
50 
51 /* Initialize Globals */
52 static long	fsize = FSIZE;
53 static size_t	bsize = BSIZE;
54 static int	count = 0;
55 static int	rflag = 0;
56 static int	seed = 0;
57 static int	vflag = 0;
58 static int	errflag = 0;
59 static off_t	offset = 0;
60 static char	*filename = NULL;
61 
62 static void usage(char *execname);
63 static void parse_options(int argc, char *argv[]);
64 static void do_write(int fd);
65 static void do_trunc(int fd);
66 
67 static void
68 usage(char *execname)
69 {
70 	(void) fprintf(stderr,
71 	    "usage: %s [-b blocksize] [-c count] [-f filesize]"
72 	    " [-o offset] [-s seed] [-r] [-v] filename\n", execname);
73 	(void) exit(1);
74 }
75 
76 int
77 main(int argc, char *argv[])
78 {
79 	int i = 0;
80 	int fd = -1;
81 
82 	parse_options(argc, argv);
83 
84 	fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
85 	if (fd < 0) {
86 		perror("open");
87 		exit(3);
88 	}
89 
90 	while (i < count) {
91 		(void) do_write(fd);
92 		(void) do_trunc(fd);
93 
94 		i++;
95 	}
96 
97 	(void) close(fd);
98 	return (0);
99 }
100 
101 static void
102 parse_options(int argc, char *argv[])
103 {
104 	int c;
105 
106 	extern char *optarg;
107 	extern int optind, optopt;
108 
109 	count = fsize / bsize;
110 	seed = time(NULL);
111 	while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) {
112 		switch (c) {
113 			case 'b':
114 				bsize = atoi(optarg);
115 				break;
116 
117 			case 'c':
118 				count = atoi(optarg);
119 				break;
120 
121 			case 'f':
122 				fsize = atoi(optarg);
123 				break;
124 
125 			case 'o':
126 				offset = atoi(optarg);
127 				break;
128 
129 			case 'r':
130 				rflag++;
131 				break;
132 
133 			case 's':
134 				seed = atoi(optarg);
135 				break;
136 
137 			case 'v':
138 				vflag++;
139 				break;
140 
141 			case ':':
142 				(void) fprintf(stderr,
143 				    "Option -%c requires an operand\n", optopt);
144 				errflag++;
145 				break;
146 
147 			case '?':
148 				(void) fprintf(stderr,
149 				    "Unrecognized option: -%c\n", optopt);
150 				errflag++;
151 				break;
152 		}
153 
154 		if (errflag) {
155 			(void) usage(argv[0]);
156 		}
157 	}
158 	if (argc <= optind) {
159 		(void) fprintf(stderr,
160 		    "No filename specified\n");
161 		usage(argv[0]);
162 	}
163 	filename = argv[optind];
164 
165 	if (vflag) {
166 		(void) fprintf(stderr, "Seed = %d\n", seed);
167 	}
168 	srandom(seed);
169 }
170 
171 static void
172 do_write(int fd)
173 {
174 	off_t	roffset = 0;
175 	char	*buf = NULL;
176 	char	*rbuf = NULL;
177 
178 	buf = (char *)calloc(1, bsize);
179 	rbuf = (char *)calloc(1, bsize);
180 	if (buf == NULL || rbuf == NULL) {
181 		perror("malloc");
182 		exit(4);
183 	}
184 
185 	roffset = random() % fsize;
186 	if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
187 		perror("lseek");
188 		exit(5);
189 	}
190 
191 	buf = "ZFS Test Suite Truncation Test";
192 	if (write(fd, buf, bsize) < bsize) {
193 		perror("write");
194 		exit(6);
195 	}
196 
197 	if (rflag) {
198 		if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
199 			perror("lseek");
200 			exit(7);
201 		}
202 
203 		if (read(fd, rbuf, bsize) < bsize) {
204 			perror("read");
205 			exit(8);
206 		}
207 
208 		if (memcmp(buf, rbuf, bsize) != 0) {
209 			perror("memcmp");
210 			exit(9);
211 		}
212 	}
213 	if (vflag) {
214 		(void) fprintf(stderr,
215 		    "Wrote to offset %lld\n", (offset + roffset));
216 		if (rflag) {
217 			(void) fprintf(stderr,
218 			    "Read back from offset %lld\n", (offset + roffset));
219 		}
220 	}
221 
222 	(void) free(buf);
223 	(void) free(rbuf);
224 }
225 
226 static void
227 do_trunc(int fd)
228 {
229 	off_t   roffset = 0;
230 
231 	roffset = random() % fsize;
232 	if (ftruncate64(fd, (offset + roffset))  < 0) {
233 		perror("truncate");
234 		exit(7);
235 	}
236 
237 	if (vflag) {
238 		(void) fprintf(stderr,
239 		    "Truncated at offset %lld\n",
240 		    (offset + roffset));
241 	}
242 }
243