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