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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 #pragma ident "%Z%%M% %I% %E% SMI" 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 39 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 40 41 #define BLOCK_SIZE 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 void usage(void); 49 50 int 51 main(int argc, char **argv) 52 { 53 char *opts; 54 off_t size; 55 size_t len; 56 size_t mult = 1; 57 char *buf = NULL; 58 size_t bufsz = 0; 59 int errors = 0; 60 int i; 61 int verbose = 0; /* option variable */ 62 int nobytes = 0; /* option variable */ 63 int saverr; 64 65 if (argc == 1) 66 usage(); 67 68 while (argv[1] && argv[1][0] == '-') { 69 opts = &argv[1][0]; 70 while (*(++opts)) { 71 switch (*opts) { 72 case 'v': 73 verbose++; 74 break; 75 case 'n': 76 nobytes++; 77 break; 78 default: 79 usage(); 80 } 81 } 82 argc--; 83 argv++; 84 } 85 if (argc < 3) 86 usage(); 87 88 len = strlen(argv[1]); 89 if (len && isalpha(argv[1][len-1])) { 90 switch (argv[1][len-1]) { 91 case 'k': 92 case 'K': 93 mult = KILOBYTE; 94 break; 95 case 'b': 96 case 'B': 97 mult = BLOCK_SIZE; 98 break; 99 case 'm': 100 case 'M': 101 mult = MEGABYTE; 102 break; 103 case 'g': 104 case 'G': 105 mult = GIGABYTE; 106 break; 107 default: 108 (void) fprintf(stderr, 109 gettext("unknown size %s\n"), argv[1]); 110 usage(); 111 } 112 113 for (i = 0; i <= (len-2); i++) { 114 if (!isdigit(argv[1][i])) { 115 (void) fprintf(stderr, 116 gettext("unknown size %s\n"), argv[1]); 117 usage(); 118 } 119 } 120 argv[1][len-1] = '\0'; 121 } 122 size = ((off_t)atoll(argv[1]) * (off_t)mult); 123 124 argv++; 125 argc--; 126 127 while (argc > 1) { 128 int fd; 129 130 if (verbose) 131 (void) fprintf(stdout, gettext("%s %lld bytes\n"), 132 argv[1], (offset_t)size); 133 fd = open(argv[1], O_CREAT|O_TRUNC|O_RDWR, FILE_MODE); 134 if (fd < 0) { 135 saverr = errno; 136 (void) fprintf(stderr, 137 gettext("Could not open %s: %s\n"), 138 argv[1], strerror(saverr)); 139 errors++; 140 argv++; 141 argc--; 142 continue; 143 } 144 if (lseek(fd, (off_t)size-1, SEEK_SET) < 0) { 145 saverr = errno; 146 (void) fprintf(stderr, gettext( 147 "Could not seek to offset %ld in %s: %s\n"), 148 (ulong_t)size-1, argv[1], strerror(saverr)); 149 (void) close(fd); 150 errors++; 151 argv++; 152 argc--; 153 continue; 154 } else if (write(fd, "", 1) != 1) { 155 saverr = errno; 156 (void) fprintf(stderr, gettext( 157 "Could not set length of %s: %s\n"), 158 argv[1], strerror(saverr)); 159 (void) close(fd); 160 errors++; 161 argv++; 162 argc--; 163 continue; 164 } 165 166 if (!nobytes) { 167 off_t written = 0; 168 struct stat64 st; 169 170 if (lseek(fd, (off_t)0, SEEK_SET) < 0) { 171 saverr = errno; 172 (void) fprintf(stderr, gettext( 173 "Could not seek to beginning of %s: %s\n"), 174 argv[1], strerror(saverr)); 175 (void) close(fd); 176 errors++; 177 argv++; 178 argc--; 179 continue; 180 } 181 if (fstat64(fd, &st) < 0) { 182 saverr = errno; 183 (void) fprintf(stderr, gettext( 184 "Could not fstat64 %s: %s\n"), 185 argv[1], strerror(saverr)); 186 (void) close(fd); 187 errors++; 188 argv++; 189 argc--; 190 continue; 191 } 192 if (bufsz != st.st_blksize) { 193 if (buf) 194 free(buf); 195 bufsz = (size_t)st.st_blksize; 196 buf = calloc(bufsz, 1); 197 if (buf == NULL) { 198 (void) fprintf(stderr, gettext( 199 "Could not allocate buffer of" 200 " size %d\n"), (int)bufsz); 201 (void) close(fd); 202 bufsz = 0; 203 errors++; 204 argv++; 205 argc--; 206 continue; 207 } 208 } 209 while (written < size) { 210 ssize_t result; 211 size_t bytes = (size_t)MIN(bufsz, size-written); 212 213 if ((result = write(fd, buf, bytes)) != 214 (ssize_t)bytes) { 215 saverr = errno; 216 if (result < 0) 217 result = 0; 218 written += result; 219 (void) fprintf(stderr, gettext( 220 "%s: initialized %lu of %lu bytes: %s\n"), 221 argv[1], (ulong_t)written, 222 (ulong_t)size, 223 strerror(saverr)); 224 errors++; 225 break; 226 } 227 written += bytes; 228 } 229 230 /* 231 * A write(2) call in the above loop failed so 232 * close out this file and go on (error was 233 * already incremented when the write(2) failed). 234 */ 235 if (written < size) { 236 (void) close(fd); 237 argv++; 238 argc--; 239 continue; 240 } 241 } 242 if (close(fd) < 0) { 243 saverr = errno; 244 (void) fprintf(stderr, gettext( 245 "Error encountered when closing %s: %s\n"), 246 argv[1], strerror(saverr)); 247 errors++; 248 argv++; 249 argc--; 250 continue; 251 } 252 253 /* 254 * Only set the modes (including the sticky bit) if we 255 * had no problems. It is not an error for the chmod(2) 256 * to fail, but do issue a warning. 257 */ 258 if (chmod(argv[1], FILE_MODE) < 0) 259 (void) fprintf(stderr, gettext( 260 "warning: couldn't set mode to %#o\n"), FILE_MODE); 261 262 argv++; 263 argc--; 264 } 265 return (errors); 266 } 267 268 static void usage() 269 { 270 (void) fprintf(stderr, gettext( 271 "Usage: mkfile [-nv] <size>[g|k|b|m] <name1> [<name2>] ...\n")); 272 exit(1); 273 /* NOTREACHED */ 274 } 275