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