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