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