/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "../file_common.h" #include #include #include #include #include #include #include #include static unsigned char bigbuffer[BIGBUFFERSIZE]; /* * Writes (or appends) a given value to a file repeatedly. * See header file for defaults. */ static void usage(char *); /* * pseudo-randomize the buffer */ static void randomize_buffer(int block_size) { int i; char rnd = rand() & 0xff; for (i = 0; i < block_size; i++) bigbuffer[i] ^= rnd; } int main(int argc, char **argv) { int bigfd; int c; int oflag = 0; int err = 0; int k; long i; int64_t good_writes = 0; uchar_t nxtfillchar; char *prog = argv[0]; /* * Default Parameters */ int write_count = BIGFILESIZE; uchar_t fillchar = DATA; int block_size = BLOCKSZ; char *filename = NULL; char *operation = NULL; offset_t noffset, offset = 0; int verbose = 0; int rsync = 0; int wsync = 0; /* * Process Arguments */ while ((c = getopt(argc, argv, "b:c:d:s:f:o:vwr")) != -1) { switch (c) { case 'b': block_size = atoi(optarg); break; case 'c': write_count = atoi(optarg); break; case 'd': if (optarg[0] == 'R') fillchar = 'R'; /* R = random data */ else fillchar = atoi(optarg); break; case 's': offset = atoll(optarg); break; case 'f': filename = optarg; break; case 'o': operation = optarg; break; case 'v': verbose = 1; break; case 'w': wsync = 1; break; case 'r': rsync = 1; break; case '?': (void) printf("unknown arg %c\n", optopt); usage(prog); break; } } /* * Validate Parameters */ if (!filename) { (void) printf("Filename not specified (-f )\n"); err++; } if (!operation) { (void) printf("Operation not specified (-o ).\n"); err++; } if (block_size > BIGBUFFERSIZE) { (void) printf("block_size is too large max==%d.\n", BIGBUFFERSIZE); err++; } if (err) { usage(prog); /* no return */ return (1); } /* * Prepare the buffer and determine the requested operation */ nxtfillchar = fillchar; k = 0; if (fillchar == 'R') srand(time(NULL)); for (i = 0; i < block_size; i++) { bigbuffer[i] = nxtfillchar; if (fillchar == 0) { if ((k % DATA_RANGE) == 0) { k = 0; } nxtfillchar = k++; } else if (fillchar == 'R') { nxtfillchar = rand() & 0xff; } } /* * using the strncmp of operation will make the operation match the * first shortest match - as the operations are unique from the first * character this means that we match single character operations */ if ((strncmp(operation, "create", strlen(operation) + 1)) == 0 || (strncmp(operation, "overwrite", strlen(operation) + 1)) == 0) { oflag = (O_RDWR|O_CREAT); } else if ((strncmp(operation, "append", strlen(operation) + 1)) == 0) { oflag = (O_RDWR|O_APPEND); } else { (void) printf("valid operations are not '%s'\n", operation); usage(prog); } if (rsync) { oflag = oflag | O_RSYNC; } if (wsync) { oflag = oflag | O_SYNC; } /* * Given an operation (create/overwrite/append), open the file * accordingly and perform a write of the appropriate type. */ if ((bigfd = open(filename, oflag, 0666)) == -1) { (void) printf("open %s: failed [%s]%d. Aborting!\n", filename, strerror(errno), errno); exit(errno); } noffset = lseek64(bigfd, offset, SEEK_SET); if (noffset != offset) { (void) printf("llseek %s (%lld/%lld) failed [%s]%d.Aborting!\n", filename, offset, noffset, strerror(errno), errno); exit(errno); } if (verbose) { (void) printf("%s: block_size = %d, write_count = %d, " "offset = %lld, ", filename, block_size, write_count, offset); if (fillchar == 'R') { (void) printf("data = [random]\n"); } else { (void) printf("data = %s%d\n", (fillchar == 0) ? "0->" : "", (fillchar == 0) ? DATA_RANGE : fillchar); } } for (i = 0; i < write_count; i++) { ssize_t n; if (fillchar == 'R') randomize_buffer(block_size); if ((n = write(bigfd, &bigbuffer, block_size)) == -1) { (void) printf("write failed (%ld), good_writes = %" PRId64 ", " "error: %s[%d]\n", (long)n, good_writes, strerror(errno), errno); exit(errno); } good_writes++; } if (verbose) { (void) printf("Success: good_writes = %" PRId64 "(%" PRId64 ")\n", good_writes, (good_writes * block_size)); } return (0); } static void usage(char *prog) { (void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name" " [-b block_size]\n" "\t[-s offset] [-c write_count] [-d data]\n\n" "Where [data] equal to zero causes chars " "0->%d to be repeated throughout, or [data]\n" "equal to 'R' for pseudorandom data.\n", prog, DATA_RANGE); exit(1); }