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