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