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
usage(char * execname)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
main(int argc,char * argv[])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
parse_options(int argc,char * argv[])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
do_write(int fd)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
do_trunc(int fd)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