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