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