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