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 #include "file_common.h" 28 #include <libgen.h> 29 #include <string.h> 30 #include <inttypes.h> 31 #include <sys/types.h> 32 #include <unistd.h> 33 #include <stdlib.h> 34 #include <time.h> 35 #include <stdint.h> 36 37 static unsigned char bigbuffer[BIGBUFFERSIZE]; 38 39 /* 40 * Writes (or appends) a given value to a file repeatedly. 41 * See header file for defaults. 42 */ 43 44 static void usage(char *); 45 46 /* 47 * pseudo-randomize the buffer 48 */ 49 static void randomize_buffer(int block_size) { 50 int i; 51 char rnd = rand() & 0xff; 52 for (i = 0; i < block_size; i++) 53 bigbuffer[i] ^= rnd; 54 } 55 56 int 57 main(int argc, char **argv) 58 { 59 int bigfd; 60 int c; 61 int oflag = 0; 62 int err = 0; 63 int k; 64 long i; 65 int64_t good_writes = 0; 66 uchar_t nxtfillchar; 67 char *prog = argv[0]; 68 /* 69 * Default Parameters 70 */ 71 int write_count = BIGFILESIZE; 72 uchar_t fillchar = DATA; 73 int block_size = BLOCKSZ; 74 char *filename = NULL; 75 char *operation = NULL; 76 offset_t noffset, offset = 0; 77 int verbose = 0; 78 int rsync = 0; 79 int wsync = 0; 80 81 /* 82 * Process Arguments 83 */ 84 while ((c = getopt(argc, argv, "b:c:d:s:f:o:vwr")) != -1) { 85 switch (c) { 86 case 'b': 87 block_size = atoi(optarg); 88 break; 89 case 'c': 90 write_count = atoi(optarg); 91 break; 92 case 'd': 93 if (optarg[0] == 'R') 94 fillchar = 'R'; /* R = random data */ 95 else 96 fillchar = atoi(optarg); 97 break; 98 case 's': 99 offset = atoll(optarg); 100 break; 101 case 'f': 102 filename = optarg; 103 break; 104 case 'o': 105 operation = optarg; 106 break; 107 case 'v': 108 verbose = 1; 109 break; 110 case 'w': 111 wsync = 1; 112 break; 113 case 'r': 114 rsync = 1; 115 break; 116 case '?': 117 (void) printf("unknown arg %c\n", optopt); 118 usage(prog); 119 break; 120 } 121 } 122 123 /* 124 * Validate Parameters 125 */ 126 if (!filename) { 127 (void) printf("Filename not specified (-f <file>)\n"); 128 err++; 129 } 130 131 if (!operation) { 132 (void) printf("Operation not specified (-o <operation>).\n"); 133 err++; 134 } 135 136 if (block_size > BIGBUFFERSIZE) { 137 (void) printf("block_size is too large max==%d.\n", 138 BIGBUFFERSIZE); 139 err++; 140 } 141 142 if (err) { 143 usage(prog); /* no return */ 144 return (1); 145 } 146 147 /* 148 * Prepare the buffer and determine the requested operation 149 */ 150 nxtfillchar = fillchar; 151 k = 0; 152 153 if (fillchar == 'R') 154 srand(time(NULL)); 155 156 for (i = 0; i < block_size; i++) { 157 bigbuffer[i] = nxtfillchar; 158 159 if (fillchar == 0) { 160 if ((k % DATA_RANGE) == 0) { 161 k = 0; 162 } 163 nxtfillchar = k++; 164 } else if (fillchar == 'R') { 165 nxtfillchar = rand() & 0xff; 166 } 167 } 168 169 /* 170 * using the strncmp of operation will make the operation match the 171 * first shortest match - as the operations are unique from the first 172 * character this means that we match single character operations 173 */ 174 if ((strncmp(operation, "create", strlen(operation) + 1)) == 0 || 175 (strncmp(operation, "overwrite", strlen(operation) + 1)) == 0) { 176 oflag = (O_RDWR|O_CREAT); 177 } else if ((strncmp(operation, "append", strlen(operation) + 1)) == 0) { 178 oflag = (O_RDWR|O_APPEND); 179 } else { 180 (void) printf("valid operations are <create|append> not '%s'\n", 181 operation); 182 usage(prog); 183 } 184 185 if (rsync) { 186 oflag = oflag | O_RSYNC; 187 } 188 189 if (wsync) { 190 oflag = oflag | O_SYNC; 191 } 192 193 /* 194 * Given an operation (create/overwrite/append), open the file 195 * accordingly and perform a write of the appropriate type. 196 */ 197 if ((bigfd = open(filename, oflag, 0666)) == -1) { 198 (void) printf("open %s: failed [%s]%d. Aborting!\n", filename, 199 strerror(errno), errno); 200 exit(errno); 201 } 202 noffset = lseek64(bigfd, offset, SEEK_SET); 203 if (noffset != offset) { 204 (void) printf("llseek %s (%lld/%lld) failed [%s]%d.Aborting!\n", 205 filename, offset, noffset, strerror(errno), errno); 206 exit(errno); 207 } 208 209 if (verbose) { 210 (void) printf("%s: block_size = %d, write_count = %d, " 211 "offset = %lld, ", filename, block_size, 212 write_count, offset); 213 if (fillchar == 'R') { 214 (void) printf("data = [random]\n"); 215 } else { 216 (void) printf("data = %s%d\n", 217 (fillchar == 0) ? "0->" : "", 218 (fillchar == 0) ? DATA_RANGE : fillchar); 219 } 220 } 221 222 for (i = 0; i < write_count; i++) { 223 ssize_t n; 224 if (fillchar == 'R') 225 randomize_buffer(block_size); 226 227 if ((n = write(bigfd, &bigbuffer, block_size)) == -1) { 228 (void) printf("write failed (%ld), good_writes = %" 229 PRId64 ", " "error: %s[%d]\n", 230 (long)n, good_writes, 231 strerror(errno), 232 errno); 233 exit(errno); 234 } 235 good_writes++; 236 } 237 238 if (verbose) { 239 (void) printf("Success: good_writes = %" PRId64 "(%" 240 PRId64 ")\n", good_writes, (good_writes * block_size)); 241 } 242 243 return (0); 244 } 245 246 static void 247 usage(char *prog) 248 { 249 (void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name" 250 " [-b block_size]\n" 251 "\t[-s offset] [-c write_count] [-d data]\n\n" 252 "Where [data] equal to zero causes chars " 253 "0->%d to be repeated throughout, or [data]\n" 254 "equal to 'R' for pseudorandom data.\n", 255 prog, DATA_RANGE); 256 257 exit(1); 258 } 259