1132624Smarcel/* 2132624Smarcel * CDDL HEADER START 3132624Smarcel * 4132624Smarcel * The contents of this file are subject to the terms of the 5132624Smarcel * Common Development and Distribution License (the "License"). 6132624Smarcel * You may not use this file except in compliance with the License. 7132624Smarcel * 8132624Smarcel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9132624Smarcel * or https://opensource.org/licenses/CDDL-1.0. 10132624Smarcel * See the License for the specific language governing permissions 11132624Smarcel * and limitations under the License. 12132624Smarcel * 13132624Smarcel * When distributing Covered Code, include this CDDL HEADER in each 14132624Smarcel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15132624Smarcel * If applicable, add the following below this CDDL HEADER, with the 16132624Smarcel * fields enclosed by brackets "[]" replaced with your own identifying 17132624Smarcel * information: Portions Copyright [yyyy] [name of copyright owner] 18132624Smarcel * 19132624Smarcel * CDDL HEADER END 20132624Smarcel */ 21132624Smarcel 22132624Smarcel/* 23132624Smarcel * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24132624Smarcel * Use is subject to license terms. 25132624Smarcel */ 26132624Smarcel 27132624Smarcel#include "file_common.h" 28132624Smarcel#include <libgen.h> 29132624Smarcel#include <string.h> 30142151Skan#include <inttypes.h> 31142151Skan#include <sys/types.h> 32142151Skan#include <unistd.h> 33142151Skan#include <stdlib.h> 34175808Sjhb#include <time.h> 35178670Sjhb#include <stdint.h> 36132624Smarcel 37132624Smarcelstatic unsigned char bigbuffer[BIGBUFFERSIZE]; 38132624Smarcel 39178670Sjhb/* 40178670Sjhb * Writes (or appends) a given value to a file repeatedly. 41142151Skan * See header file for defaults. 42175808Sjhb */ 43149954Smarcel 44178713Sjhbstatic void usage(char *); 45178670Sjhb 46132624Smarcel/* 47132624Smarcel * pseudo-randomize the buffer 48178670Sjhb */ 49142151Skanstatic void randomize_buffer(int block_size) { 50178670Sjhb int i; 51132624Smarcel char rnd = rand() & 0xff; 52178713Sjhb for (i = 0; i < block_size; i++) 53132624Smarcel bigbuffer[i] ^= rnd; 54142151Skan} 55142151Skan 56246893Smarcelint 57246893Smarcelmain(int argc, char **argv) 58178670Sjhb{ 59178670Sjhb int bigfd; 60178670Sjhb int c; 61132624Smarcel int oflag = 0; 62132624Smarcel int err = 0; 63178670Sjhb int k; 64178670Sjhb long i; 65175808Sjhb int64_t good_writes = 0; 66163439Sjhb uchar_t nxtfillchar; 67286305Skib char *prog = argv[0]; 68163439Sjhb /* 69163439Sjhb * Default Parameters 70163439Sjhb */ 71163439Sjhb int write_count = BIGFILESIZE; 72163439Sjhb uchar_t fillchar = DATA; 73163439Sjhb int block_size = BLOCKSZ; 74163439Sjhb char *filename = NULL; 75163439Sjhb char *operation = NULL; 76163439Sjhb offset_t noffset, offset = 0; 77163439Sjhb int verbose = 0; 78163439Sjhb int rsync = 0; 79163439Sjhb int wsync = 0; 80163439Sjhb 81163439Sjhb /* 82163439Sjhb * Process Arguments 83163439Sjhb */ 84163439Sjhb while ((c = getopt(argc, argv, "b:c:d:s:f:o:vwr")) != -1) { 85163439Sjhb switch (c) { 86178670Sjhb case 'b': 87178670Sjhb block_size = atoi(optarg); 88178670Sjhb break; 89178670Sjhb case 'c': 90178670Sjhb write_count = atoi(optarg); 91178670Sjhb break; 92178670Sjhb case 'd': 93178670Sjhb if (optarg[0] == 'R') 94178670Sjhb fillchar = 'R'; /* R = random data */ 95178670Sjhb else 96178670Sjhb fillchar = atoi(optarg); 97178670Sjhb break; 98178670Sjhb case 's': 99178670Sjhb offset = atoll(optarg); 100178670Sjhb break; 101178670Sjhb case 'f': 102178670Sjhb filename = optarg; 103178670Sjhb break; 104178670Sjhb case 'o': 105178670Sjhb operation = optarg; 106178670Sjhb break; 107178670Sjhb case 'v': 108178670Sjhb verbose = 1; 109178670Sjhb break; 110178670Sjhb case 'w': 111178670Sjhb wsync = 1; 112178670Sjhb break; 113178670Sjhb case 'r': 114178670Sjhb rsync = 1; 115178670Sjhb break; 116178670Sjhb case '?': 117178670Sjhb (void) printf("unknown arg %c\n", optopt); 118178670Sjhb usage(prog); 119178670Sjhb break; 120178670Sjhb } 121178670Sjhb } 122178670Sjhb 123178670Sjhb /* 124178670Sjhb * Validate Parameters 125178670Sjhb */ 126178670Sjhb if (!filename) { 127178670Sjhb (void) printf("Filename not specified (-f <file>)\n"); 128178670Sjhb err++; 129178670Sjhb } 130178670Sjhb 131178670Sjhb if (!operation) { 132178713Sjhb (void) printf("Operation not specified (-o <operation>).\n"); 133178670Sjhb err++; 134178670Sjhb } 135178670Sjhb 136178713Sjhb if (block_size > BIGBUFFERSIZE) { 137178670Sjhb (void) printf("block_size is too large max==%d.\n", 138178670Sjhb BIGBUFFERSIZE); 139178670Sjhb err++; 140178670Sjhb } 141178670Sjhb 142178670Sjhb if (err) { 143178670Sjhb usage(prog); /* no return */ 144178670Sjhb return (1); 145178670Sjhb } 146178670Sjhb 147178670Sjhb /* 148178670Sjhb * Prepare the buffer and determine the requested operation 149178670Sjhb */ 150178670Sjhb nxtfillchar = fillchar; 151178670Sjhb k = 0; 152178670Sjhb 153178670Sjhb if (fillchar == 'R') 154178670Sjhb srand(time(NULL)); 155178670Sjhb 156178670Sjhb for (i = 0; i < block_size; i++) { 157178670Sjhb bigbuffer[i] = nxtfillchar; 158178670Sjhb 159178670Sjhb if (fillchar == 0) { 160178670Sjhb if ((k % DATA_RANGE) == 0) { 161178670Sjhb k = 0; 162178670Sjhb } 163178670Sjhb nxtfillchar = k++; 164178670Sjhb } else if (fillchar == 'R') { 165178670Sjhb nxtfillchar = rand() & 0xff; 166178670Sjhb } 167178670Sjhb } 168178670Sjhb 169178670Sjhb /* 170178670Sjhb * using the strncmp of operation will make the operation match the 171178670Sjhb * first shortest match - as the operations are unique from the first 172178670Sjhb * character this means that we match single character operations 173178670Sjhb */ 174178670Sjhb if ((strncmp(operation, "create", strlen(operation) + 1)) == 0 || 175178670Sjhb (strncmp(operation, "overwrite", strlen(operation) + 1)) == 0) { 176178670Sjhb oflag = (O_RDWR|O_CREAT); 177178670Sjhb } else if ((strncmp(operation, "append", strlen(operation) + 1)) == 0) { 178178670Sjhb oflag = (O_RDWR|O_APPEND); 179178670Sjhb } else { 180178670Sjhb (void) printf("valid operations are <create|append> not '%s'\n", 181178670Sjhb operation); 182178670Sjhb usage(prog); 183178670Sjhb } 184178670Sjhb 185178670Sjhb if (rsync) { 186178670Sjhb oflag = oflag | O_RSYNC; 187178670Sjhb } 188178670Sjhb 189178670Sjhb if (wsync) { 190178670Sjhb oflag = oflag | O_SYNC; 191148802Smarcel } 192148802Smarcel 193148802Smarcel /* 194142151Skan * Given an operation (create/overwrite/append), open the file 195178713Sjhb * accordingly and perform a write of the appropriate type. 196142151Skan */ 197142151Skan if ((bigfd = open(filename, oflag, 0666)) == -1) { 198148802Smarcel (void) printf("open %s: failed [%s]%d. Aborting!\n", filename, 199148802Smarcel strerror(errno), errno); 200132624Smarcel exit(errno); 201148802Smarcel } 202178670Sjhb noffset = lseek64(bigfd, offset, SEEK_SET); 203178670Sjhb if (noffset != offset) { 204178670Sjhb (void) printf("llseek %s (%lld/%lld) failed [%s]%d.Aborting!\n", 205132624Smarcel filename, offset, noffset, strerror(errno), errno); 206132624Smarcel exit(errno); 207132624Smarcel } 208132624Smarcel 209132624Smarcel if (verbose) { 210148802Smarcel (void) printf("%s: block_size = %d, write_count = %d, " 211148802Smarcel "offset = %lld, ", filename, block_size, 212148802Smarcel write_count, offset); 213148802Smarcel if (fillchar == 'R') { 214148802Smarcel (void) printf("data = [random]\n"); 215148802Smarcel } else { 216148802Smarcel (void) printf("data = %s%d\n", 217148802Smarcel (fillchar == 0) ? "0->" : "", 218132624Smarcel (fillchar == 0) ? DATA_RANGE : fillchar); 219132624Smarcel } 220132624Smarcel } 221132624Smarcel 222132624Smarcel for (i = 0; i < write_count; i++) { 223142151Skan ssize_t n; 224132624Smarcel if (fillchar == 'R') 225178713Sjhb randomize_buffer(block_size); 226132624Smarcel 227132624Smarcel if ((n = write(bigfd, &bigbuffer, block_size)) == -1) { 228132624Smarcel (void) printf("write failed (%ld), good_writes = %" 229132624Smarcel PRId64 ", " "error: %s[%d]\n", 230132624Smarcel (long)n, good_writes, 231132624Smarcel strerror(errno), 232178713Sjhb errno); 233132624Smarcel exit(errno); 234132624Smarcel } 235132624Smarcel good_writes++; 236132624Smarcel } 237148802Smarcel 238132624Smarcel if (verbose) { 239148802Smarcel (void) printf("Success: good_writes = %" PRId64 "(%" 240132624Smarcel PRId64 ")\n", good_writes, (good_writes * block_size)); 241148802Smarcel } 242148802Smarcel 243148802Smarcel return (0); 244148802Smarcel} 245148802Smarcel 246148802Smarcelstatic void 247148802Smarcelusage(char *prog) 248142151Skan{ 249148802Smarcel (void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name" 250148802Smarcel " [-b block_size]\n" 251142151Skan "\t[-s offset] [-c write_count] [-d data]\n\n" 252142151Skan "Where [data] equal to zero causes chars " 253178670Sjhb "0->%d to be repeated throughout, or [data]\n" 254178670Sjhb "equal to 'R' for pseudorandom data.\n", 255178670Sjhb prog, DATA_RANGE); 256178670Sjhb 257178670Sjhb exit(1); 258178670Sjhb} 259178670Sjhb