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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 #pragma ident "%Z%%M% %I% %E% SMI" 23 /* from UCB 5.2 9/11/85 */ 24 25 /* 26 * newfs: friendly front end to mkfs 27 * 28 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 29 * Use is subject to license terms. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <locale.h> 35 #include <sys/stat.h> 36 #include <sys/buf.h> 37 #include <sys/fs/ufs_fs.h> 38 #include <sys/vnode.h> 39 #include <sys/fs/ufs_inode.h> 40 #include <sys/sysmacros.h> 41 42 #include <errno.h> 43 #include <stdio.h> 44 #include <string.h> 45 #include <stdlib.h> 46 #include <stdarg.h> 47 #include <stdio.h> 48 #include <fcntl.h> 49 #include <unistd.h> 50 #include <limits.h> 51 #include <libintl.h> 52 #include <sys/dkio.h> 53 #include <sys/vtoc.h> 54 #include <sys/mkdev.h> 55 #include <sys/efi_partition.h> 56 57 #include <fslib.h> 58 59 static unsigned int number(char *, char *, int, int); 60 static int64_t number64(char *, char *, int, int64_t); 61 static diskaddr_t getdiskbydev(char *); 62 static int yes(void); 63 static int notrand(char *); 64 static void usage(); 65 static diskaddr_t get_device_size(int, char *); 66 static diskaddr_t brute_force_get_device_size(int); 67 static int validate_size(char *disk, diskaddr_t size); 68 static void exenv(void); 69 static struct fs *read_sb(char *); 70 /*PRINTFLIKE1*/ 71 static void fatal(char *fmt, ...); 72 73 #define EPATH "PATH=/usr/sbin:/sbin:" 74 #define CPATH "/sbin" /* an EPATH element */ 75 #define MB (1024 * 1024) 76 #define GBSEC ((1024 * 1024 * 1024) / DEV_BSIZE) /* sectors in a GB */ 77 #define MINFREESEC ((64 * 1024 * 1024) / DEV_BSIZE) /* sectors in 64 MB */ 78 #define MINCPG (16) /* traditional */ 79 #define MAXDEFDENSITY (8 * 1024) /* arbitrary */ 80 #define MINDENSITY (2 * 1024) /* traditional */ 81 #define MIN_MTB_DENSITY (1024 * 1024) 82 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 83 #define SECTORS_PER_TERABYTE (1LL << 31) 84 /* 85 * The following constant specifies an upper limit for file system size 86 * that is actually a lot bigger than we expect to support with UFS. (Since 87 * it's specified in sectors, the file system size would be 2**44 * 512, 88 * which is 2**53, which is 8192 Terabytes.) However, it's useful 89 * for checking the basic sanity of a size value that is input on the 90 * command line. 91 */ 92 #define FS_SIZE_UPPER_LIMIT 0x100000000000LL 93 94 /* For use with number() */ 95 #define NR_NONE 0 96 #define NR_PERCENT 0x01 97 98 /* 99 * The following two constants set the default block and fragment sizes. 100 * Both constants must be a power of 2 and meet the following constraints: 101 * MINBSIZE <= DESBLKSIZE <= MAXBSIZE 102 * DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE 103 * DESBLKSIZE / DESFRAGSIZE <= 8 104 */ 105 #define DESBLKSIZE 8192 106 #define DESFRAGSIZE 1024 107 108 #ifdef DEBUG 109 #define dprintf(x) printf x 110 #else 111 #define dprintf(x) 112 #endif 113 114 static int Nflag; /* run mkfs without writing file system */ 115 static int Tflag; /* set up file system for growth to over 1 TB */ 116 static int verbose; /* show mkfs line before exec */ 117 static int fsize = 0; /* fragment size */ 118 static int fsize_flag = 0; /* fragment size was specified on cmd line */ 119 static int bsize; /* block size */ 120 static int ntracks; /* # tracks/cylinder */ 121 static int ntracks_set = 0; /* true if the user specified ntracks */ 122 static int optim = FS_OPTTIME; /* optimization, t(ime) or s(pace) */ 123 static int nsectors; /* # sectors/track */ 124 static int cpg; /* cylinders/cylinder group */ 125 static int cpg_set = 0; /* true if the user specified cpg */ 126 static int minfree = -1; /* free space threshold */ 127 static int rpm; /* revolutions/minute of drive */ 128 static int rpm_set = 0; /* true if the user specified rpm */ 129 static int nrpos = 8; /* # of distinguished rotational positions */ 130 /* 8 is the historical default */ 131 static int nrpos_set = 0; /* true if the user specified nrpos */ 132 static int density = 0; /* number of bytes per inode */ 133 static int apc; /* alternates per cylinder */ 134 static int apc_set = 0; /* true if the user specified apc */ 135 static int rot = -1; /* rotational delay (msecs) */ 136 static int rot_set = 0; /* true if the user specified rot */ 137 static int maxcontig = -1; /* maximum number of contig blocks */ 138 static int text_sb = 0; /* no disk changes; just final sb text dump */ 139 static int binary_sb = 0; /* no disk changes; just final sb binary dump */ 140 static int label_type; /* see types below */ 141 142 /* 143 * The variable use_efi_dflts is an indicator of whether to use EFI logic 144 * or the geometry logic in laying out the filesystem. This is decided 145 * based on the size/type of the disk and is used only for non-EFI labeled 146 * disks and removable media. 147 */ 148 static int use_efi_dflts = 0; 149 static int isremovable = 0; 150 151 static char device[MAXPATHLEN]; 152 static char cmd[BUFSIZ]; 153 154 extern char *getfullrawname(); /* from libadm */ 155 156 int 157 main(int argc, char *argv[]) 158 { 159 char *special, *name; 160 struct stat64 st; 161 int status; 162 int option; 163 struct fs *sbp; /* Pointer to superblock (if present) */ 164 diskaddr_t actual_fssize; 165 diskaddr_t max_possible_fssize; 166 diskaddr_t req_fssize = 0; 167 diskaddr_t fssize = 0; 168 char *req_fssize_str = NULL; /* requested size argument */ 169 170 (void) setlocale(LC_ALL, ""); 171 172 #if !defined(TEXT_DOMAIN) 173 #define TEXT_DOMAIN "SYS_TEST" 174 #endif 175 (void) textdomain(TEXT_DOMAIN); 176 177 opterr = 0; /* We print our own errors, disable getopt's message */ 178 while ((option = getopt(argc, argv, 179 "vNBSs:C:d:t:o:a:b:f:c:m:n:r:i:T")) != EOF) { 180 switch (option) { 181 case 'S': 182 text_sb++; 183 break; 184 case 'B': 185 binary_sb++; 186 break; 187 case 'v': 188 verbose++; 189 break; 190 191 case 'N': 192 Nflag++; 193 break; 194 195 case 's': 196 /* 197 * The maximum file system size is a lot smaller 198 * than FS_SIZE_UPPER_LIMIT, but until we find out 199 * the device size and block size, we don't know 200 * what it is. So save the requested size in a 201 * string so that we can print it out later if we 202 * determine it's too big. 203 */ 204 req_fssize = number64("fssize", optarg, NR_NONE, 205 FS_SIZE_UPPER_LIMIT); 206 if (req_fssize < 1024) 207 fatal(gettext( 208 "%s: fssize must be at least 1024"), 209 optarg); 210 req_fssize_str = strdup(optarg); 211 if (req_fssize_str == NULL) 212 fatal(gettext( 213 "Insufficient memory for string copy.")); 214 break; 215 216 case 'C': 217 maxcontig = number("maxcontig", optarg, NR_NONE, -1); 218 if (maxcontig < 0) 219 fatal(gettext("%s: bad maxcontig"), optarg); 220 break; 221 222 case 'd': 223 rot = number("rotdelay", optarg, NR_NONE, 0); 224 rot_set = 1; 225 if (rot < 0 || rot > 1000) 226 fatal(gettext( 227 "%s: bad rotational delay"), optarg); 228 break; 229 230 case 't': 231 ntracks = number("ntrack", optarg, NR_NONE, 16); 232 ntracks_set = 1; 233 if ((ntracks < 0) || 234 (ntracks > INT_MAX)) 235 fatal(gettext("%s: bad total tracks"), optarg); 236 break; 237 238 case 'o': 239 if (strcmp(optarg, "space") == 0) 240 optim = FS_OPTSPACE; 241 else if (strcmp(optarg, "time") == 0) 242 optim = FS_OPTTIME; 243 else 244 fatal(gettext( 245 "%s: bad optimization preference (options are `space' or `time')"), optarg); 246 break; 247 248 case 'a': 249 apc = number("apc", optarg, NR_NONE, 0); 250 apc_set = 1; 251 if (apc < 0 || apc > 32768) /* see mkfs.c */ 252 fatal(gettext( 253 "%s: bad alternates per cyl"), optarg); 254 break; 255 256 case 'b': 257 bsize = number("bsize", optarg, NR_NONE, DESBLKSIZE); 258 if (bsize < MINBSIZE || bsize > MAXBSIZE) 259 fatal(gettext( 260 "%s: bad block size"), optarg); 261 break; 262 263 case 'f': 264 fsize = number("fragsize", optarg, NR_NONE, 265 DESFRAGSIZE); 266 fsize_flag++; 267 /* xxx ought to test against bsize for upper limit */ 268 if (fsize < DEV_BSIZE) 269 fatal(gettext("%s: bad frag size"), optarg); 270 break; 271 272 case 'c': 273 cpg = number("cpg", optarg, NR_NONE, 16); 274 cpg_set = 1; 275 if (cpg < 1) 276 fatal(gettext("%s: bad cylinders/group"), 277 optarg); 278 break; 279 280 case 'm': 281 minfree = number("minfree", optarg, NR_PERCENT, 10); 282 if (minfree < 0 || minfree > 99) 283 fatal(gettext("%s: bad free space %%"), optarg); 284 break; 285 286 case 'n': 287 nrpos = number("nrpos", optarg, NR_NONE, 8); 288 nrpos_set = 1; 289 if (nrpos <= 0) 290 fatal(gettext( 291 "%s: bad number of rotational positions"), 292 optarg); 293 break; 294 295 case 'r': 296 rpm = number("rpm", optarg, NR_NONE, 3600); 297 rpm_set = 1; 298 if (rpm < 0) 299 fatal(gettext("%s: bad revs/minute"), optarg); 300 break; 301 302 case 'i': 303 /* xxx ought to test against fsize */ 304 density = number("nbpi", optarg, NR_NONE, 2048); 305 if (density < DEV_BSIZE) 306 fatal(gettext("%s: bad bytes per inode"), 307 optarg); 308 break; 309 310 case 'T': 311 Tflag++; 312 break; 313 314 default: 315 usage(); 316 fatal(gettext("-%c: unknown flag"), optopt); 317 } 318 } 319 320 /* At this point, there should only be one argument left: */ 321 /* The raw-special-device itself. If not, print usage message. */ 322 if ((argc - optind) != 1) { 323 usage(); 324 exit(1); 325 } 326 327 name = argv[optind]; 328 329 special = getfullrawname(name); 330 if (special == NULL) { 331 (void) fprintf(stderr, gettext("newfs: malloc failed\n")); 332 exit(1); 333 } 334 335 if (*special == '\0') { 336 if (strchr(name, '/') != NULL) { 337 if (stat64(name, &st) < 0) { 338 (void) fprintf(stderr, 339 gettext("newfs: %s: %s\n"), 340 name, strerror(errno)); 341 exit(2); 342 } 343 fatal(gettext("%s: not a raw disk device"), name); 344 } 345 (void) sprintf(device, "/dev/rdsk/%s", name); 346 if ((special = getfullrawname(device)) == NULL) { 347 (void) fprintf(stderr, 348 gettext("newfs: malloc failed\n")); 349 exit(1); 350 } 351 352 if (*special == '\0') { 353 (void) sprintf(device, "/dev/%s", name); 354 if ((special = getfullrawname(device)) == NULL) { 355 (void) fprintf(stderr, 356 gettext("newfs: malloc failed\n")); 357 exit(1); 358 } 359 if (*special == '\0') 360 fatal(gettext( 361 "%s: not a raw disk device"), name); 362 } 363 } 364 365 /* 366 * getdiskbydev() determines the characteristics of the special 367 * device on which the file system will be built. In the case 368 * of devices with SMI labels (that is, non-EFI labels), the 369 * following characteristics are set (if they were not already 370 * set on the command line, since the command line settings 371 * take precedence): 372 * 373 * nsectors - sectors per track 374 * ntracks - tracks per cylinder 375 * rpm - disk revolutions per minute 376 * 377 * apc is NOT set 378 * 379 * getdiskbydev() also sets the following quantities for all 380 * devices, if not already set: 381 * 382 * bsize - file system block size 383 * maxcontig 384 * label_type (efi, vtoc, or other) 385 * 386 * getdiskbydev() returns the actual size of the device, in 387 * sectors. 388 */ 389 390 actual_fssize = getdiskbydev(special); 391 392 if (req_fssize == 0) { 393 fssize = actual_fssize; 394 } else { 395 /* 396 * If the user specified a size larger than what we've 397 * determined as the actual size of the device, see if the 398 * size specified by the user can be read. If so, use it, 399 * since some devices and volume managers may not support 400 * the vtoc and EFI interfaces we use to determine device 401 * size. 402 */ 403 if (req_fssize > actual_fssize && 404 validate_size(special, req_fssize)) { 405 (void) fprintf(stderr, gettext( 406 "Warning: the requested size of this file system\n" 407 "(%lld sectors) is greater than the size of the\n" 408 "device reported by the driver (%lld sectors).\n" 409 "However, a read of the device at the requested size\n" 410 "does succeed, so the requested size will be used.\n"), 411 req_fssize, actual_fssize); 412 fssize = req_fssize; 413 } else { 414 fssize = MIN(req_fssize, actual_fssize); 415 } 416 } 417 418 if (label_type == LABEL_TYPE_VTOC) { 419 if (nsectors < 0) 420 fatal(gettext("%s: no default #sectors/track"), 421 special); 422 if (!use_efi_dflts) { 423 if (ntracks < 0) 424 fatal(gettext("%s: no default #tracks"), 425 special); 426 } 427 if (rpm < 0) 428 fatal(gettext( 429 "%s: no default revolutions/minute value"), 430 special); 431 if (rpm < 60) { 432 (void) fprintf(stderr, 433 gettext("Warning: setting rpm to 60\n")); 434 rpm = 60; 435 } 436 } 437 if (label_type == LABEL_TYPE_EFI || label_type == LABEL_TYPE_OTHER) { 438 if (ntracks_set) 439 (void) fprintf(stderr, gettext( 440 "Warning: ntracks is obsolete for this device and will be ignored.\n")); 441 if (cpg_set) 442 (void) fprintf(stderr, gettext( 443 "Warning: cylinders/group is obsolete for this device and will be ignored.\n")); 444 if (rpm_set) 445 (void) fprintf(stderr, gettext( 446 "Warning: rpm is obsolete for this device and will be ignored.\n")); 447 if (rot_set) 448 (void) fprintf(stderr, gettext( 449 "Warning: rotational delay is obsolete for this device and" 450 " will be ignored.\n")); 451 if (nrpos_set) 452 (void) fprintf(stderr, gettext( 453 "Warning: number of rotational positions is obsolete for this device and\n" 454 "will be ignored.\n")); 455 if (apc_set) 456 (void) fprintf(stderr, gettext( 457 "Warning: number of alternate sectors per cylinder is obsolete for this\n" 458 "device and will be ignored.\n")); 459 460 /* 461 * We need these for the call to mkfs, even though they are 462 * meaningless. 463 */ 464 rpm = 60; 465 nrpos = 1; 466 apc = 0; 467 rot = -1; 468 469 /* 470 * These values are set to produce a file system with 471 * a cylinder group size of 48MB. For disks with 472 * non-EFI labels, most geometries result in cylinder 473 * groups of around 40 - 50 MB, so we arbitrarily choose 474 * 48MB for disks with EFI labels. mkfs will reduce 475 * cylinders per group even further if necessary. 476 */ 477 478 cpg = 16; 479 nsectors = 128; 480 ntracks = 48; 481 482 /* 483 * mkfs produces peculiar results for file systems 484 * that are smaller than one cylinder so don't allow 485 * them to be created (this check is only made for 486 * disks with EFI labels. Eventually, it should probably 487 * be enforced for all disks.) 488 */ 489 490 if (fssize < nsectors * ntracks) { 491 fatal(gettext( 492 "file system size must be at least %d sectors"), 493 nsectors * ntracks); 494 } 495 } 496 497 if (fssize > INT_MAX) 498 Tflag = 1; 499 500 /* 501 * If the user requested that the file system be set up for 502 * eventual growth to over a terabyte, or if it's already greater 503 * than a terabyte, set the inode density (nbpi) to MIN_MTB_DENSITY 504 * (unless the user has specified a larger nbpi), set the frag size 505 * equal to the block size, and set the cylinders-per-group value 506 * passed to mkfs to -1, which tells mkfs to make cylinder groups 507 * as large as possible. 508 */ 509 if (Tflag) { 510 if (density < MIN_MTB_DENSITY) 511 density = MIN_MTB_DENSITY; 512 fsize = bsize; 513 cpg = -1; /* says make cyl groups as big as possible */ 514 } else { 515 if (fsize == 0) 516 fsize = DESFRAGSIZE; 517 } 518 519 if (!POWEROF2(fsize)) { 520 (void) fprintf(stderr, gettext( 521 "newfs: fragment size must a power of 2, not %d\n"), fsize); 522 fsize = bsize/8; 523 (void) fprintf(stderr, gettext( 524 "newfs: fragsize reset to %ld\n"), fsize); 525 } 526 527 /* 528 * The file system is limited in size by the fragment size. 529 * The number of fragments in the file system must fit into 530 * a signed 32-bit quantity, so the number of sectors in the 531 * file system is INT_MAX * the number of sectors in a frag. 532 */ 533 534 max_possible_fssize = ((uint64_t)fsize)/DEV_BSIZE * INT_MAX; 535 if (fssize > max_possible_fssize) 536 fssize = max_possible_fssize; 537 538 /* 539 * Now fssize is the final size of the file system (in sectors). 540 * If it's less than what the user requested, print a message. 541 */ 542 if (fssize < req_fssize) { 543 (void) fprintf(stderr, gettext( 544 "newfs: requested size of %s disk blocks is too large.\n"), 545 req_fssize_str); 546 (void) fprintf(stderr, gettext( 547 "newfs: Resetting size to %lld\n"), fssize); 548 } 549 550 /* 551 * fssize now equals the size (in sectors) of the file system 552 * that will be created. 553 */ 554 555 /* XXX - following defaults are both here and in mkfs */ 556 if (density <= 0) { 557 if (fssize < GBSEC) 558 density = MINDENSITY; 559 else 560 density = (int)((((longlong_t)fssize + (GBSEC - 1)) / 561 GBSEC) * MINDENSITY); 562 if (density <= 0) 563 density = MINDENSITY; 564 if (density > MAXDEFDENSITY) 565 density = MAXDEFDENSITY; 566 } 567 if (cpg == 0) { 568 /* 569 * maxcpg calculation adapted from mkfs 570 * In the case of disks with EFI labels, cpg has 571 * already been set, so we won't enter this code. 572 */ 573 long maxcpg, maxipg; 574 575 maxipg = roundup(bsize * NBBY / 3, 576 bsize / sizeof (struct inode)); 577 maxcpg = (bsize - sizeof (struct cg) - howmany(maxipg, NBBY)) / 578 (sizeof (long) + nrpos * sizeof (short) + 579 nsectors / (MAXFRAG * NBBY)); 580 cpg = (fssize / GBSEC) * 32; 581 if (cpg > maxcpg) 582 cpg = maxcpg; 583 if (cpg <= 0) 584 cpg = MINCPG; 585 } 586 if (minfree < 0) { 587 minfree = ((float)MINFREESEC / fssize) * 100; 588 if (minfree > 10) 589 minfree = 10; 590 if (minfree <= 0) 591 minfree = 1; 592 } 593 #ifdef i386 /* Bug 1170182 */ 594 if (ntracks > 32 && (ntracks % 16) != 0) { 595 ntracks -= (ntracks % 16); 596 } 597 #endif 598 /* 599 * Confirmation 600 */ 601 if (isatty(fileno(stdin)) && !Nflag) { 602 /* 603 * If we can read a valid superblock, report the mount 604 * point on which this filesystem was last mounted. 605 */ 606 if (((sbp = read_sb(special)) != 0) && 607 (*sbp->fs_fsmnt != '\0')) { 608 (void) printf(gettext( 609 "newfs: %s last mounted as %s\n"), 610 special, sbp->fs_fsmnt); 611 } 612 (void) printf(gettext( 613 "newfs: construct a new file system %s: (y/n)? "), 614 special); 615 (void) fflush(stdout); 616 if (!yes()) 617 exit(0); 618 } 619 /* 620 * Geometry information does not make sense for removable media 621 * anyway, so indicate mkfs to use the default parameters by passing -1. 622 */ 623 if (!Tflag && isremovable) 624 ntracks = -1; 625 dprintf(("DeBuG newfs : nsect=%d ntrak=%d cpg=%d\n", 626 nsectors, ntracks, cpg)); 627 /* 628 * If alternates-per-cylinder is ever implemented: 629 * need to get apc from dp->d_apc if no -a switch??? 630 */ 631 (void) sprintf(cmd, 632 "mkfs -F ufs %s%s%s%s %lld %d %d %d %d %d %d %d %d %s %d %d %d %d %s", 633 Nflag ? "-o N " : "", binary_sb ? "-o calcbinsb " : "", 634 text_sb ? "-o calcsb " : "", special, 635 fssize, nsectors, ntracks, bsize, fsize, cpg, minfree, rpm/60, 636 density, optim == FS_OPTSPACE ? "s" : "t", apc, rot, nrpos, 637 maxcontig, Tflag ? "y" : "n"); 638 if (verbose) { 639 (void) printf("%s\n", cmd); 640 (void) fflush(stdout); 641 } 642 exenv(); 643 if (status = system(cmd)) 644 exit(status >> 8); 645 if (Nflag) 646 exit(0); 647 (void) sprintf(cmd, "/usr/sbin/fsirand %s", special); 648 if (notrand(special) && (status = system(cmd)) != 0) 649 (void) fprintf(stderr, 650 gettext("%s: failed, status = %d\n"), 651 cmd, status); 652 return (0); 653 } 654 655 static void 656 exenv(void) 657 { 658 char *epath; /* executable file path */ 659 char *cpath; /* current path */ 660 661 if ((cpath = getenv("PATH")) == NULL) { 662 (void) fprintf(stderr, gettext("newfs: no PATH in env\n")); 663 /* 664 * Background: the Bourne shell interpolates "." into 665 * the path where said path starts with a colon, ends 666 * with a colon, or has two adjacent colons. Thus, 667 * the path ":/sbin::/usr/sbin:" is equivalent to 668 * ".:/sbin:.:/usr/sbin:.". Now, we have no cpath, 669 * and epath ends in a colon (to make for easy 670 * catenation in the normal case). By the above, if 671 * we use "", then "." becomes part of path. That's 672 * bad, so use CPATH (which is just a duplicate of some 673 * element in EPATH). No point in opening ourselves 674 * up to a Trojan horse attack when we don't have to.... 675 */ 676 cpath = CPATH; 677 } 678 if ((epath = malloc(strlen(EPATH) + strlen(cpath) + 1)) == NULL) { 679 (void) fprintf(stderr, gettext("newfs: malloc failed\n")); 680 exit(1); 681 } 682 (void) strcpy(epath, EPATH); 683 (void) strcat(epath, cpath); 684 if (putenv(epath) < 0) { 685 (void) fprintf(stderr, gettext("newfs: putenv failed\n")); 686 exit(1); 687 } 688 } 689 690 static int 691 yes(void) 692 { 693 int i, b; 694 695 i = b = getchar(); 696 while (b != '\n' && b != '\0' && b != EOF) 697 b = getchar(); 698 return (i == 'y'); 699 } 700 701 /* 702 * xxx Caller must run fmt through gettext(3) for us, if we ever 703 * xxx go the i18n route.... 704 */ 705 static void 706 fatal(char *fmt, ...) 707 { 708 va_list pvar; 709 710 (void) fprintf(stderr, "newfs: "); 711 va_start(pvar, fmt); 712 (void) vfprintf(stderr, fmt, pvar); 713 va_end(pvar); 714 (void) putc('\n', stderr); 715 exit(10); 716 } 717 718 static diskaddr_t 719 getdiskbydev(char *disk) 720 { 721 struct dk_geom g; 722 struct dk_cinfo ci; 723 diskaddr_t actual_size; 724 int fd; 725 726 if ((fd = open64(disk, 0)) < 0) { 727 perror(disk); 728 exit(1); 729 } 730 731 /* 732 * get_device_size() determines the actual size of the 733 * device, and also the disk's attributes, such as geometry. 734 */ 735 actual_size = get_device_size(fd, disk); 736 737 if (ioctl(fd, DKIOCREMOVABLE, &isremovable)) { 738 (void) fprintf(stderr, gettext( 739 "%s: Unable to find Media type. Proceeding with " 740 "system determined parameters.\n"), disk); 741 isremovable = 0; 742 } 743 744 if (label_type == LABEL_TYPE_VTOC) { 745 if (ioctl(fd, DKIOCGGEOM, &g)) 746 fatal(gettext( 747 "%s: Unable to read Disk geometry"), disk); 748 dprintf(("DeBuG newfs : geom=%ld, CHSLIMIT=%d\n", 749 g.dkg_ncyl * g.dkg_nhead * g.dkg_nsect, CHSLIMIT)); 750 if (((g.dkg_ncyl * g.dkg_nhead * g.dkg_nsect) > CHSLIMIT) && 751 !Tflag) { 752 dprintf(("DeBuG newfs : geom > CHSLIMIT\n")); 753 use_efi_dflts = 1; 754 } 755 /* 756 * The ntracks that is passed to mkfs is decided here based 757 * on 'use_efi_dflts' and whether ntracks was specified as a 758 * command line parameter to newfs. 759 * If ntracks of -1 is passed to mkfs, mkfs uses DEF_TRACKS_EFI 760 * and DEF_SECTORS_EFI for ntracks and nsectors respectively. 761 */ 762 if (nsectors == 0) 763 nsectors = g.dkg_nsect; 764 if (ntracks == 0) 765 ntracks = use_efi_dflts ? -1 : g.dkg_nhead; 766 if (rpm == 0) 767 rpm = ((int)g.dkg_rpm <= 0) ? 3600: g.dkg_rpm; 768 } 769 770 if (bsize == 0) 771 bsize = DESBLKSIZE; 772 /* 773 * Adjust maxcontig by the device's maxtransfer. If maxtransfer 774 * information is not available, default to the min of a MB and 775 * maxphys. 776 */ 777 if (maxcontig == -1 && ioctl(fd, DKIOCINFO, &ci) == 0) { 778 maxcontig = ci.dki_maxtransfer * DEV_BSIZE; 779 if (maxcontig < 0) { 780 int error, gotit, maxphys; 781 gotit = fsgetmaxphys(&maxphys, &error); 782 783 /* 784 * If we cannot get the maxphys value, default 785 * to ufs_maxmaxphys (MB). 786 */ 787 if (gotit) { 788 maxcontig = MIN(maxphys, MB); 789 } else { 790 (void) fprintf(stderr, gettext( 791 "Warning: Could not get system value for maxphys. The value for maxcontig\n" 792 "will default to 1MB.\n")); 793 maxcontig = MB; 794 } 795 } 796 maxcontig /= bsize; 797 } 798 (void) close(fd); 799 return (actual_size); 800 } 801 802 /* 803 * Figure out how big the partition we're dealing with is. 804 */ 805 static diskaddr_t 806 get_device_size(int fd, char *name) 807 { 808 struct vtoc vtoc; 809 dk_gpt_t *efi_vtoc; 810 diskaddr_t slicesize; 811 812 int index = read_vtoc(fd, &vtoc); 813 814 if (index >= 0) { 815 label_type = LABEL_TYPE_VTOC; 816 } else { 817 if (index == VT_ENOTSUP || index == VT_ERROR) { 818 /* it might be an EFI label */ 819 index = efi_alloc_and_read(fd, &efi_vtoc); 820 if (index >= 0) 821 label_type = LABEL_TYPE_EFI; 822 } 823 } 824 825 if (index < 0) { 826 /* 827 * Since both attempts to read the label failed, we're 828 * going to fall back to a brute force approach to 829 * determining the device's size: see how far out we can 830 * perform reads on the device. 831 */ 832 833 slicesize = brute_force_get_device_size(fd); 834 if (slicesize == 0) { 835 switch (index) { 836 case VT_ERROR: 837 (void) fprintf(stderr, gettext( 838 "newfs: %s: %s\n"), name, strerror(errno)); 839 exit(10); 840 /*NOTREACHED*/ 841 case VT_EIO: 842 fatal(gettext( 843 "%s: I/O error accessing VTOC"), name); 844 /*NOTREACHED*/ 845 case VT_EINVAL: 846 fatal(gettext( 847 "%s: Invalid field in VTOC"), name); 848 /*NOTREACHED*/ 849 default: 850 fatal(gettext( 851 "%s: unknown error accessing VTOC"), 852 name); 853 /*NOTREACHED*/ 854 } 855 } else { 856 label_type = LABEL_TYPE_OTHER; 857 } 858 } 859 860 if (label_type == LABEL_TYPE_EFI) { 861 slicesize = efi_vtoc->efi_parts[index].p_size; 862 efi_free(efi_vtoc); 863 } else if (label_type == LABEL_TYPE_VTOC) { 864 /* 865 * In the vtoc struct, p_size is a 32-bit signed quantity. 866 * In the dk_gpt struct (efi's version of the vtoc), p_size 867 * is an unsigned 64-bit quantity. By casting the vtoc's 868 * psize to an unsigned 32-bit quantity, it will be copied 869 * to 'slicesize' (an unsigned 64-bit diskaddr_t) without 870 * sign extension. 871 */ 872 873 slicesize = (uint32_t)vtoc.v_part[index].p_size; 874 } 875 876 return (slicesize); 877 } 878 879 /* 880 * brute_force_get_device_size 881 * 882 * Determine the size of the device by seeing how far we can 883 * read. Doing an llseek( , , SEEK_END) would probably work 884 * in most cases, but we've seen at least one third-party driver 885 * which doesn't correctly support the SEEK_END option when the 886 * the device is greater than a terabyte. 887 */ 888 889 static diskaddr_t 890 brute_force_get_device_size(int fd) 891 { 892 diskaddr_t min_fail = 0; 893 diskaddr_t max_succeed = 0; 894 diskaddr_t cur_db_off; 895 char buf[DEV_BSIZE]; 896 897 /* 898 * First, see if we can read the device at all, just to 899 * eliminate errors that have nothing to do with the 900 * device's size. 901 */ 902 903 if (((llseek(fd, (offset_t)0, SEEK_SET)) == -1) || 904 ((read(fd, buf, DEV_BSIZE)) == -1)) 905 return (0); /* can't determine size */ 906 907 /* 908 * Now, go sequentially through the multiples of 4TB 909 * to find the first read that fails (this isn't strictly 910 * the most efficient way to find the actual size if the 911 * size really could be anything between 0 and 2**64 bytes. 912 * We expect the sizes to be less than 16 TB for some time, 913 * so why do a bunch of reads that are larger than that? 914 * However, this algorithm *will* work for sizes of greater 915 * than 16 TB. We're just not optimizing for those sizes.) 916 */ 917 918 for (cur_db_off = SECTORS_PER_TERABYTE * 4; 919 min_fail == 0 && cur_db_off < FS_SIZE_UPPER_LIMIT; 920 cur_db_off += 4 * SECTORS_PER_TERABYTE) { 921 if (((llseek(fd, (offset_t)(cur_db_off * DEV_BSIZE), 922 SEEK_SET)) == -1) || 923 ((read(fd, buf, DEV_BSIZE)) != DEV_BSIZE)) 924 min_fail = cur_db_off; 925 else 926 max_succeed = cur_db_off; 927 } 928 929 if (min_fail == 0) 930 return (0); 931 932 /* 933 * We now know that the size of the device is less than 934 * min_fail and greater than or equal to max_succeed. Now 935 * keep splitting the difference until the actual size in 936 * sectors in known. We also know that the difference 937 * between max_succeed and min_fail at this time is 938 * 4 * SECTORS_PER_TERABYTE, which is a power of two, which 939 * simplifies the math below. 940 */ 941 942 while (min_fail - max_succeed > 1) { 943 cur_db_off = max_succeed + (min_fail - max_succeed)/2; 944 if (((llseek(fd, (offset_t)(cur_db_off * DEV_BSIZE), 945 SEEK_SET)) == -1) || 946 ((read(fd, buf, DEV_BSIZE)) != DEV_BSIZE)) 947 min_fail = cur_db_off; 948 else 949 max_succeed = cur_db_off; 950 } 951 952 /* the size is the last successfully read sector offset plus one */ 953 return (max_succeed + 1); 954 } 955 956 /* 957 * validate_size 958 * 959 * Return 1 if the device appears to be at least "size" sectors long. 960 * Return 0 if it's shorter or we can't read it. 961 */ 962 963 static int 964 validate_size(char *disk, diskaddr_t size) 965 { 966 char buf[DEV_BSIZE]; 967 int fd, rc; 968 969 if ((fd = open64(disk, O_RDONLY)) < 0) { 970 perror(disk); 971 exit(1); 972 } 973 974 if ((llseek(fd, (offset_t)((size - 1) * DEV_BSIZE), SEEK_SET) == -1) || 975 (read(fd, buf, DEV_BSIZE)) != DEV_BSIZE) 976 rc = 0; 977 else 978 rc = 1; 979 (void) close(fd); 980 return (rc); 981 } 982 983 /* 984 * read_sb(char * rawdev) - Attempt to read the superblock from a raw device 985 * 986 * Returns: 987 * 0 : 988 * Could not read a valid superblock for a variety of reasons. 989 * Since 'newfs' handles any fatal conditions, we're not going 990 * to make any guesses as to why this is failing or what should 991 * be done about it. 992 * 993 * struct fs *: 994 * A pointer to (what we think is) a valid superblock. The 995 * space for the superblock is static (inside the function) 996 * since we will only be reading the values from it. 997 */ 998 999 struct fs * 1000 read_sb(char *fsdev) 1001 { 1002 static struct fs sblock; 1003 struct stat64 statb; 1004 int dskfd; 1005 char *bufp = NULL; 1006 int bufsz = 0; 1007 1008 if (stat64(fsdev, &statb) < 0) 1009 return (0); 1010 1011 if ((dskfd = open64(fsdev, O_RDONLY)) < 0) 1012 return (0); 1013 1014 /* 1015 * We need a buffer whose size is a multiple of DEV_BSIZE in order 1016 * to read from a raw device (which we were probably passed). 1017 */ 1018 bufsz = ((sizeof (sblock) / DEV_BSIZE) + 1) * DEV_BSIZE; 1019 if ((bufp = malloc(bufsz)) == NULL) { 1020 (void) close(dskfd); 1021 return (0); 1022 } 1023 1024 if (llseek(dskfd, (offset_t)SBOFF, SEEK_SET) < 0 || 1025 read(dskfd, bufp, bufsz) < 0) { 1026 (void) close(dskfd); 1027 free(bufp); 1028 return (0); 1029 } 1030 (void) close(dskfd); /* Done with the file */ 1031 1032 (void) memcpy(&sblock, bufp, sizeof (sblock)); 1033 free(bufp); /* Don't need this anymore */ 1034 1035 if (((sblock.fs_magic != FS_MAGIC) && 1036 (sblock.fs_magic != MTB_UFS_MAGIC)) || 1037 sblock.fs_ncg < 1 || sblock.fs_cpg < 1) 1038 return (0); 1039 1040 if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || 1041 (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) 1042 return (0); 1043 1044 if (sblock.fs_sbsize < 0 || sblock.fs_sbsize > SBSIZE) 1045 return (0); 1046 1047 return (&sblock); 1048 } 1049 1050 /* 1051 * Read the UFS file system on the raw device SPECIAL. If it does not 1052 * appear to be a UFS file system, return non-zero, indicating that 1053 * fsirand should be called (and it will spit out an error message). 1054 * If it is a UFS file system, take a look at the inodes in the first 1055 * cylinder group. If they appear to be randomized (non-zero), return 1056 * zero, which will cause fsirand to not be called. If the inode generation 1057 * counts are all zero, then we must call fsirand, so return non-zero. 1058 */ 1059 1060 #define RANDOMIZED 0 1061 #define NOT_RANDOMIZED 1 1062 1063 static int 1064 notrand(char *special) 1065 { 1066 long fsbuf[SBSIZE / sizeof (long)]; 1067 struct dinode dibuf[MAXBSIZE/sizeof (struct dinode)]; 1068 struct fs *fs; 1069 struct dinode *dip; 1070 offset_t seekaddr; 1071 int bno, inum; 1072 int fd; 1073 1074 fs = (struct fs *)fsbuf; 1075 if ((fd = open64(special, 0)) == -1) 1076 return (NOT_RANDOMIZED); 1077 if (llseek(fd, (offset_t)SBLOCK * DEV_BSIZE, 0) == -1 || 1078 read(fd, (char *)fs, SBSIZE) != SBSIZE || 1079 ((fs->fs_magic != FS_MAGIC) && (fs->fs_magic != MTB_UFS_MAGIC))) { 1080 (void) close(fd); 1081 return (NOT_RANDOMIZED); 1082 } 1083 1084 /* looks like a UFS file system; read the first cylinder group */ 1085 bsize = INOPB(fs) * sizeof (struct dinode); 1086 inum = 0; 1087 while (inum < fs->fs_ipg) { 1088 bno = itod(fs, inum); 1089 seekaddr = (offset_t)fsbtodb(fs, bno) * DEV_BSIZE; 1090 if (llseek(fd, seekaddr, 0) == -1 || 1091 read(fd, (char *)dibuf, bsize) != bsize) { 1092 (void) close(fd); 1093 return (NOT_RANDOMIZED); 1094 } 1095 for (dip = dibuf; dip < &dibuf[INOPB(fs)]; dip++) { 1096 if (dip->di_gen != 0) { 1097 (void) close(fd); 1098 return (RANDOMIZED); 1099 } 1100 inum++; 1101 } 1102 } 1103 (void) close(fd); 1104 return (NOT_RANDOMIZED); 1105 } 1106 1107 static void 1108 usage(void) 1109 { 1110 (void) fprintf(stderr, gettext( 1111 "usage: newfs [ -v ] [ mkfs-options ] raw-special-device\n")); 1112 (void) fprintf(stderr, gettext("where mkfs-options are:\n")); 1113 (void) fprintf(stderr, gettext( 1114 "\t-N do not create file system, just print out parameters\n")); 1115 (void) fprintf(stderr, gettext( 1116 "\t-T configure file system for eventual growth to over a terabyte\n")); 1117 (void) fprintf(stderr, gettext("\t-s file system size (sectors)\n")); 1118 (void) fprintf(stderr, gettext("\t-b block size\n")); 1119 (void) fprintf(stderr, gettext("\t-f frag size\n")); 1120 (void) fprintf(stderr, gettext("\t-t tracks/cylinder\n")); 1121 (void) fprintf(stderr, gettext("\t-c cylinders/group\n")); 1122 (void) fprintf(stderr, gettext("\t-m minimum free space %%\n")); 1123 (void) fprintf(stderr, gettext( 1124 "\t-o optimization preference (`space' or `time')\n")); 1125 (void) fprintf(stderr, gettext("\t-r revolutions/minute\n")); 1126 (void) fprintf(stderr, gettext("\t-i number of bytes per inode\n")); 1127 (void) fprintf(stderr, gettext( 1128 "\t-a number of alternates per cylinder\n")); 1129 (void) fprintf(stderr, gettext("\t-C maxcontig\n")); 1130 (void) fprintf(stderr, gettext("\t-d rotational delay\n")); 1131 (void) fprintf(stderr, gettext( 1132 "\t-n number of rotational positions\n")); 1133 (void) fprintf(stderr, gettext( 1134 "\t-S print a textual version of the calculated superblock to stdout\n")); 1135 (void) fprintf(stderr, gettext( 1136 "\t-B dump a binary version of the calculated superblock to stdout\n")); 1137 } 1138 1139 /* 1140 * Error-detecting version of atoi(3). Adapted from mkfs' number(). 1141 */ 1142 static unsigned int 1143 number(char *param, char *value, int flags, int def_value) 1144 { 1145 char *cs; 1146 int n; 1147 int cut = INT_MAX / 10; /* limit to avoid overflow */ 1148 int minus = 0; 1149 1150 cs = value; 1151 if (*cs == '-') { 1152 minus = 1; 1153 cs += 1; 1154 } 1155 if ((*cs < '0') || (*cs > '9')) { 1156 goto bail_out; 1157 } 1158 n = 0; 1159 while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) { 1160 n = n*10 + *cs++ - '0'; 1161 } 1162 if (minus) 1163 n = -n; 1164 for (;;) { 1165 switch (*cs++) { 1166 case '\0': 1167 return (n); 1168 1169 case '0': case '1': case '2': case '3': case '4': 1170 case '5': case '6': case '7': case '8': case '9': 1171 (void) fprintf(stderr, gettext( 1172 "newfs: value for %s overflowed, using %d\n"), 1173 param, def_value); 1174 return (def_value); 1175 1176 case '%': 1177 if (flags & NR_PERCENT) 1178 break; 1179 /* FALLTHROUGH */ 1180 1181 default: 1182 bail_out: 1183 fatal(gettext("bad numeric arg for %s: \"%s\""), 1184 param, value); 1185 1186 } 1187 } 1188 /* NOTREACHED */ 1189 } 1190 1191 /* 1192 * Error-detecting version of atoi(3). Adapted from mkfs' number(). 1193 */ 1194 static int64_t 1195 number64(char *param, char *value, int flags, int64_t def_value) 1196 { 1197 char *cs; 1198 int64_t n; 1199 int64_t cut = FS_SIZE_UPPER_LIMIT/ 10; /* limit to avoid overflow */ 1200 int minus = 0; 1201 1202 cs = value; 1203 if (*cs == '-') { 1204 minus = 1; 1205 cs += 1; 1206 } 1207 if ((*cs < '0') || (*cs > '9')) { 1208 goto bail_out; 1209 } 1210 n = 0; 1211 while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) { 1212 n = n*10 + *cs++ - '0'; 1213 } 1214 if (minus) 1215 n = -n; 1216 for (;;) { 1217 switch (*cs++) { 1218 case '\0': 1219 return (n); 1220 1221 case '0': case '1': case '2': case '3': case '4': 1222 case '5': case '6': case '7': case '8': case '9': 1223 (void) fprintf(stderr, gettext( 1224 "newfs: value for %s overflowed, using %d\n"), 1225 param, def_value); 1226 return (def_value); 1227 1228 case '%': 1229 if (flags & NR_PERCENT) 1230 break; 1231 /* FALLTHROUGH */ 1232 1233 default: 1234 bail_out: 1235 fatal(gettext("bad numeric arg for %s: \"%s\""), 1236 param, value); 1237 1238 } 1239 } 1240 /* NOTREACHED */ 1241 } 1242