Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_write.c
48674 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* 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.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright 2007 Sun Microsystems, Inc. All rights reserved.24* Use is subject to license terms.25*/2627#include "file_common.h"28#include <libgen.h>29#include <string.h>30#include <inttypes.h>31#include <sys/types.h>32#include <unistd.h>33#include <stdlib.h>34#include <time.h>35#include <stdint.h>3637static unsigned char bigbuffer[BIGBUFFERSIZE];3839/*40* Writes (or appends) a given value to a file repeatedly.41* See header file for defaults.42*/4344static void usage(char *);4546/*47* pseudo-randomize the buffer48*/49static void randomize_buffer(int block_size) {50int i;51char rnd = rand() & 0xff;52for (i = 0; i < block_size; i++)53bigbuffer[i] ^= rnd;54}5556int57main(int argc, char **argv)58{59int bigfd;60int c;61int oflag = 0;62int err = 0;63int k;64long i;65int64_t good_writes = 0;66uchar_t nxtfillchar;67char *prog = argv[0];68/*69* Default Parameters70*/71int write_count = BIGFILESIZE;72uchar_t fillchar = DATA;73int block_size = BLOCKSZ;74char *filename = NULL;75char *operation = NULL;76offset_t noffset, offset = 0;77int verbose = 0;78int rsync = 0;79int wsync = 0;8081/*82* Process Arguments83*/84while ((c = getopt(argc, argv, "b:c:d:s:f:o:vwr")) != -1) {85switch (c) {86case 'b':87block_size = atoi(optarg);88break;89case 'c':90write_count = atoi(optarg);91break;92case 'd':93if (optarg[0] == 'R')94fillchar = 'R'; /* R = random data */95else96fillchar = atoi(optarg);97break;98case 's':99offset = atoll(optarg);100break;101case 'f':102filename = optarg;103break;104case 'o':105operation = optarg;106break;107case 'v':108verbose = 1;109break;110case 'w':111wsync = 1;112break;113case 'r':114rsync = 1;115break;116case '?':117(void) printf("unknown arg %c\n", optopt);118usage(prog);119break;120}121}122123/*124* Validate Parameters125*/126if (!filename) {127(void) printf("Filename not specified (-f <file>)\n");128err++;129}130131if (!operation) {132(void) printf("Operation not specified (-o <operation>).\n");133err++;134}135136if (block_size > BIGBUFFERSIZE) {137(void) printf("block_size is too large max==%d.\n",138BIGBUFFERSIZE);139err++;140}141142if (err) {143usage(prog); /* no return */144return (1);145}146147/*148* Prepare the buffer and determine the requested operation149*/150nxtfillchar = fillchar;151k = 0;152153if (fillchar == 'R')154srand(time(NULL));155156for (i = 0; i < block_size; i++) {157bigbuffer[i] = nxtfillchar;158159if (fillchar == 0) {160if ((k % DATA_RANGE) == 0) {161k = 0;162}163nxtfillchar = k++;164} else if (fillchar == 'R') {165nxtfillchar = rand() & 0xff;166}167}168169/*170* using the strncmp of operation will make the operation match the171* first shortest match - as the operations are unique from the first172* character this means that we match single character operations173*/174if ((strncmp(operation, "create", strlen(operation) + 1)) == 0 ||175(strncmp(operation, "overwrite", strlen(operation) + 1)) == 0) {176oflag = (O_RDWR|O_CREAT);177} else if ((strncmp(operation, "append", strlen(operation) + 1)) == 0) {178oflag = (O_RDWR|O_APPEND);179} else {180(void) printf("valid operations are <create|append> not '%s'\n",181operation);182usage(prog);183}184185if (rsync) {186oflag = oflag | O_RSYNC;187}188189if (wsync) {190oflag = oflag | O_SYNC;191}192193/*194* Given an operation (create/overwrite/append), open the file195* accordingly and perform a write of the appropriate type.196*/197if ((bigfd = open(filename, oflag, 0666)) == -1) {198(void) printf("open %s: failed [%s]%d. Aborting!\n", filename,199strerror(errno), errno);200exit(errno);201}202noffset = lseek64(bigfd, offset, SEEK_SET);203if (noffset != offset) {204(void) printf("llseek %s (%lld/%lld) failed [%s]%d.Aborting!\n",205filename, offset, noffset, strerror(errno), errno);206exit(errno);207}208209if (verbose) {210(void) printf("%s: block_size = %d, write_count = %d, "211"offset = %lld, ", filename, block_size,212write_count, offset);213if (fillchar == 'R') {214(void) printf("data = [random]\n");215} else {216(void) printf("data = %s%d\n",217(fillchar == 0) ? "0->" : "",218(fillchar == 0) ? DATA_RANGE : fillchar);219}220}221222for (i = 0; i < write_count; i++) {223ssize_t n;224if (fillchar == 'R')225randomize_buffer(block_size);226227if ((n = write(bigfd, &bigbuffer, block_size)) == -1) {228(void) printf("write failed (%ld), good_writes = %"229PRId64 ", " "error: %s[%d]\n",230(long)n, good_writes,231strerror(errno),232errno);233exit(errno);234}235good_writes++;236}237238if (verbose) {239(void) printf("Success: good_writes = %" PRId64 "(%"240PRId64 ")\n", good_writes, (good_writes * block_size));241}242243return (0);244}245246static void247usage(char *prog)248{249(void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name"250" [-b block_size]\n"251"\t[-s offset] [-c write_count] [-d data]\n\n"252"Where [data] equal to zero causes chars "253"0->%d to be repeated throughout, or [data]\n"254"equal to 'R' for pseudorandom data.\n",255prog, DATA_RANGE);256257exit(1);258}259260261