Merge commit 'b1e7e97d3b60469b243b3b2e22c7d8cbd11c7c90'
[unleashed.git] / usr / src / cmd / mkfile / mkfile.c
blob860aaab9b12a4f89efe3fb02d493cfd0de8a8904
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>
38 #define MIN(a, b) ((a) < (b) ? (a) : (b))
40 #define BLOCK_SIZE 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 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 = BLOCK_SIZE;
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;
143 if (lseek(fd, (off_t)size-1, SEEK_SET) < 0) {
144 saverr = errno;
145 (void) fprintf(stderr, gettext(
146 "Could not seek to offset %ld in %s: %s\n"),
147 (ulong_t)size-1, argv[1], strerror(saverr));
148 (void) close(fd);
149 errors++;
150 argv++;
151 argc--;
152 continue;
153 } else if (write(fd, "", 1) != 1) {
154 saverr = errno;
155 (void) fprintf(stderr, gettext(
156 "Could not set length of %s: %s\n"),
157 argv[1], strerror(saverr));
158 (void) close(fd);
159 errors++;
160 argv++;
161 argc--;
162 continue;
165 if (!nobytes) {
166 off_t written = 0;
167 struct stat64 st;
169 if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
170 saverr = errno;
171 (void) fprintf(stderr, gettext(
172 "Could not seek to beginning of %s: %s\n"),
173 argv[1], strerror(saverr));
174 (void) close(fd);
175 errors++;
176 argv++;
177 argc--;
178 continue;
180 if (fstat64(fd, &st) < 0) {
181 saverr = errno;
182 (void) fprintf(stderr, gettext(
183 "Could not fstat64 %s: %s\n"),
184 argv[1], strerror(saverr));
185 (void) close(fd);
186 errors++;
187 argv++;
188 argc--;
189 continue;
191 if (bufsz != st.st_blksize) {
192 free(buf);
193 bufsz = (size_t)st.st_blksize;
194 buf = calloc(bufsz, 1);
195 if (buf == NULL) {
196 (void) fprintf(stderr, gettext(
197 "Could not allocate buffer of"
198 " size %d\n"), (int)bufsz);
199 (void) close(fd);
200 bufsz = 0;
201 errors++;
202 argv++;
203 argc--;
204 continue;
207 while (written < size) {
208 ssize_t result;
209 size_t bytes = (size_t)MIN(bufsz, size-written);
211 if ((result = write(fd, buf, bytes)) !=
212 (ssize_t)bytes) {
213 saverr = errno;
214 if (result < 0)
215 result = 0;
216 written += result;
217 (void) fprintf(stderr, gettext(
218 "%s: initialized %lu of %lu bytes: %s\n"),
219 argv[1], (ulong_t)written,
220 (ulong_t)size,
221 strerror(saverr));
222 errors++;
223 break;
225 written += bytes;
229 * A write(2) call in the above loop failed so
230 * close out this file and go on (error was
231 * already incremented when the write(2) failed).
233 if (written < size) {
234 (void) close(fd);
235 argv++;
236 argc--;
237 continue;
240 if (close(fd) < 0) {
241 saverr = errno;
242 (void) fprintf(stderr, gettext(
243 "Error encountered when closing %s: %s\n"),
244 argv[1], strerror(saverr));
245 errors++;
246 argv++;
247 argc--;
248 continue;
252 * Only set the modes (including the sticky bit) if we
253 * had no problems. It is not an error for the chmod(2)
254 * to fail, but do issue a warning.
256 if (chmod(argv[1], FILE_MODE) < 0)
257 (void) fprintf(stderr, gettext(
258 "warning: couldn't set mode to %#o\n"), FILE_MODE);
260 argv++;
261 argc--;
263 return (errors);
266 static void usage()
268 (void) fprintf(stderr, gettext(
269 "Usage: mkfile [-nv] <size>[g|k|b|m] <name1> [<name2>] ...\n"));
270 exit(1);
271 /* NOTREACHED */