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 * $FreeBSD$ 21 */ 22 23 /* 24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "@(#)file_write.c 1.4 07/10/09 SMI" 29 30 #include "file_common.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); 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 (%lld/%lld) 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 = %lld, 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), good_writes = %lld, " 201 "error: %s[%d]\n", (long)n, good_writes, 202 strerror(errno), 203 errno); 204 exit(errno); 205 } 206 good_writes++; 207 } 208 209 if (verbose) { 210 (void) printf("Success: good_writes = %lld (%lld)\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