1 1.11 andvar /* $NetBSD: newfs_ext2fs.c,v 1.11 2022/04/16 18:15:21 andvar Exp $ */ 2 1.1 tsutsui 3 1.1 tsutsui /* 4 1.1 tsutsui * Copyright (c) 1983, 1989, 1993, 1994 5 1.1 tsutsui * The Regents of the University of California. All rights reserved. 6 1.1 tsutsui * 7 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 8 1.1 tsutsui * modification, are permitted provided that the following conditions 9 1.1 tsutsui * are met: 10 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 11 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 12 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 14 1.1 tsutsui * documentation and/or other materials provided with the distribution. 15 1.1 tsutsui * 3. Neither the name of the University nor the names of its contributors 16 1.1 tsutsui * may be used to endorse or promote products derived from this software 17 1.1 tsutsui * without specific prior written permission. 18 1.1 tsutsui * 19 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 tsutsui * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 tsutsui * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 tsutsui * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 tsutsui * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 tsutsui * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 tsutsui * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 tsutsui * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 tsutsui * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 tsutsui * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 tsutsui * SUCH DAMAGE. 30 1.1 tsutsui */ 31 1.1 tsutsui 32 1.1 tsutsui #include <sys/cdefs.h> 33 1.1 tsutsui #ifndef lint 34 1.4 lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\ 35 1.4 lukem The Regents of the University of California. All rights reserved."); 36 1.1 tsutsui #endif /* not lint */ 37 1.1 tsutsui 38 1.1 tsutsui #ifndef lint 39 1.1 tsutsui #if 0 40 1.1 tsutsui static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95"; 41 1.1 tsutsui #else 42 1.11 andvar __RCSID("$NetBSD: newfs_ext2fs.c,v 1.11 2022/04/16 18:15:21 andvar Exp $"); 43 1.1 tsutsui #endif 44 1.1 tsutsui #endif /* not lint */ 45 1.1 tsutsui 46 1.1 tsutsui /* 47 1.1 tsutsui * newfs: friendly front end to mke2fs 48 1.1 tsutsui */ 49 1.1 tsutsui #include <sys/param.h> 50 1.1 tsutsui #include <sys/ioctl.h> 51 1.1 tsutsui #include <sys/disklabel.h> 52 1.1 tsutsui #include <sys/disk.h> 53 1.1 tsutsui #include <sys/file.h> 54 1.1 tsutsui #include <sys/mount.h> 55 1.1 tsutsui 56 1.1 tsutsui #include <ufs/ext2fs/ext2fs.h> 57 1.7 tsutsui #include <ufs/ext2fs/ext2fs_dinode.h> 58 1.1 tsutsui 59 1.1 tsutsui #include <disktab.h> 60 1.1 tsutsui #include <err.h> 61 1.1 tsutsui #include <errno.h> 62 1.1 tsutsui #include <limits.h> 63 1.1 tsutsui #include <paths.h> 64 1.1 tsutsui #include <stdio.h> 65 1.1 tsutsui #include <stdlib.h> 66 1.1 tsutsui #include <string.h> 67 1.1 tsutsui #include <unistd.h> 68 1.1 tsutsui #include <util.h> 69 1.1 tsutsui #include <mntopts.h> 70 1.1 tsutsui 71 1.1 tsutsui #include "extern.h" 72 1.1 tsutsui #include "partutil.h" 73 1.1 tsutsui 74 1.1 tsutsui static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *); 75 1.3 perry static void usage(void) __dead; 76 1.1 tsutsui 77 1.1 tsutsui /* 78 1.1 tsutsui * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults, 79 1.1 tsutsui * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use 80 1.1 tsutsui * L_DFL_*. 81 1.1 tsutsui */ 82 1.1 tsutsui #define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */ 83 1.1 tsutsui #define S_DFL_BSIZE 1024 84 1.1 tsutsui #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */ 85 1.1 tsutsui #define M_DFL_BSIZE 1024 86 1.1 tsutsui #define L_DFL_BSIZE 4096 87 1.1 tsutsui 88 1.1 tsutsui /* 89 1.1 tsutsui * Each file system has a number of inodes statically allocated. 90 1.1 tsutsui * We allocate one inode slot per 2, 4, or 8 blocks, expecting this 91 1.1 tsutsui * to be far more than we will ever need. 92 1.1 tsutsui */ 93 1.1 tsutsui #define S_DFL_NINODE(blocks) ((blocks) / 8) 94 1.1 tsutsui #define M_DFL_NINODE(blocks) ((blocks) / 4) 95 1.1 tsutsui #define L_DFL_NINODE(blocks) ((blocks) / 2) 96 1.1 tsutsui 97 1.1 tsutsui /* 98 1.1 tsutsui * Default sector size. 99 1.1 tsutsui */ 100 1.1 tsutsui #define DFL_SECSIZE 512 101 1.1 tsutsui 102 1.1 tsutsui int Nflag; /* run without writing file system */ 103 1.10 mrg int Oflag = 1; /* format as REV1 by default */ 104 1.1 tsutsui int verbosity; /* amount of printf() output */ 105 1.1 tsutsui #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior of newfs(8) */ 106 1.1 tsutsui int64_t fssize; /* file system size */ 107 1.1 tsutsui uint sectorsize; /* bytes/sector */ 108 1.7 tsutsui uint16_t inodesize = EXT2_REV0_DINODE_SIZE; /* inode size */ 109 1.1 tsutsui uint fsize = 0; /* fragment size */ 110 1.1 tsutsui uint bsize = 0; /* block size */ 111 1.1 tsutsui uint minfree = MINFREE; /* free space threshold */ 112 1.1 tsutsui uint density; /* number of bytes per inode */ 113 1.1 tsutsui uint num_inodes; /* number of inodes (overrides density) */ 114 1.1 tsutsui char *volname = NULL; /* volume name */ 115 1.1 tsutsui 116 1.1 tsutsui static char *disktype = NULL; 117 1.1 tsutsui static char device[MAXPATHLEN]; 118 1.1 tsutsui 119 1.1 tsutsui static const char lmsg[] = "%s: can't read disk label"; 120 1.1 tsutsui 121 1.1 tsutsui int 122 1.1 tsutsui main(int argc, char *argv[]) 123 1.1 tsutsui { 124 1.1 tsutsui struct disk_geom geo; 125 1.1 tsutsui struct dkwedge_info dkw; 126 1.1 tsutsui struct statvfs *mp; 127 1.1 tsutsui struct stat sb; 128 1.1 tsutsui int ch, fsi, fso, len, n, Fflag, Iflag, Zflag; 129 1.9 christos char *s1, *s2, *special; 130 1.1 tsutsui const char *opstring; 131 1.1 tsutsui int byte_sized; 132 1.1 tsutsui uint blocks; /* number of blocks */ 133 1.1 tsutsui 134 1.1 tsutsui fsi = fso = -1; 135 1.1 tsutsui Fflag = Iflag = Zflag = 0; 136 1.1 tsutsui verbosity = -1; 137 1.5 christos opstring = "D:FINO:S:V:Zb:f:i:l:m:n:s:v:"; 138 1.1 tsutsui byte_sized = 0; 139 1.1 tsutsui while ((ch = getopt(argc, argv, opstring)) != -1) 140 1.1 tsutsui switch (ch) { 141 1.5 christos case 'D': 142 1.5 christos inodesize = (uint16_t)strtol(optarg, &s1, 0); 143 1.8 tsutsui if (*s1 || (inodesize != 128 && inodesize != 256)) 144 1.5 christos errx(1, "Bad inode size %d " 145 1.5 christos "(only 128 and 256 supported)", inodesize); 146 1.5 christos break; 147 1.1 tsutsui case 'F': 148 1.1 tsutsui Fflag = 1; 149 1.1 tsutsui break; 150 1.1 tsutsui case 'I': 151 1.1 tsutsui Iflag = 1; 152 1.1 tsutsui break; 153 1.1 tsutsui case 'N': 154 1.1 tsutsui Nflag = 1; 155 1.1 tsutsui if (verbosity == -1) 156 1.1 tsutsui verbosity = DEFAULT_VERBOSITY; 157 1.1 tsutsui break; 158 1.1 tsutsui case 'O': 159 1.1 tsutsui Oflag = strsuftoi64("format", optarg, 0, 1, NULL); 160 1.1 tsutsui break; 161 1.1 tsutsui case 'S': 162 1.1 tsutsui /* 163 1.1 tsutsui * XXX: 164 1.1 tsutsui * non-512 byte sectors almost certainly don't work. 165 1.1 tsutsui */ 166 1.1 tsutsui sectorsize = strsuftoi64("sector size", 167 1.1 tsutsui optarg, 512, 65536, NULL); 168 1.1 tsutsui if (!powerof2(sectorsize)) 169 1.1 tsutsui errx(EXIT_FAILURE, 170 1.1 tsutsui "sector size `%s' is not a power of 2.", 171 1.1 tsutsui optarg); 172 1.1 tsutsui break; 173 1.1 tsutsui case 'V': 174 1.1 tsutsui verbosity = strsuftoi64("verbose", optarg, 0, 4, NULL); 175 1.1 tsutsui break; 176 1.1 tsutsui case 'Z': 177 1.1 tsutsui Zflag = 1; 178 1.1 tsutsui break; 179 1.1 tsutsui case 'b': 180 1.1 tsutsui bsize = strsuftoi64("block size", 181 1.2 tsutsui optarg, MINBSIZE, EXT2_MAXBSIZE, NULL); 182 1.1 tsutsui break; 183 1.1 tsutsui case 'f': 184 1.1 tsutsui fsize = strsuftoi64("fragment size", 185 1.2 tsutsui optarg, MINBSIZE, EXT2_MAXBSIZE, NULL); 186 1.1 tsutsui break; 187 1.1 tsutsui case 'i': 188 1.1 tsutsui density = strsuftoi64("bytes per inode", 189 1.1 tsutsui optarg, 1, INT_MAX, NULL); 190 1.1 tsutsui break; 191 1.1 tsutsui case 'm': 192 1.1 tsutsui minfree = strsuftoi64("free space %", 193 1.1 tsutsui optarg, 0, 99, NULL); 194 1.1 tsutsui break; 195 1.1 tsutsui case 'n': 196 1.1 tsutsui num_inodes = strsuftoi64("number of inodes", 197 1.1 tsutsui optarg, 1, INT_MAX, NULL); 198 1.1 tsutsui break; 199 1.1 tsutsui case 's': 200 1.1 tsutsui fssize = strsuftoi64("file system size", 201 1.1 tsutsui optarg, INT64_MIN, INT64_MAX, &byte_sized); 202 1.1 tsutsui break; 203 1.1 tsutsui case 'v': 204 1.1 tsutsui volname = optarg; 205 1.1 tsutsui if (volname[0] == '\0') 206 1.1 tsutsui errx(EXIT_FAILURE, 207 1.1 tsutsui "Volume name cannot be zero length"); 208 1.1 tsutsui break; 209 1.1 tsutsui case '?': 210 1.1 tsutsui default: 211 1.1 tsutsui usage(); 212 1.1 tsutsui } 213 1.1 tsutsui argc -= optind; 214 1.1 tsutsui argv += optind; 215 1.1 tsutsui 216 1.1 tsutsui if (verbosity == -1) 217 1.1 tsutsui /* Default to showing cg info */ 218 1.1 tsutsui verbosity = DEFAULT_VERBOSITY; 219 1.1 tsutsui 220 1.1 tsutsui if (argc != 1) 221 1.1 tsutsui usage(); 222 1.1 tsutsui 223 1.1 tsutsui memset(&sb, 0, sizeof(sb)); 224 1.1 tsutsui memset(&dkw, 0, sizeof(dkw)); 225 1.1 tsutsui special = argv[0]; 226 1.1 tsutsui if (Fflag) { 227 1.1 tsutsui int fl; 228 1.1 tsutsui /* 229 1.1 tsutsui * It's a file system image 230 1.1 tsutsui * no label, use fixed default for sectorsize. 231 1.1 tsutsui */ 232 1.1 tsutsui if (sectorsize == 0) 233 1.1 tsutsui sectorsize = DFL_SECSIZE; 234 1.1 tsutsui 235 1.1 tsutsui /* creating image in a regular file */ 236 1.1 tsutsui if (Nflag) 237 1.1 tsutsui fl = O_RDONLY; 238 1.1 tsutsui else { 239 1.1 tsutsui if (fssize > 0) 240 1.1 tsutsui fl = O_RDWR | O_CREAT; 241 1.1 tsutsui else 242 1.1 tsutsui fl = O_RDWR; 243 1.1 tsutsui } 244 1.1 tsutsui fsi = open(special, fl, 0777); 245 1.1 tsutsui if (fsi == -1) 246 1.1 tsutsui err(EXIT_FAILURE, "can't open file %s", special); 247 1.1 tsutsui if (fstat(fsi, &sb) == -1) 248 1.1 tsutsui err(EXIT_FAILURE, "can't fstat opened %s", special); 249 1.1 tsutsui if (!Nflag) 250 1.1 tsutsui fso = fsi; 251 1.1 tsutsui } else { /* !Fflag */ 252 1.1 tsutsui fsi = opendisk(special, O_RDONLY, device, sizeof(device), 0); 253 1.1 tsutsui special = device; 254 1.1 tsutsui if (fsi < 0 || fstat(fsi, &sb) == -1) 255 1.1 tsutsui err(EXIT_FAILURE, "%s: open for read", special); 256 1.1 tsutsui 257 1.1 tsutsui if (!Nflag) { 258 1.1 tsutsui fso = open(special, O_WRONLY, 0); 259 1.1 tsutsui if (fso < 0) 260 1.1 tsutsui err(EXIT_FAILURE, 261 1.1 tsutsui "%s: open for write", special); 262 1.1 tsutsui 263 1.1 tsutsui /* Bail if target special is mounted */ 264 1.1 tsutsui n = getmntinfo(&mp, MNT_NOWAIT); 265 1.1 tsutsui if (n == 0) 266 1.1 tsutsui err(EXIT_FAILURE, "%s: getmntinfo", special); 267 1.1 tsutsui 268 1.1 tsutsui len = sizeof(_PATH_DEV) - 1; 269 1.1 tsutsui s1 = special; 270 1.1 tsutsui if (strncmp(_PATH_DEV, s1, len) == 0) 271 1.1 tsutsui s1 += len; 272 1.1 tsutsui 273 1.1 tsutsui while (--n >= 0) { 274 1.1 tsutsui s2 = mp->f_mntfromname; 275 1.1 tsutsui if (strncmp(_PATH_DEV, s2, len) == 0) { 276 1.1 tsutsui s2 += len - 1; 277 1.1 tsutsui *s2 = 'r'; 278 1.1 tsutsui } 279 1.1 tsutsui if (strcmp(s1, s2) == 0 || 280 1.1 tsutsui strcmp(s1, &s2[1]) == 0) 281 1.1 tsutsui errx(EXIT_FAILURE, 282 1.1 tsutsui "%s is mounted on %s", 283 1.1 tsutsui special, mp->f_mntonname); 284 1.1 tsutsui ++mp; 285 1.1 tsutsui } 286 1.1 tsutsui } 287 1.1 tsutsui 288 1.1 tsutsui if (getdiskinfo(special, fsi, disktype, &geo, &dkw) == -1) 289 1.1 tsutsui errx(EXIT_FAILURE, lmsg, special); 290 1.1 tsutsui 291 1.1 tsutsui if (sectorsize == 0) { 292 1.1 tsutsui sectorsize = geo.dg_secsize; 293 1.1 tsutsui if (sectorsize <= 0) 294 1.1 tsutsui errx(EXIT_FAILURE, "no default sector size"); 295 1.1 tsutsui } 296 1.1 tsutsui 297 1.1 tsutsui if (dkw.dkw_parent[0]) { 298 1.1 tsutsui if (dkw.dkw_size == 0) 299 1.1 tsutsui errx(EXIT_FAILURE, 300 1.1 tsutsui "%s partition is unavailable", special); 301 1.1 tsutsui 302 1.1 tsutsui if (!Iflag) { 303 1.1 tsutsui static const char m[] = 304 1.1 tsutsui "%s partition type is not `%s' (or use -I)"; 305 1.1 tsutsui if (strcmp(dkw.dkw_ptype, DKW_PTYPE_EXT2FS)) 306 1.1 tsutsui errx(EXIT_FAILURE, m, 307 1.1 tsutsui special, "Linux Ext2"); 308 1.1 tsutsui } 309 1.1 tsutsui } 310 1.1 tsutsui } 311 1.1 tsutsui 312 1.1 tsutsui if (byte_sized) 313 1.1 tsutsui fssize /= sectorsize; 314 1.1 tsutsui if (fssize <= 0) { 315 1.1 tsutsui if (sb.st_size != 0) 316 1.1 tsutsui fssize += sb.st_size / sectorsize; 317 1.1 tsutsui else 318 1.1 tsutsui fssize += dkw.dkw_size; 319 1.1 tsutsui if (fssize <= 0) 320 1.1 tsutsui errx(EXIT_FAILURE, 321 1.1 tsutsui "Unable to determine file system size"); 322 1.1 tsutsui } 323 1.1 tsutsui 324 1.1 tsutsui if (dkw.dkw_parent[0] && fssize > dkw.dkw_size) 325 1.1 tsutsui errx(EXIT_FAILURE, 326 1.1 tsutsui "size %" PRIu64 " exceeds maximum file system size on " 327 1.1 tsutsui "`%s' of %" PRIu64 " sectors", 328 1.1 tsutsui fssize, special, dkw.dkw_size); 329 1.1 tsutsui 330 1.1 tsutsui /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */ 331 1.1 tsutsui if (Fflag && fso != -1 332 1.1 tsutsui && ftruncate(fso, (off_t)fssize * sectorsize) == -1) 333 1.1 tsutsui err(1, "can't ftruncate %s to %" PRId64, special, fssize); 334 1.1 tsutsui 335 1.11 andvar if (Zflag && fso != -1) { /* pre-zero (and de-sparse) the file */ 336 1.1 tsutsui char *buf; 337 1.1 tsutsui int bufsize, i; 338 1.1 tsutsui off_t bufrem; 339 1.1 tsutsui struct statvfs sfs; 340 1.1 tsutsui 341 1.1 tsutsui if (fstatvfs(fso, &sfs) == -1) { 342 1.1 tsutsui warn("can't fstatvfs `%s'", special); 343 1.1 tsutsui bufsize = 8192; 344 1.1 tsutsui } else 345 1.1 tsutsui bufsize = sfs.f_iosize; 346 1.1 tsutsui 347 1.1 tsutsui if ((buf = calloc(1, bufsize)) == NULL) 348 1.1 tsutsui err(1, "can't malloc buffer of %d", 349 1.1 tsutsui bufsize); 350 1.1 tsutsui bufrem = fssize * sectorsize; 351 1.1 tsutsui if (verbosity > 0) 352 1.1 tsutsui printf("Creating file system image in `%s', " 353 1.1 tsutsui "size %" PRId64 " bytes, in %d byte chunks.\n", 354 1.1 tsutsui special, bufrem, bufsize); 355 1.1 tsutsui while (bufrem > 0) { 356 1.1 tsutsui i = write(fso, buf, MIN(bufsize, bufrem)); 357 1.1 tsutsui if (i == -1) 358 1.1 tsutsui err(1, "writing image"); 359 1.1 tsutsui bufrem -= i; 360 1.1 tsutsui } 361 1.1 tsutsui free(buf); 362 1.1 tsutsui } 363 1.1 tsutsui 364 1.1 tsutsui /* Sort out fragment and block sizes */ 365 1.1 tsutsui if (bsize == 0) { 366 1.1 tsutsui bsize = fsize; 367 1.1 tsutsui if (bsize == 0) { 368 1.1 tsutsui if (fssize < SMALL_FSSIZE) 369 1.1 tsutsui bsize = S_DFL_BSIZE; 370 1.1 tsutsui else if (fssize < MEDIUM_FSSIZE) 371 1.1 tsutsui bsize = M_DFL_BSIZE; 372 1.1 tsutsui else 373 1.1 tsutsui bsize = L_DFL_BSIZE; 374 1.1 tsutsui } 375 1.1 tsutsui } 376 1.1 tsutsui if (fsize == 0) 377 1.1 tsutsui fsize = bsize; 378 1.1 tsutsui 379 1.1 tsutsui blocks = fssize * sectorsize / bsize; 380 1.1 tsutsui 381 1.1 tsutsui if (num_inodes == 0) { 382 1.1 tsutsui if (density != 0) 383 1.1 tsutsui num_inodes = fssize / density; 384 1.1 tsutsui else { 385 1.1 tsutsui if (fssize < SMALL_FSSIZE) 386 1.1 tsutsui num_inodes = S_DFL_NINODE(blocks); 387 1.1 tsutsui else if (fssize < MEDIUM_FSSIZE) 388 1.1 tsutsui num_inodes = M_DFL_NINODE(blocks); 389 1.1 tsutsui else 390 1.1 tsutsui num_inodes = L_DFL_NINODE(blocks); 391 1.1 tsutsui } 392 1.1 tsutsui } 393 1.1 tsutsui mke2fs(special, fsi, fso); 394 1.1 tsutsui 395 1.1 tsutsui if (fsi != -1) 396 1.1 tsutsui close(fsi); 397 1.1 tsutsui if (fso != -1 && fso != fsi) 398 1.1 tsutsui close(fso); 399 1.1 tsutsui exit(EXIT_SUCCESS); 400 1.1 tsutsui } 401 1.1 tsutsui 402 1.1 tsutsui static int64_t 403 1.1 tsutsui strsuftoi64(const char *desc, const char *arg, int64_t min, int64_t max, 404 1.1 tsutsui int *num_suffix) 405 1.1 tsutsui { 406 1.1 tsutsui int64_t result, r1; 407 1.1 tsutsui int shift = 0; 408 1.1 tsutsui char *ep; 409 1.1 tsutsui 410 1.1 tsutsui errno = 0; 411 1.1 tsutsui r1 = strtoll(arg, &ep, 10); 412 1.1 tsutsui if (ep[0] != '\0' && ep[1] != '\0') 413 1.1 tsutsui errx(EXIT_FAILURE, 414 1.1 tsutsui "%s `%s' is not a valid number.", desc, arg); 415 1.1 tsutsui switch (ep[0]) { 416 1.1 tsutsui case '\0': 417 1.1 tsutsui case 's': 418 1.1 tsutsui case 'S': 419 1.1 tsutsui if (num_suffix != NULL) 420 1.1 tsutsui *num_suffix = 0; 421 1.1 tsutsui break; 422 1.1 tsutsui case 'g': 423 1.1 tsutsui case 'G': 424 1.1 tsutsui shift += 10; 425 1.1 tsutsui /* FALLTHROUGH */ 426 1.1 tsutsui case 'm': 427 1.1 tsutsui case 'M': 428 1.1 tsutsui shift += 10; 429 1.1 tsutsui /* FALLTHROUGH */ 430 1.1 tsutsui case 'k': 431 1.1 tsutsui case 'K': 432 1.1 tsutsui shift += 10; 433 1.1 tsutsui /* FALLTHROUGH */ 434 1.1 tsutsui case 'b': 435 1.1 tsutsui case 'B': 436 1.1 tsutsui if (num_suffix != NULL) 437 1.1 tsutsui *num_suffix = 1; 438 1.1 tsutsui break; 439 1.1 tsutsui default: 440 1.1 tsutsui errx(EXIT_FAILURE, 441 1.1 tsutsui "`%s' is not a valid suffix for %s.", ep, desc); 442 1.1 tsutsui } 443 1.1 tsutsui result = r1 << shift; 444 1.1 tsutsui if (errno == ERANGE || result >> shift != r1) 445 1.1 tsutsui errx(EXIT_FAILURE, 446 1.1 tsutsui "%s `%s' is too large to convert.", desc, arg); 447 1.1 tsutsui if (result < min) 448 1.1 tsutsui errx(EXIT_FAILURE, 449 1.1 tsutsui "%s `%s' (%" PRId64 ") is less than the minimum (%" 450 1.1 tsutsui PRId64 ").", desc, arg, result, min); 451 1.1 tsutsui if (result > max) 452 1.1 tsutsui errx(EXIT_FAILURE, 453 1.1 tsutsui "%s `%s' (%" PRId64 ") is greater than the maximum (%" 454 1.1 tsutsui PRId64 ").", desc, arg, result, max); 455 1.1 tsutsui return result; 456 1.1 tsutsui } 457 1.1 tsutsui 458 1.1 tsutsui static const char help_strings[] = 459 1.6 wiz "\t-b bsize\tblock size\n" 460 1.5 christos "\t-D inodesize\tsize of an inode in bytes (128 or 256)\n" 461 1.1 tsutsui "\t-F \t\tcreate file system image in regular file\n" 462 1.6 wiz "\t-f fsize\tfragment size\n" 463 1.1 tsutsui "\t-I \t\tdo not check that the file system type is `Linux Ext2'\n" 464 1.6 wiz "\t-i density\tnumber of bytes per inode\n" 465 1.6 wiz "\t-m minfree\tminimum free space %\n" 466 1.1 tsutsui "\t-N \t\tdo not create file system, just print out parameters\n" 467 1.6 wiz "\t-n inodes\tnumber of inodes (overrides -i density)\n" 468 1.1 tsutsui "\t-O N\t\tfilesystem revision: 0 ==> REV0, 1 ==> REV1 (default 0)\n" 469 1.1 tsutsui "\t-S secsize\tsector size\n" 470 1.6 wiz "\t-s fssize\tfile system size (sectors)\n" 471 1.1 tsutsui "\t-V verbose\toutput verbosity: 0 ==> none, 4 ==> max\n" 472 1.6 wiz "\t-v volname\text2fs volume name\n" 473 1.6 wiz "\t-Z \t\tpre-zero the image file\n"; 474 1.1 tsutsui 475 1.1 tsutsui static void 476 1.1 tsutsui usage(void) 477 1.1 tsutsui { 478 1.1 tsutsui 479 1.1 tsutsui fprintf(stderr, 480 1.1 tsutsui "usage: %s [ fsoptions ] special-device\n", getprogname()); 481 1.1 tsutsui fprintf(stderr, "where fsoptions are:\n"); 482 1.1 tsutsui fprintf(stderr, "%s", help_strings); 483 1.1 tsutsui 484 1.1 tsutsui exit(EXIT_FAILURE); 485 1.1 tsutsui } 486