1/* 2 * Copyright (c) 1999-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25#include <err.h> 26#include <errno.h> 27#include <fcntl.h> 28#include <grp.h> 29#include <paths.h> 30#include <pwd.h> 31#include <stdlib.h> 32#include <stdio.h> 33#include <string.h> 34#include <ctype.h> 35#include <syslog.h> 36#include <unistd.h> 37 38#include <sys/ioctl.h> 39#include <sys/mount.h> 40#include <sys/param.h> 41#include <sys/stat.h> 42 43#include <IOKit/storage/IOMediaBSDClient.h> 44 45#include <hfs/hfs_format.h> 46#include "newfs_hfs.h" 47 48#if __STDC__ 49#include <stdarg.h> 50#else 51#include <varargs.h> 52#endif 53 54#define NOVAL (-1) 55#define UMASK (0755) 56#define ACCESSMASK (0777) 57 58/* 59 * The maximum HFS volume size is calculated thusly: 60 * 61 * The maximum allocation block size (which must be a power of 2 value), 62 * is 2GB, or 2^31 bytes 63 * 64 * The maximum number of allocation blocks is 2^32 -1. 65 * 66 * Multiplying that out yields 2GB * ( 4GB - 1 ) == 2GB*4GB - 2GB. 67 * More explicitly, 8 exabytes - 2 gigabytes, 68 * or 0x7FFFFFFF80000000 bytes. That gives us our value below. 69 */ 70 71#define MAXHFSVOLSIZE (0x7FFFFFFF80000000ULL) 72 73#define ROUNDUP(x,y) (((x)+(y)-1)/(y)*(y)) 74 75static void getnodeopts __P((char* optlist)); 76static void getclumpopts __P((char* optlist)); 77#ifdef DEBUG_BUILD 78static void getstartopts __P((char *optlist)); 79static void getextsopts __P((char* optlist)); 80#endif 81static gid_t a_gid __P((char *)); 82static uid_t a_uid __P((char *)); 83static mode_t a_mask __P((char *)); 84static int hfs_newfs __P((char *device)); 85static void validate_hfsplus_block_size __P((UInt64 sectorCount, UInt32 sectorSize)); 86static void hfsplus_params __P((const DriveInfo* dip, hfsparams_t *defaults)); 87static UInt32 clumpsizecalc __P((UInt32 clumpblocks)); 88static UInt32 CalcHFSPlusBTreeClumpSize __P((UInt32 blockSize, UInt32 nodeSize, UInt64 sectors, int fileID)); 89static void usage __P((void)); 90static int get_high_bit (u_int64_t bitstring); 91static int bad_disk_size (u_int64_t numsectors, u_int64_t sectorsize); 92 93 94 95char *progname; 96char *gVolumeName = kDefaultVolumeNameStr; 97char rawdevice[MAXPATHLEN]; 98char blkdevice[MAXPATHLEN]; 99uint32_t gBlockSize = 0; 100UInt32 gNextCNID = kHFSFirstUserCatalogNodeID; 101 102time_t createtime; 103 104int gNoCreate = FALSE; 105int gUserCatNodeSize = FALSE; 106int gCaseSensitive = FALSE; 107int gUserAttrSize = FALSE; 108int gContentProtect = FALSE; 109 110static UInt32 attrExtCount = 1, blkallocExtCount = 1, catExtCount = 1, extExtCount = 1; 111static UInt32 attrExtStart = 0, blkallocExtStart = 0, catExtStart = 0, extExtStart = 0; 112static UInt32 jibStart = 0, jnlStart = 0, allocStart = 0; 113 114#ifdef DEBUG_BUILD 115uint16_t gProtectLevel = 0; 116#endif 117 118#define JOURNAL_DEFAULT_SIZE (8*1024*1024) 119int gJournaled = FALSE; 120char *gJournalDevice = NULL; 121UInt64 gJournalSize = 0; 122 123uid_t gUserID = (uid_t)NOVAL; 124gid_t gGroupID = (gid_t)NOVAL; 125mode_t gModeMask = (mode_t)NOVAL; 126 127/* Starting allocation block number for the file system, 128 * all btrees, including journal will be laid down at this 129 * alloation block offset. 130 */ 131UInt32 gFSStartBlock = 0; 132 133UInt64 gPartitionSize = 0; 134 135UInt32 catnodesiz = 8192; 136UInt32 extnodesiz = 4096; 137UInt32 atrnodesiz = 8192; 138 139UInt32 catclumpblks = 0; 140UInt32 extclumpblks = 0; 141UInt32 atrclumpblks = 0; 142UInt32 bmclumpblks = 0; 143UInt32 rsrclumpblks = 0; 144UInt32 datclumpblks = 0; 145uint32_t hfsgrowblks = 0; /* maximum growable size of wrapper */ 146 147 148UInt64 149get_num(char *str) 150{ 151 UInt64 num; 152 char *ptr; 153 154 num = strtoull(str, &ptr, 0); 155 156 if (*ptr) { 157 char scale = tolower(*ptr); 158 159 switch(scale) { 160 case 'b': 161 num *= 512ULL; 162 break; 163 case 'p': 164 num *= 1024ULL; 165 /* fall through */ 166 case 't': 167 num *= 1024ULL; 168 /* fall through */ 169 case 'g': 170 num *= 1024ULL; 171 /* fall through */ 172 case 'm': 173 num *= 1024ULL; 174 /* fall through */ 175 case 'k': 176 num *= 1024ULL; 177 break; 178 179 default: 180 num = 0ULL; 181 break; 182 } 183 } 184 return num; 185} 186 187 188int 189main(argc, argv) 190 int argc; 191 char **argv; 192{ 193 extern char *optarg; 194 extern int optind; 195 int ch; 196 char *cp, *special; 197 struct statfs *mp; 198 int n; 199 200 if ((progname = strrchr(*argv, '/'))) 201 ++progname; 202 else 203 progname = *argv; 204 205// No semicolon at end of line deliberately! 206 207 static const char *options = "G:J:D:M:N:PU:hsb:c:i:n:v:" 208#ifdef DEBUG_BUILD 209 "p:a:E:" 210#endif 211 ; 212 213 while ((ch = getopt(argc, argv, options)) != -1) 214 switch (ch) { 215 case 'G': 216 gGroupID = a_gid(optarg); 217 break; 218 219 case 'J': 220 gJournaled = TRUE; 221 if (isdigit(optarg[0])) { 222 gJournalSize = get_num(optarg); 223 if (gJournalSize < 512*1024) { 224 printf("%s: journal size %lldk too small. Reset to %dk.\n", 225 progname, gJournalSize/1024, JOURNAL_DEFAULT_SIZE/1024); 226 gJournalSize = JOURNAL_DEFAULT_SIZE; 227 } 228 } else { 229 /* back up because there was no size argument */ 230 optind--; 231 } 232 break; 233 234 case 'D': 235 gJournalDevice = (char *)optarg; 236 break; 237 238 case 'N': 239 gNoCreate = TRUE; 240 if (isdigit(optarg[0])) { 241 gPartitionSize = get_num(optarg); 242 } else { 243 /* back up because there was no size argument */ 244 optind--; 245 } 246 break; 247 248 case 'P': 249 gContentProtect = TRUE; 250 break; 251 252#ifdef DEBUG_BUILD 253 case 'p': 254 if (isdigit (optarg[0])) { 255 uint64_t level = get_num (optarg); 256 gProtectLevel = (uint16_t) level; 257 } 258 else { 259 /* back up because no level was provided */ 260 optind--; 261 } 262 break; 263#endif 264 265 case 'M': 266 gModeMask = a_mask(optarg); 267 break; 268 269 case 'U': 270 gUserID = a_uid(optarg); 271 break; 272 273#ifdef DEBUG_BUILD 274 case 'a': 275 getstartopts(optarg); 276 break; 277#endif 278 279#ifdef DEBUG_BUILD 280 case 'E': 281 getextsopts(optarg); 282 break; 283#endif 284 case 'b': 285 { 286 UInt64 tempBlockSize; 287 288 tempBlockSize = get_num(optarg); 289 if (tempBlockSize < HFSMINBSIZE) 290 fatal("%s: bad allocation block size (too small)", optarg); 291 if (tempBlockSize > HFSMAXBSIZE) 292 fatal("%s: bad allocation block size (too large)", optarg); 293 gBlockSize = tempBlockSize; 294 break; 295 } 296 297 case 'c': 298 getclumpopts(optarg); 299 break; 300 301 case 'i': 302 gNextCNID = atoi(optarg); 303 /* 304 * make sure its at least kHFSFirstUserCatalogNodeID 305 */ 306 if (gNextCNID < kHFSFirstUserCatalogNodeID) 307 fatal("%s: starting catalog node id too small (must be > 15)", optarg); 308 break; 309 310 case 'n': 311 getnodeopts(optarg); 312 break; 313 314 case 's': 315 gCaseSensitive = TRUE; 316 break; 317 318 case 'v': 319 if ((gVolumeName = strdup(optarg)) == NULL) { 320 fatal("Could not copy volume name %s", optarg); 321 } 322 break; 323 324 case '?': 325 default: 326 usage(); 327 } 328 329 argc -= optind; 330 argv += optind; 331 332#ifdef DEBUG_BUILD 333 if ((gProtectLevel) && !(gContentProtect)) { 334 fatal ("content protection must be specified to set a protection level"); 335 } 336#endif 337 338 if (gPartitionSize != 0) { 339 /* 340 * If we are given -N, a size, and a device, that's a usage error. 341 */ 342 if (argc != 0) 343 usage(); 344 345 rawdevice[0] = blkdevice[0] = 0; 346 } else { 347 if (argc != 1) 348 usage(); 349 350 special = argv[0]; 351 cp = strrchr(special, '/'); 352 if (cp != 0) 353 special = cp + 1; 354 if (*special == 'r') 355 special++; 356 (void) snprintf(rawdevice, sizeof(rawdevice), "%sr%s", _PATH_DEV, special); 357 (void) snprintf(blkdevice, sizeof(blkdevice), "%s%s", _PATH_DEV, special); 358 } 359 360 if (gPartitionSize == 0) { 361 /* 362 * Check if target device is aready mounted 363 */ 364 n = getmntinfo(&mp, MNT_NOWAIT); 365 if (n == 0) 366 fatal("%s: getmntinfo: %s", blkdevice, strerror(errno)); 367 368 while (--n >= 0) { 369 if (strcmp(blkdevice, mp->f_mntfromname) == 0) 370 fatal("%s is mounted on %s", blkdevice, mp->f_mntonname); 371 ++mp; 372 } 373 } 374 375 if (hfs_newfs(rawdevice) < 0) { 376 err(1, "cannot create filesystem on %s", rawdevice); 377 } 378 379 exit(0); 380} 381 382 383static void getnodeopts(char* optlist) 384{ 385 char *strp = optlist; 386 char *ndarg; 387 char *p; 388 UInt32 ndsize; 389 390 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') { 391 392 p = strchr(ndarg, '='); 393 if (p == NULL) 394 usage(); 395 396 ndsize = atoi(p+1); 397 398 switch (*ndarg) { 399 case 'c': 400 if (ndsize < 4096 || ndsize > 32768 || (ndsize & (ndsize-1)) != 0) 401 fatal("%s: invalid catalog b-tree node size", ndarg); 402 catnodesiz = ndsize; 403 gUserCatNodeSize = TRUE; 404 break; 405 406 case 'e': 407 if (ndsize < 1024 || ndsize > 32768 || (ndsize & (ndsize-1)) != 0) 408 fatal("%s: invalid extents b-tree node size", ndarg); 409 extnodesiz = ndsize; 410 break; 411 412 case 'a': 413 if (ndsize < 4096 || ndsize > 32768 || (ndsize & (ndsize-1)) != 0) 414 fatal("%s: invalid atrribute b-tree node size", ndarg); 415 atrnodesiz = ndsize; 416 break; 417 418 default: 419 usage(); 420 } 421 } 422} 423 424 425static void getclumpopts(char* optlist) 426{ 427 char *strp = optlist; 428 char *ndarg; 429 char *p; 430 UInt32 clpblocks; 431 432 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') { 433 434 p = strchr(ndarg, '='); 435 if (p == NULL) 436 usage(); 437 438 clpblocks = atoi(p+1); 439 440 switch (*ndarg) { 441 case 'a': 442 atrclumpblks = clpblocks; 443 gUserAttrSize = TRUE; 444 break; 445 case 'b': 446 bmclumpblks = clpblocks; 447 break; 448 case 'c': 449 catclumpblks = clpblocks; 450 break; 451 case 'd': 452 datclumpblks = clpblocks; 453 break; 454 case 'e': 455 extclumpblks = clpblocks; 456 break; 457 case 'r': 458 rsrclumpblks = clpblocks; 459 break; 460 461 default: 462 usage(); 463 } 464 } 465} 466 467#ifdef DEBUG_BUILD 468static void getextsopts(char* optlist) 469{ 470 char *strp = optlist; 471 char *ndarg; 472 char *p; 473 UInt32 numexts; 474 475 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') { 476 477 p = strchr(ndarg, '='); 478 if (p == NULL) 479 usage(); 480 481 numexts = atoi(p+1); 482 483 switch (*ndarg) { 484 case 'a': 485 attrExtCount = numexts; 486 break; 487 case 'b': 488 blkallocExtCount = numexts; 489 break; 490 case 'c': 491 catExtCount = numexts; 492 break; 493 case 'e': 494 extExtCount = numexts; 495 break; 496 default: 497 usage(); 498 } 499 } 500} 501 502static void getstartopts(char* optlist) 503{ 504 char *strp; 505 char *ndarg; 506 char *p; 507 unsigned long startat = 0; 508 509 startat = strtoul(optlist, &strp, 0); 510 if (startat == ULONG_MAX && errno != 0) { 511 err(1, "invalid allocation start block string %s", optlist); 512 } 513 if (startat > UINT_MAX) { 514 errx(1, "Allocation block %lu larger than max", startat); 515 } 516 if (strp && *strp == ',') 517 strp++; 518 519 gFSStartBlock = startat; 520 521 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') { 522 523 startat = strtoul(optlist, NULL, 0); 524 p = strchr(ndarg, '='); 525 if (p == NULL) 526 usage(); 527 528 startat = atoi(p+1); 529 530 switch (*ndarg) { 531 case 'a': 532 attrExtStart = startat; 533 break; 534 case 'b': 535 blkallocExtStart = startat; 536 break; 537 case 'c': 538 catExtStart = startat; 539 break; 540 case 'e': 541 extExtStart = startat; 542 break; 543 case 'j': 544 jibStart = startat; 545 break; 546 case 'J': 547 jnlStart = startat; 548 break; 549 case 'N': 550 allocStart = startat; 551 break; 552 default: 553 usage(); 554 } 555 } 556} 557#endif 558 559gid_t 560static a_gid(char *s) 561{ 562 struct group *gr; 563 char *gname; 564 gid_t gid = 0; 565 566 if ((gr = getgrnam(s)) != NULL) 567 gid = gr->gr_gid; 568 else { 569 for (gname = s; *s && isdigit(*s); ++s); 570 if (!*s) 571 gid = atoi(gname); 572 else 573 errx(1, "unknown group id: %s", gname); 574 } 575 return (gid); 576} 577 578static uid_t 579a_uid(char *s) 580{ 581 struct passwd *pw; 582 char *uname; 583 uid_t uid = 0; 584 585 if ((pw = getpwnam(s)) != NULL) 586 uid = pw->pw_uid; 587 else { 588 for (uname = s; *s && isdigit(*s); ++s); 589 if (!*s) 590 uid = atoi(uname); 591 else 592 errx(1, "unknown user id: %s", uname); 593 } 594 return (uid); 595} 596 597static mode_t 598a_mask(char *s) 599{ 600 int done, rv; 601 char *ep; 602 603 done = 0; 604 rv = -1; 605 if (*s >= '0' && *s <= '7') { 606 done = 1; 607 rv = strtol(s, &ep, 8); 608 } 609 if (!done || rv < 0 || *ep) 610 errx(1, "invalid access mask: %s", s); 611 return (rv); 612} 613 614/* 615 * Check to see if the volume is too big. 616 * 617 * Returns: 618 * 0 if it is appropriately sized. 619 * 1 if HFS+ cannot be formatted onto the disk. 620 */ 621 622static int bad_disk_size (u_int64_t numsectors, u_int64_t sectorsize) { 623 624 u_int32_t maxSectorBits = 0; 625 u_int32_t maxSectorSizeBits = 0; 626 u_int32_t maxBits = 0; 627 u_int64_t bytes; 628 629 /* 630 * The essential problem here is that we cannot simply multiply the sector size by the 631 * number of sectors because the product could overflow a 64 bit integer. We do a cursory 632 * check and then a longer check once we know the product will not overflow. 633 */ 634 635 maxSectorBits = get_high_bit (numsectors); 636 maxSectorSizeBits = get_high_bit (sectorsize); 637 638 /* 639 * We get the number of bits to represent the number of sectors and the sector size. 640 * Adding the two numbers gives us the number of bits required to represent the product. 641 * If the product is > 63 then it must be too big. 642 */ 643 644 maxBits = maxSectorBits + maxSectorSizeBits; 645 if (maxBits > 63) { 646 return 1; 647 } 648 649 /* Well, now we know that the two values won't overflow. Time to multiply */ 650 bytes = numsectors * sectorsize; 651 652 if (bytes > MAXHFSVOLSIZE) { 653 /* Too big! */ 654 return 1; 655 } 656 657 /* Otherwise, it looks good */ 658 return 0; 659 660} 661 662/* 663 * The allocation block size must be defined as a power of 2 value, with a floor of 664 * 512 bytes. However, we never default to anything less than 4096 bytes, so that 665 * gives us 20 block size values from 4kb -> 2GB block size. 666 * 667 * See inline comments for how this table is used to determine the minimum fs size that 668 * will use a specified allocation block size. 669 * 670 * The growth boundary is used to figure out if we need a bigger block size than the 671 * 4 KB default. We get the index of the highest bit set in the FS size, then subtract the 672 * growth boundary to index into the block allocation size array. 673 * 674 * Note that 8K appears twice in table since we want to use it for the range 2 TB < 8 TB FS size. 675 * This means that when the 2TB bit or the 4TB bit is the high bit set, we prefer the 8K block size. 676 */ 677#define NUM_ALLOC_BLOCKSIZES 21 678#define GROWTH_BOUNDARY 41 679 680u_int64_t alloc_blocksize[NUM_ALLOC_BLOCKSIZES] = { 681 /* Block Size*/ /* Min Dflt FS Size */ /* Max FS Size */ 682 4096, /* 0 bytes */ /* 16 TB */ 683 8192, /* 2 TB */ /* 32 TB */ /* Note that 8K appears twice in table ! */ 684 8192, /* 4 TB */ /* 32 TB */ /* Note that 8K appears twice in table ! */ 685 16384, /* 8 TB */ /* 64 TB */ 686 32768, /* 16 TB */ /* 128 TB */ 687 65536, /* 32 TB */ /* 256 TB */ 688 131072, /* 64 TB */ /* 512 TB */ 689 262144, /* 128 TB */ /* 1 PB */ 690 524288, /* 256 TB */ /* 2 PB */ 691 1048576, /* 512 TB */ /* 4 PB */ 692 2097152, /* 1 PB */ /* 8 PB */ 693 4194304, /* 2 PB */ /* 16 PB */ 694 8388608, /* 4 PB */ /* 32 PB */ 695 16777216, /* 8 PB */ /* 64 PB */ 696 33554432, /* 16 PB */ /* 128 PB */ 697 67108864, /* 32 PB */ /* 256 PB */ 698 134217728, /* 64 PB */ /* 512 PB */ 699 268435456, /* 128 PB */ /* 1 EB */ 700 536870912, /* 256 PB */ /* 2 EB */ 701 1073741824, /* 512 PB */ /* 4 EB */ 702 2147483648ULL /* 1 EB */ /* 8 EB */ 703}; 704 705static int get_high_bit (u_int64_t bitstring) { 706 u_int64_t bits = bitstring; 707 int counter = 0; 708 while (bits) { 709 bits = (bits >> 1); 710 counter++; 711 } 712 return counter; 713} 714 715 716/* 717 * Validate the HFS Plus allocation block size in gBlockSize. If none was 718 * specified, then calculate a suitable default. 719 * 720 * Modifies the global variable gBlockSize. 721 */ 722static void validate_hfsplus_block_size(UInt64 sectorCount, UInt32 sectorSize) 723{ 724 if (gBlockSize == 0) { 725 726 /* Start by calculating the fs size */ 727 u_int64_t fs_size = sectorCount * sectorSize; 728 729 /* 730 * Determine the default based on a sliding scale. The maximum number of 731 * allocation blocks is always 4294967295 == (32 bits worth). At 1 bit per 732 * allocation block, that yields 512 MB of bitmap no matter what size we use 733 * for the allocation block. 734 * 735 * The general default policy is to allow the filesystem to grow up to 8x the 736 * current maximum size. So for a 1.5TB filesystem, an 8x multiplier would be 737 * 12TB. That means we can use the default size of 4096 bytes. The boundary begins 738 * at 2TB, since at that point, we can no longer use the default 4096 block size to 739 * extend the filesystem by 8x. For a 16KB block size, the max is 64 TB, but the 8x 740 * multiplier begins at 8 TB. Thereafter, we increase for every power of 2 that 741 * the current filesystem size grows. 742 */ 743 744 gBlockSize = DFL_BLKSIZE; /* Prefer the default of 4K */ 745 746 int bit_index = get_high_bit (fs_size); 747 bit_index -= GROWTH_BOUNDARY; 748 749 /* 750 * After subtracting the GROWTH_BOUNDARY to index into the array, we'll 751 * use the values in the static array if we have a non-negative index. 752 * That means that if the filesystem is >= 1 TB, then we'll use the index 753 * value. At 2TB, we grow to the 8K block size. 754 */ 755 if ((bit_index >= 0) && (bit_index < 22)) { 756 gBlockSize = alloc_blocksize[bit_index]; 757 } 758 759 if (bit_index >= 22) { 760 fatal("Error: Disk Device is too big (%llu sectors, %d bytes per sector", sectorCount, sectorSize); 761 } 762 } 763 else { 764 /* Make sure a user-specified block size is reasonable */ 765 if ((gBlockSize & (gBlockSize-1)) != 0) { 766 fatal("%s: bad HFS Plus allocation block size (must be a power of two)", optarg); 767 } 768 769 if ((sectorCount / (gBlockSize / sectorSize)) > 0xFFFFFFFF) { 770 fatal("%s: block size is too small for %lld sectors", optarg, gBlockSize, sectorCount); 771 } 772 773 if (gBlockSize < HFSOPTIMALBLKSIZE) { 774 warnx("Warning: %u is a non-optimal block size (4096 would be a better choice)", (unsigned int)gBlockSize); 775 } 776 } 777 778 if (gFSStartBlock) { 779 u_int64_t fs_size = sectorCount * sectorSize; 780 u_int32_t totalBlocks = fs_size/gBlockSize; 781 782 if (gFSStartBlock >= totalBlocks) { 783 warnx("Warning: %u is invalid file system start allocation block number, must be less than total allocation blocks (%u)", (unsigned int)gFSStartBlock, (unsigned int)totalBlocks); 784 warnx("Warning: Resetting file system start block to zero"); 785 gFSStartBlock = 0; 786 } 787 } 788} 789 790 791 792static int 793hfs_newfs(char *device) 794{ 795 struct stat stbuf; 796 DriveInfo dip = { 0 }; 797 int fso = -1; 798 int retval = 0; 799 hfsparams_t defaults = {0}; 800 UInt64 maxPhysPerIO = 0; 801 802 if (gPartitionSize) { 803 dip.sectorSize = kBytesPerSector; 804 dip.physTotalSectors = dip.totalSectors = gPartitionSize / kBytesPerSector; 805 dip.physSectorSize = kBytesPerSector; /* 512-byte sectors */ 806 dip.fd = 0; 807 } else { 808 if (gNoCreate) { 809 fso = open( device, O_RDONLY | O_NDELAY, 0 ); 810 } else { 811 fso = open( device, O_RDWR | O_NDELAY, 0 ); 812 } 813 if (fso == -1) { 814 return -1; 815 } 816 817 dip.fd = fso; 818 fcntl(fso, F_NOCACHE, 1); 819 820 if (fso < 0) 821 fatal("%s: %s", device, strerror(errno)); 822 823 if (fstat( fso, &stbuf) < 0) 824 fatal("%s: %s", device, strerror(errno)); 825 826 if (ioctl(fso, DKIOCGETBLOCKSIZE, &dip.physSectorSize) < 0) 827 fatal("%s: %s", device, strerror(errno)); 828 829 if ((dip.physSectorSize % kBytesPerSector) != 0) 830 fatal("%d is an unsupported sector size\n", dip.physSectorSize); 831 832 if (ioctl(fso, DKIOCGETBLOCKCOUNT, &dip.physTotalSectors) < 0) 833 fatal("%s: %s", device, strerror(errno)); 834 835 } 836 837 dip.physSectorsPerIO = (1024 * 1024) / dip.physSectorSize; /* use 1M as default */ 838 839 if (fso != -1 && ioctl(fso, DKIOCGETMAXBLOCKCOUNTREAD, &maxPhysPerIO) < 0) 840 fatal("%s: %s", device, strerror(errno)); 841 842 if (maxPhysPerIO) 843 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO); 844 845 if (fso != -1 && ioctl(fso, DKIOCGETMAXBLOCKCOUNTWRITE, &maxPhysPerIO) < 0) 846 fatal("%s: %s", device, strerror(errno)); 847 848 if (maxPhysPerIO) 849 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO); 850 851 if (fso != -1 && ioctl(fso, DKIOCGETMAXBYTECOUNTREAD, &maxPhysPerIO) < 0) 852 fatal("%s: %s", device, strerror(errno)); 853 854 if (maxPhysPerIO) 855 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO / dip.physSectorSize); 856 857 if (fso != -1 && ioctl(fso, DKIOCGETMAXBYTECOUNTWRITE, &maxPhysPerIO) < 0) 858 fatal("%s: %s", device, strerror(errno)); 859 860 if (maxPhysPerIO) 861 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO / dip.physSectorSize); 862 863 dip.sectorSize = kBytesPerSector; 864 dip.totalSectors = dip.physTotalSectors * dip.physSectorSize / dip.sectorSize; 865 866 dip.sectorOffset = 0; 867 time(&createtime); 868 869 /* Check to see if the disk is too big */ 870 u_int64_t secsize = (u_int64_t) dip.sectorSize; 871 if (bad_disk_size(dip.totalSectors, secsize)) { 872 fatal("%s: partition is too big (maximum is %llu KB)", device, MAXHFSVOLSIZE/1024); 873 } 874 875 /* 876 * If we're going to make an HFS Plus disk (with or without a wrapper), validate the 877 * HFS Plus allocation block size. This will also calculate a default allocation 878 * block size if none (or zero) was specified. 879 */ 880 validate_hfsplus_block_size(dip.totalSectors, dip.sectorSize); 881 882 /* Make an HFS Plus disk */ 883 884 if ((dip.totalSectors * dip.sectorSize ) < kMinHFSPlusVolumeSize) 885 fatal("%s: partition is too small (minimum is %d KB)", device, kMinHFSPlusVolumeSize/1024); 886 887 hfsplus_params(&dip, &defaults); 888 if (gNoCreate == 0) { 889 retval = make_hfsplus(&dip, &defaults); 890 if (retval == 0) { 891 printf("Initialized %s as a ", device); 892 if (dip.totalSectors > 2048ULL*1024*1024) 893 printf("%ld TB", 894 (long)((dip.totalSectors + (1024ULL*1024*1024))/(2048ULL*1024*1024))); 895 else if (dip.totalSectors > 2048*1024) 896 printf("%ld GB", 897 (long)((dip.totalSectors + (1024*1024))/(2048*1024))); 898 else if (dip.totalSectors > 2048) 899 printf("%ld MB", 900 (long)((dip.totalSectors + 1024)/2048)); 901 else 902 printf("%ld KB", 903 (long)((dip.totalSectors + 1)/2)); 904 905 if (gCaseSensitive) { 906 printf(" case-sensitive"); 907 } 908 else { 909 printf(" case-insensitive"); 910 } 911 if (gJournaled) 912 printf(" HFS Plus volume with a %uk journal\n", 913 (u_int32_t)defaults.journalSize/1024); 914 else 915 printf(" HFS Plus volume\n"); 916 } 917 } 918 919 if (retval) 920 fatal("%s: %s", device, strerror(errno)); 921 922 if ( fso > 0 ) { 923 close(fso); 924 } 925 926 return retval; 927} 928 929/* 930 typedef struct block_info { 931 off_t bnum; //64 bit 932 union { 933 _blk_info bi; //64 bit 934 struct buf *bp; //64 bit on K64, 32 bit on K32 935 } u; 936 }__attribute__((__packed__)) block_info; 937 938 total size == 16 bytes 939 */ 940 941#define BLOCK_INFO_SIZE 16 942 943static void hfsplus_params (const DriveInfo* dip, hfsparams_t *defaults) 944{ 945 UInt64 sectorCount = dip->totalSectors; 946 UInt32 sectorSize = dip->sectorSize; 947 uint32_t totalBlocks; 948 UInt32 minClumpSize; 949 UInt32 clumpSize; 950 UInt32 oddBitmapBytes; 951 952 defaults->flags = 0; 953 defaults->blockSize = gBlockSize; 954 defaults->fsStartBlock = gFSStartBlock; 955 defaults->nextFreeFileID = gNextCNID; 956 defaults->createDate = createtime + MAC_GMT_FACTOR; /* Mac OS GMT time */ 957 defaults->hfsAlignment = 0; 958 defaults->journaledHFS = gJournaled; 959 defaults->journalDevice = gJournalDevice; 960 961 /* 962 * 8429818 963 * Always set kUseAccessPerms now; this also 964 * means we have to always have an owner, group, 965 * and mask. 966 */ 967 defaults->owner = (gUserID == (uid_t)NOVAL) ? geteuid() : gUserID; 968 defaults->group = (gGroupID == (gid_t)NOVAL) ? getegid() : gGroupID; 969 defaults->mask = (gModeMask == (mode_t)NOVAL) ? UMASK : (gModeMask & ACCESSMASK); 970 defaults->flags |= kUseAccessPerms; 971 972 /* 973 * We want at least 8 megs of journal for each 100 gigs of 974 * disk space. We cap the size at 512 megs (64x default), unless 975 * the allocation block size is larger, in which case we use one 976 * allocation block. 977 * 978 * Only scale if it's the default, otherwise just take what 979 * the user specified, with the caveat below. 980 */ 981 if (gJournaled) { 982 uint32_t min_size = 0; 983 984 /* 985 * Check to ensure the journal size is not too small relative to the 986 * sector size of the device. This is the check in the kernel: 987 if (tr->blhdr && (tr->blhdr->max_blocks <= 0 || 988 tr->blhdr->max_blocks > (tr->jnl->jhdr->size/tr->jnl->jhdr->jhdr_size))) 989 * We assume that there will be a block header and that there will be a 990 * non-negative max_blocks value. 991 * 992 * The 2nd check is the problematic one. We cannot have a journal that's too 993 * small relative to the sector size. max_blocks == (blhdr_size / 16). However, 994 * this only matters where the current block header size is smaller than the current 995 * sector size. So, assume that the blhdr_size == sector size for now. We look 996 * at the condition above to get the rest of the equation -- (journal size / sector size). 997 * Then, it's simple algebra to figure out what the new minimum journal size 998 * should be: 999 * 1000 * (sector_size / 16) > (journal_size / sector_size) 1001 * (sector_size / 16) = (journal_size / sector_size) 1002 * (sector_size / 16) * sector_size = (journal_size / sector_size) * sector_size 1003 * (sector_size / 16) * sector_size = journal_size 1004 * 1005 * This becomes our new _floor_ for the journal_size. 1006 */ 1007 1008 if (dip->physSectorSize != 0) { 1009 min_size = dip->physSectorSize * (dip->physSectorSize / BLOCK_INFO_SIZE); 1010 } 1011 1012 if (gJournalSize != 0) { 1013 1014 /* Was the supplied journal size at least the minimum computed above? */ 1015 if (gJournalSize < min_size) { 1016 printf("%s: journal size %lldk too small. Reset to %dk.\n", 1017 progname, gJournalSize/1024, JOURNAL_DEFAULT_SIZE/1024); 1018 gJournalSize = 0; 1019 1020 } 1021 /* defaults->journalSize will get reset below if it is 0 */ 1022 defaults->journalSize = gJournalSize; 1023 } 1024 1025 if ((gJournalSize == 0) || (defaults->journalSize == 0)) { 1026 UInt32 jscale; 1027 uint32_t target_size; 1028 /* Figure out how many 100's of GBs this filesystem represents */ 1029 jscale = (sectorCount * sectorSize) / ((UInt64)100 * 1024 * 1024 * 1024); 1030 if (jscale > 64) { 1031 jscale = 64; 1032 } 1033 1034 target_size = JOURNAL_DEFAULT_SIZE * (jscale + 1); 1035 /* Is the target size at least the min_size computed above? */ 1036 if (target_size < min_size) { 1037 target_size = min_size; 1038 } 1039 1040 defaults->journalSize = target_size; 1041 } 1042 1043 1044#ifndef DEBUG_BUILD 1045 // volumes that are 128 megs or less in size have such 1046 // a small bitmap (one 4k-block) and inherhently such 1047 // a small btree that we can get by with a much smaller 1048 // journal. even in a worst case scenario of a catalog 1049 // filled with very long korean file names we should 1050 // never touch more than 256k of meta-data for a single 1051 // transaction. therefore we'll make the journal 512k, 1052 // or as small as possible, given the sector size, 1053 // which is safe and doesn't waste much space. 1054 // However, be careful not to let the journal size drop BELOW 1055 // 512k, since the min_size computations can create an artificially 1056 // tiny journal (16k or so) with 512byte sectors. 1057 // 1058 if (sectorCount * sectorSize < 128*1024*1024) { 1059 /* This is a small (<128MB) FS */ 1060 uint32_t small_default = (512 * 1024); 1061 1062 if (small_default <= min_size) { 1063 /* 1064 * If 512k is too small given the sector size, 1065 * then use the larger sector size 1066 */ 1067 defaults->journalSize = min_size; 1068 } 1069 else { 1070 /* 512k was bigger than the min size; we can use it */ 1071 defaults->journalSize = small_default; 1072 } 1073 } 1074#endif 1075 1076 if (defaults->journalSize > 512 * 1024 * 1024) { 1077 defaults->journalSize = 512 * 1024 * 1024; 1078 } 1079 1080 if (defaults->journalSize < defaults->blockSize) { 1081 defaults->journalSize = defaults->blockSize; 1082 } 1083 } 1084 1085 defaults->volumeName = (unsigned char*)gVolumeName; 1086 1087 if (rsrclumpblks == 0) { 1088 if (gBlockSize > DFL_BLKSIZE) 1089 defaults->rsrcClumpSize = ROUNDUP(kHFSPlusRsrcClumpFactor * DFL_BLKSIZE, gBlockSize); 1090 else 1091 defaults->rsrcClumpSize = kHFSPlusRsrcClumpFactor * gBlockSize; 1092 } else 1093 defaults->rsrcClumpSize = clumpsizecalc(rsrclumpblks); 1094 1095 if (datclumpblks == 0) { 1096 if (gBlockSize > DFL_BLKSIZE) 1097 defaults->dataClumpSize = ROUNDUP(kHFSPlusRsrcClumpFactor * DFL_BLKSIZE, gBlockSize); 1098 else 1099 defaults->dataClumpSize = kHFSPlusRsrcClumpFactor * gBlockSize; 1100 } else 1101 defaults->dataClumpSize = clumpsizecalc(datclumpblks); 1102 1103 /* 1104 * The default b-tree node size is 8K. However, if the 1105 * volume is small (< 1 GB) we use 4K instead. 1106 */ 1107 if (!gUserCatNodeSize) { 1108 if ((gBlockSize < HFSOPTIMALBLKSIZE) || 1109 ((UInt64)(sectorCount * sectorSize) < (UInt64)0x40000000)) 1110 catnodesiz = 4096; 1111 } 1112 1113 if (catclumpblks == 0) { 1114 clumpSize = CalcHFSPlusBTreeClumpSize(gBlockSize, catnodesiz, sectorCount, kHFSCatalogFileID); 1115 } 1116 else { 1117 clumpSize = clumpsizecalc(catclumpblks); 1118 1119 if (clumpSize % catnodesiz != 0) 1120 fatal("c=%ld: clump size is not a multiple of node size\n", clumpSize/gBlockSize); 1121 } 1122 defaults->catalogClumpSize = clumpSize; 1123 defaults->catalogNodeSize = catnodesiz; 1124 defaults->catalogExtsCount = catExtCount; 1125 defaults->catalogStartBlock = catExtStart; 1126 1127 if (gBlockSize < 4096 && gBlockSize < catnodesiz) 1128 warnx("Warning: block size %u is less than catalog b-tree node size %u", (unsigned int)gBlockSize, (unsigned int)catnodesiz); 1129 1130 if (extclumpblks == 0) { 1131 clumpSize = CalcHFSPlusBTreeClumpSize(gBlockSize, extnodesiz, sectorCount, kHFSExtentsFileID); 1132 } 1133 else { 1134 clumpSize = clumpsizecalc(extclumpblks); 1135 if (clumpSize % extnodesiz != 0) 1136 fatal("e=%ld: clump size is not a multiple of node size\n", clumpSize/gBlockSize); 1137 } 1138 defaults->extentsClumpSize = clumpSize; 1139 defaults->extentsNodeSize = extnodesiz; 1140 defaults->extentsExtsCount = extExtCount; 1141 defaults->extentsStartBlock = extExtStart; 1142 1143 if (gBlockSize < extnodesiz) 1144 warnx("Warning: block size %u is less than extents b-tree node size %u", (unsigned int)gBlockSize, (unsigned int)extnodesiz); 1145 if (defaults->extentsExtsCount > 8) { 1146 warnx("Warning: extents overflow extent requested count %u exceeds maximum 8, capping at 8\n", defaults->extentsExtsCount); 1147 defaults->extentsExtsCount = 8; 1148 } 1149 if (atrclumpblks == 0) { 1150 if (gUserAttrSize) { 1151 clumpSize = 0; 1152 } 1153 else { 1154 clumpSize = CalcHFSPlusBTreeClumpSize(gBlockSize, atrnodesiz, sectorCount, kHFSAttributesFileID); 1155 } 1156 } 1157 else { 1158 clumpSize = clumpsizecalc(atrclumpblks); 1159 if (clumpSize % atrnodesiz != 0) 1160 fatal("a=%ld: clump size is not a multiple of node size\n", clumpSize/gBlockSize); 1161 } 1162 defaults->attributesClumpSize = clumpSize; 1163 defaults->attributesNodeSize = atrnodesiz; 1164 defaults->attributesExtsCount = attrExtCount; 1165 defaults->attributesStartBlock = attrExtStart; 1166 1167 /* 1168 * Calculate the number of blocks needed for bitmap (rounded up to a multiple of the block size). 1169 */ 1170 1171 /* 1172 * Figure out how many bytes we need for the given totalBlocks 1173 * Note: this minimum value may be too large when it counts the 1174 * space used by the wrapper 1175 */ 1176 totalBlocks = sectorCount / (gBlockSize / sectorSize); 1177 1178 minClumpSize = totalBlocks >> 3; /* convert bits to bytes by dividing by 8 */ 1179 if (totalBlocks & 7) 1180 ++minClumpSize; /* round up to whole bytes */ 1181 1182 /* Round up to a multiple of blockSize */ 1183 if ((oddBitmapBytes = minClumpSize % gBlockSize)) 1184 minClumpSize = minClumpSize - oddBitmapBytes + gBlockSize; 1185 1186 if (bmclumpblks == 0) { 1187 clumpSize = minClumpSize; 1188 } 1189 else { 1190 clumpSize = clumpsizecalc(bmclumpblks); 1191 1192 if (clumpSize < minClumpSize) 1193 fatal("b=%ld: bitmap clump size is too small\n", clumpSize/gBlockSize); 1194 } 1195 defaults->allocationClumpSize = clumpSize; 1196 defaults->allocationExtsCount = blkallocExtCount; 1197 defaults->allocationStartBlock = blkallocExtStart; 1198 1199 defaults->journalInfoBlock = jibStart; 1200 defaults->journalBlock = jnlStart; 1201 defaults->nextAllocBlock = allocStart; 1202 1203 if (gCaseSensitive) 1204 defaults->flags |= kMakeCaseSensitive; 1205 1206 if (gContentProtect) 1207 defaults->flags |= kMakeContentProtect; 1208 1209#ifdef DEBUG_BUILD 1210 if (gProtectLevel) 1211 defaults->protectlevel = gProtectLevel; 1212#endif 1213 1214 if (gNoCreate) { 1215 if (gPartitionSize == 0) 1216 printf("%llu sectors (%u bytes per sector)\n", dip->physTotalSectors, dip->physSectorSize); 1217 printf("HFS Plus format parameters:\n"); 1218 printf("\tvolume name: \"%s\"\n", gVolumeName); 1219 printf("\tblock-size: %u\n", defaults->blockSize); 1220 printf("\ttotal blocks: %u\n", totalBlocks); 1221 if (gJournaled) 1222 printf("\tjournal-size: %uk\n", defaults->journalSize/1024); 1223 printf("\tfirst free catalog node id: %u\n", defaults->nextFreeFileID); 1224 printf("\tcatalog b-tree node size: %u\n", defaults->catalogNodeSize); 1225 printf("\tinitial catalog file size: %u\n", defaults->catalogClumpSize); 1226 printf("\textents b-tree node size: %u\n", defaults->extentsNodeSize); 1227 printf("\tinitial extents file size: %u\n", defaults->extentsClumpSize); 1228 printf("\tattributes b-tree node size: %u\n", defaults->attributesNodeSize); 1229 printf("\tinitial attributes file size: %u\n", defaults->attributesClumpSize); 1230 printf("\tinitial allocation file size: %u (%u blocks)\n", 1231 defaults->allocationClumpSize, defaults->allocationClumpSize / gBlockSize); 1232 printf("\tdata fork clump size: %u\n", defaults->dataClumpSize); 1233 printf("\tresource fork clump size: %u\n", defaults->rsrcClumpSize); 1234 if (defaults->flags & kUseAccessPerms) { 1235 printf("\tuser ID: %d\n", (int)defaults->owner); 1236 printf("\tgroup ID: %d\n", (int)defaults->group); 1237 printf("\taccess mask: %o\n", (int)defaults->mask); 1238 } 1239 printf("\tfile system start block: %u\n", defaults->fsStartBlock); 1240 } 1241} 1242 1243 1244static UInt32 1245clumpsizecalc(UInt32 clumpblocks) 1246{ 1247 UInt64 clumpsize; 1248 1249 clumpsize = (UInt64)clumpblocks * (UInt64)gBlockSize; 1250 1251 if (clumpsize & (UInt64)(0xFFFFFFFF00000000ULL)) 1252 fatal("=%ld: too many blocks for clump size!", clumpblocks); 1253 1254 return ((UInt32)clumpsize); 1255} 1256 1257 1258#define CLUMP_ENTRIES 15 1259 1260short clumptbl[CLUMP_ENTRIES * 3] = { 1261/* 1262 * Volume Attributes Catalog Extents 1263 * Size Clump (MB) Clump (MB) Clump (MB) 1264 */ 1265 /* 1GB */ 4, 4, 4, 1266 /* 2GB */ 6, 6, 4, 1267 /* 4GB */ 8, 8, 4, 1268 /* 8GB */ 11, 11, 5, 1269 /* 1270 * For volumes 16GB and larger, we want to make sure that a full OS 1271 * install won't require fragmentation of the Catalog or Attributes 1272 * B-trees. We do this by making the clump sizes sufficiently large, 1273 * and by leaving a gap after the B-trees for them to grow into. 1274 * 1275 * For SnowLeopard 10A298, a FullNetInstall with all packages selected 1276 * results in: 1277 * Catalog B-tree Header 1278 * nodeSize: 8192 1279 * totalNodes: 31616 1280 * freeNodes: 1978 1281 * (used = 231.55 MB) 1282 * Attributes B-tree Header 1283 * nodeSize: 8192 1284 * totalNodes: 63232 1285 * freeNodes: 958 1286 * (used = 486.52 MB) 1287 * 1288 * We also want Time Machine backup volumes to have a sufficiently 1289 * large clump size to reduce fragmentation. 1290 * 1291 * The series of numbers for Catalog and Attribute form a geometric series. 1292 * For Catalog (16GB to 512GB), each term is 8**(1/5) times the previous 1293 * term. For Attributes (16GB to 512GB), each term is 4**(1/5) times 1294 * the previous term. For 1TB to 16TB, each term is 2**(1/5) times the 1295 * previous term. 1296 */ 1297 /* 16GB */ 64, 32, 5, 1298 /* 32GB */ 84, 49, 6, 1299 /* 64GB */ 111, 74, 7, 1300 /* 128GB */ 147, 111, 8, 1301 /* 256GB */ 194, 169, 9, 1302 /* 512GB */ 256, 256, 11, 1303 /* 1TB */ 294, 294, 14, 1304 /* 2TB */ 338, 338, 16, 1305 /* 4TB */ 388, 388, 20, 1306 /* 8TB */ 446, 446, 25, 1307 /* 16TB */ 512, 512, 32 1308}; 1309 1310/* 1311 * CalcHFSPlusBTreeClumpSize 1312 * 1313 * This routine calculates the file clump size for either 1314 * the catalog file or the extents overflow file. 1315 */ 1316static UInt32 1317CalcHFSPlusBTreeClumpSize(UInt32 blockSize, UInt32 nodeSize, UInt64 sectors, int fileID) 1318{ 1319 UInt32 mod = MAX(nodeSize, blockSize); 1320 UInt32 clumpSize; 1321 int column; 1322 int i; 1323 1324 /* Figure out which column of the above table to use for this file. */ 1325 switch (fileID) { 1326 case kHFSAttributesFileID: 1327 column = 0; 1328 break; 1329 case kHFSCatalogFileID: 1330 column = 1; 1331 break; 1332 default: 1333 column = 2; 1334 break; 1335 } 1336 1337 /* 1338 * The default clump size is 0.8% of the volume size. And 1339 * it must also be a multiple of the node and block size. 1340 */ 1341 if (sectors < 0x200000) { 1342 clumpSize = sectors << 2; /* 0.8 % */ 1343 if (clumpSize < (8 * nodeSize)) 1344 clumpSize = 8 * nodeSize; 1345 } else { 1346 /* 1347 * XXX This should scale more smoothly! 1348 */ 1349 /* turn exponent into table index... */ 1350 for (i = 0, sectors = sectors >> 22; 1351 sectors && (i < CLUMP_ENTRIES-1); 1352 ++i, sectors = sectors >> 1); 1353 1354 clumpSize = clumptbl[column + (i) * 3] * 1024 * 1024; 1355 } 1356 1357 /* 1358 * Round the clump size to a multiple of node and block size. 1359 * NOTE: This rounds down. 1360 */ 1361 clumpSize /= mod; 1362 clumpSize *= mod; 1363 1364 /* 1365 * Rounding down could have rounded down to 0 if the block size was 1366 * greater than the clump size. If so, just use one block or node. 1367 */ 1368 if (clumpSize == 0) 1369 clumpSize = mod; 1370 1371 return (clumpSize); 1372} 1373 1374 1375/* VARARGS */ 1376void 1377#if __STDC__ 1378fatal(const char *fmt, ...) 1379#else 1380fatal(fmt, va_alist) 1381 char *fmt; 1382 va_dcl 1383#endif 1384{ 1385 va_list ap; 1386 1387#if __STDC__ 1388 va_start(ap, fmt); 1389#else 1390 va_start(ap); 1391#endif 1392 if (fcntl(STDERR_FILENO, F_GETFL) < 0) { 1393 openlog(progname, LOG_CONS, LOG_DAEMON); 1394 vsyslog(LOG_ERR, fmt, ap); 1395 closelog(); 1396 } else { 1397 vwarnx(fmt, ap); 1398 } 1399 va_end(ap); 1400 exit(1); 1401 /* NOTREACHED */ 1402} 1403 1404 1405void usage() 1406{ 1407 fprintf(stderr, "usage: %s [-N [partition-size]] [hfsplus-options] special-device\n", progname); 1408 1409 fprintf(stderr, " options:\n"); 1410 fprintf(stderr, "\t-N do not create file system, just print out parameters\n"); 1411 fprintf(stderr, "\t-s use case-sensitive filenames (default is case-insensitive)\n"); 1412 1413 fprintf(stderr, " where hfsplus-options are:\n"); 1414 fprintf(stderr, "\t-J [journal-size] make this HFS+ volume journaled\n"); 1415 fprintf(stderr, "\t-D journal-dev use 'journal-dev' for an external journal\n"); 1416 fprintf(stderr, "\t-G group-id (for root directory)\n"); 1417 fprintf(stderr, "\t-U user-id (for root directory)\n"); 1418 fprintf(stderr, "\t-M octal access-mask (for root directory)\n"); 1419 fprintf(stderr, "\t-b allocation block size (4096 optimal)\n"); 1420 fprintf(stderr, "\t-c clump size list (comma separated)\n"); 1421 fprintf(stderr, "\t\ta=blocks (attributes file)\n"); 1422 fprintf(stderr, "\t\tb=blocks (bitmap file)\n"); 1423 fprintf(stderr, "\t\tc=blocks (catalog file)\n"); 1424 fprintf(stderr, "\t\td=blocks (user data fork)\n"); 1425 fprintf(stderr, "\t\te=blocks (extents file)\n"); 1426 fprintf(stderr, "\t\tr=blocks (user resource fork)\n"); 1427 fprintf(stderr, "\t-i starting catalog node id\n"); 1428 fprintf(stderr, "\t-n b-tree node size list (comma separated)\n"); 1429 fprintf(stderr, "\t\te=size (extents b-tree)\n"); 1430 fprintf(stderr, "\t\tc=size (catalog b-tree)\n"); 1431 fprintf(stderr, "\t\ta=size (attributes b-tree)\n"); 1432 fprintf(stderr, "\t-v volume name (in ascii or UTF-8)\n"); 1433#ifdef DEBUG_BUILD 1434 fprintf(stderr, "\t-E extent count list (comma separated)\n"); 1435 fprintf(stderr, "\t\ta=count (attributes file)\n"); 1436 fprintf(stderr, "\t\tb=count (bitmap file)\n"); 1437 fprintf(stderr, "\t\tc=count (catalog file)\n"); 1438 fprintf(stderr, "\t\te=count (extents file)\n"); 1439 fprintf(stderr, "\t-a <num>[,list] metadata start allocation block, all btrees and journal will be created starting at this allocation block offset\n"); 1440 fprintf(stderr, "\t\tlist is as with -E above, plus:\n"); 1441 fprintf(stderr, "\t\tj=addr (JournalInfoBlock)\n"); 1442 fprintf(stderr, "\t\tJ=addr (Journal)\n"); 1443 fprintf(stderr, "\t\tN=addr (Next Allocation Block)\n"); 1444 fprintf(stderr, "\t\tExample: -a 100,e=200,c=500\n"); 1445#endif 1446 1447 fprintf(stderr, " examples:\n"); 1448 fprintf(stderr, "\t%s -v Untitled /dev/rdisk0s7 \n", progname); 1449 fprintf(stderr, "\t%s -v Untitled -n c=4096,e=1024 /dev/rdisk0s7 \n", progname); 1450 fprintf(stderr, "\t%s -v Untitled -c b=64,c=1024 /dev/rdisk0s7 \n\n", progname); 1451 1452 exit(1); 1453} 1454