Use _Noreturn (C11; GNU89) properly
[zfs.git] / tests / zfs-tests / cmd / mkfile / mkfile.c
blobf59a01efaca2e5d28404703fd7a2b84585505d4f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <libintl.h>
36 #include <errno.h>
37 #include <sys/stdtypes.h>
38 #include <sys/sysmacros.h>
40 #define BLOCKSIZE 512 /* bytes */
41 #define KILOBYTE 1024
42 #define MEGABYTE (KILOBYTE * KILOBYTE)
43 #define GIGABYTE (KILOBYTE * MEGABYTE)
45 #define FILE_MODE (S_ISVTX + S_IRUSR + S_IWUSR)
47 static _Noreturn void usage(void);
49 int
50 main(int argc, char **argv)
52 char *opts;
53 off_t size;
54 size_t len;
55 size_t mult = 1;
56 char *buf = NULL;
57 size_t bufsz = 0;
58 int errors = 0;
59 int i;
60 int verbose = 0; /* option variable */
61 int nobytes = 0; /* option variable */
62 int saverr;
64 if (argc == 1)
65 usage();
67 while (argv[1] && argv[1][0] == '-') {
68 opts = &argv[1][0];
69 while (*(++opts)) {
70 switch (*opts) {
71 case 'v':
72 verbose++;
73 break;
74 case 'n':
75 nobytes++;
76 break;
77 default:
78 usage();
81 argc--;
82 argv++;
84 if (argc < 3)
85 usage();
87 len = strlen(argv[1]);
88 if (len && isalpha(argv[1][len-1])) {
89 switch (argv[1][len-1]) {
90 case 'k':
91 case 'K':
92 mult = KILOBYTE;
93 break;
94 case 'b':
95 case 'B':
96 mult = BLOCKSIZE;
97 break;
98 case 'm':
99 case 'M':
100 mult = MEGABYTE;
101 break;
102 case 'g':
103 case 'G':
104 mult = GIGABYTE;
105 break;
106 default:
107 (void) fprintf(stderr,
108 gettext("unknown size %s\n"), argv[1]);
109 usage();
112 for (i = 0; i <= (len-2); i++) {
113 if (!isdigit(argv[1][i])) {
114 (void) fprintf(stderr,
115 gettext("unknown size %s\n"), argv[1]);
116 usage();
119 argv[1][len-1] = '\0';
121 size = ((off_t)atoll(argv[1]) * (off_t)mult);
123 argv++;
124 argc--;
126 while (argc > 1) {
127 int fd;
129 if (verbose)
130 (void) fprintf(stdout, gettext("%s %lld bytes\n"),
131 argv[1], (offset_t)size);
132 fd = open(argv[1], O_CREAT|O_TRUNC|O_RDWR, FILE_MODE);
133 if (fd < 0) {
134 saverr = errno;
135 (void) fprintf(stderr,
136 gettext("Could not open %s: %s\n"),
137 argv[1], strerror(saverr));
138 errors++;
139 argv++;
140 argc--;
141 continue;
142 } else if (fchown(fd, getuid(), getgid()) < 0) {
143 saverr = errno;
144 (void) fprintf(stderr, gettext(
145 "Could not set owner/group of %s: %s\n"),
146 argv[1], strerror(saverr));
147 (void) close(fd);
148 errors++;
149 argv++;
150 argc--;
151 continue;
152 } else if (lseek(fd, (off_t)size-1, SEEK_SET) < 0) {
153 saverr = errno;
154 (void) fprintf(stderr, gettext(
155 "Could not seek to offset %ld in %s: %s\n"),
156 (unsigned long)size-1, argv[1], strerror(saverr));
157 (void) close(fd);
158 errors++;
159 argv++;
160 argc--;
161 continue;
162 } else if (write(fd, "", 1) != 1) {
163 saverr = errno;
164 (void) fprintf(stderr, gettext(
165 "Could not set length of %s: %s\n"),
166 argv[1], strerror(saverr));
167 (void) close(fd);
168 errors++;
169 argv++;
170 argc--;
171 continue;
174 if (!nobytes) {
175 off_t written = 0;
176 struct stat64 st;
178 if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
179 saverr = errno;
180 (void) fprintf(stderr, gettext(
181 "Could not seek to beginning of %s: %s\n"),
182 argv[1], strerror(saverr));
183 (void) close(fd);
184 errors++;
185 argv++;
186 argc--;
187 continue;
189 if (fstat64(fd, &st) < 0) {
190 saverr = errno;
191 (void) fprintf(stderr, gettext(
192 "Could not fstat64 %s: %s\n"),
193 argv[1], strerror(saverr));
194 (void) close(fd);
195 errors++;
196 argv++;
197 argc--;
198 continue;
200 if (bufsz != st.st_blksize) {
201 if (buf)
202 free(buf);
203 bufsz = (size_t)st.st_blksize;
204 buf = calloc(1, bufsz);
205 if (buf == NULL) {
206 (void) fprintf(stderr, gettext(
207 "Could not allocate buffer of"
208 " size %d\n"), (int)bufsz);
209 (void) close(fd);
210 bufsz = 0;
211 errors++;
212 argv++;
213 argc--;
214 continue;
217 while (written < size) {
218 ssize_t result;
219 size_t bytes = (size_t)MIN(bufsz, size-written);
221 if ((result = write(fd, buf, bytes)) !=
222 (ssize_t)bytes) {
223 saverr = errno;
224 if (result < 0)
225 result = 0;
226 written += result;
227 (void) fprintf(stderr, gettext(
228 "%s: initialized %lu of %lu bytes: %s\n"),
229 argv[1], (unsigned long)written,
230 (unsigned long)size,
231 strerror(saverr));
232 errors++;
233 break;
235 written += bytes;
239 * A write(2) call in the above loop failed so
240 * close out this file and go on (error was
241 * already incremented when the write(2) failed).
243 if (written < size) {
244 (void) close(fd);
245 argv++;
246 argc--;
247 continue;
250 if (close(fd) < 0) {
251 saverr = errno;
252 (void) fprintf(stderr, gettext(
253 "Error encountered when closing %s: %s\n"),
254 argv[1], strerror(saverr));
255 errors++;
256 argv++;
257 argc--;
258 continue;
262 * Only set the modes (including the sticky bit) if we
263 * had no problems. It is not an error for the chmod(2)
264 * to fail, but do issue a warning.
266 if (chmod(argv[1], FILE_MODE) < 0)
267 (void) fprintf(stderr, gettext(
268 "warning: couldn't set mode to %#o\n"), FILE_MODE);
270 argv++;
271 argc--;
273 return (errors);
276 static void usage()
278 (void) fprintf(stderr, gettext(
279 "Usage: mkfile [-nv] <size>[g|k|b|m] <name1> [<name2>] ...\n"));
280 exit(1);