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