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 https://opensource.org/licenses/CDDL-1.0. 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, 2014 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/stat.h> 39 #include <sys/statvfs.h> 40 #include <sys/time.h> 41 #include <sys/ioctl.h> 42 #include <sys/wait.h> 43 #include <sys/param.h> 44 #include <string.h> 45 #include <time.h> 46 #include <inttypes.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 for (i = 0; count == 0 || i < count; i++) { 91 (void) do_write(fd); 92 (void) do_trunc(fd); 93 } 94 95 (void) close(fd); 96 return (0); 97 } 98 99 static void 100 parse_options(int argc, char *argv[]) 101 { 102 int c; 103 104 extern char *optarg; 105 extern int optind, optopt; 106 107 count = fsize / bsize; 108 seed = time(NULL); 109 while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) { 110 switch (c) { 111 case 'b': 112 bsize = atoi(optarg); 113 break; 114 115 case 'c': 116 count = atoi(optarg); 117 break; 118 119 case 'f': 120 fsize = atoi(optarg); 121 break; 122 123 case 'o': 124 offset = atoi(optarg); 125 break; 126 127 case 'r': 128 rflag++; 129 break; 130 131 case 's': 132 seed = atoi(optarg); 133 break; 134 135 case 'v': 136 vflag++; 137 break; 138 139 case ':': 140 (void) fprintf(stderr, 141 "Option -%c requires an operand\n", optopt); 142 errflag++; 143 break; 144 145 case '?': 146 (void) fprintf(stderr, 147 "Unrecognized option: -%c\n", optopt); 148 errflag++; 149 break; 150 } 151 152 if (errflag) { 153 (void) usage(argv[0]); 154 } 155 } 156 if (argc <= optind) { 157 (void) fprintf(stderr, 158 "No filename specified\n"); 159 usage(argv[0]); 160 } 161 filename = argv[optind]; 162 163 if (vflag) { 164 (void) fprintf(stderr, "Seed = %d\n", seed); 165 } 166 srandom(seed); 167 } 168 169 static void 170 do_write(int fd) 171 { 172 off_t roffset = 0; 173 char *buf = NULL; 174 char *rbuf = NULL; 175 176 buf = (char *)calloc(1, bsize); 177 rbuf = (char *)calloc(1, bsize); 178 if (buf == NULL || rbuf == NULL) { 179 perror("malloc"); 180 exit(4); 181 } 182 183 roffset = random() % fsize; 184 if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) { 185 perror("lseek"); 186 exit(5); 187 } 188 189 (void) strcpy(buf, "ZFS Test Suite Truncation Test"); 190 if (write(fd, buf, bsize) < bsize) { 191 perror("write"); 192 exit(6); 193 } 194 195 if (rflag) { 196 if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) { 197 perror("lseek"); 198 exit(7); 199 } 200 201 if (read(fd, rbuf, bsize) < bsize) { 202 perror("read"); 203 exit(8); 204 } 205 206 if (memcmp(buf, rbuf, bsize) != 0) { 207 perror("memcmp"); 208 exit(9); 209 } 210 } 211 if (vflag) { 212 (void) fprintf(stderr, 213 "Wrote to offset %" PRId64 "\n", (offset + roffset)); 214 if (rflag) { 215 (void) fprintf(stderr, 216 "Read back from offset %" PRId64 "\n", 217 (offset + roffset)); 218 } 219 } 220 221 (void) free(buf); 222 (void) free(rbuf); 223 } 224 225 static void 226 do_trunc(int fd) 227 { 228 off_t roffset = 0; 229 230 roffset = random() % fsize; 231 if (ftruncate64(fd, (offset + roffset)) < 0) { 232 perror("truncate"); 233 exit(7); 234 } 235 236 if (vflag) { 237 (void) fprintf(stderr, "Truncated at offset %" PRId64 "\n", 238 (offset + roffset)); 239 } 240 } 241