2 * Copyright (c) 1999-2011 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
38 #include <sys/ioctl.h>
39 #include <sys/mount.h>
40 #include <sys/param.h>
43 #include <IOKit/storage/IOMediaBSDClient.h>
45 #include <hfs/hfs_format.h>
46 #include "newfs_hfs.h"
56 #define ACCESSMASK (0777)
59 * The maximum HFS volume size is calculated thusly:
61 * The maximum allocation block size (which must be a power of 2 value),
62 * is 2GB, or 2^31 bytes
64 * The maximum number of allocation blocks is 2^32 -1.
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.
71 #define MAXHFSVOLSIZE (0x7FFFFFFF80000000ULL)
73 #define ROUNDUP(x,y) (((x)+(y)-1)/(y)*(y))
75 static void getnodeopts
__P((char* optlist
));
76 static void getclumpopts
__P((char* optlist
));
78 static void getstartopts
__P((char *optlist
));
79 static void getextsopts
__P((char* optlist
));
81 static gid_t a_gid
__P((char *));
82 static uid_t a_uid
__P((char *));
83 static mode_t a_mask
__P((char *));
84 static int hfs_newfs
__P((char *device
));
85 static void validate_hfsplus_block_size
__P((UInt64 sectorCount
, UInt32 sectorSize
));
86 static void hfsplus_params
__P((const DriveInfo
* dip
, hfsparams_t
*defaults
));
87 static UInt32 clumpsizecalc
__P((UInt32 clumpblocks
));
88 static UInt32 CalcHFSPlusBTreeClumpSize
__P((UInt32 blockSize
, UInt32 nodeSize
, UInt64 sectors
, int fileID
));
89 static void usage
__P((void));
90 static int get_high_bit (u_int64_t bitstring
);
91 static int bad_disk_size (u_int64_t numsectors
, u_int64_t sectorsize
);
96 char gVolumeName
[kHFSPlusMaxFileNameChars
+ 1] = {kDefaultVolumeNameStr
};
97 char rawdevice
[MAXPATHLEN
];
98 char blkdevice
[MAXPATHLEN
];
99 uint32_t gBlockSize
= 0;
100 UInt32 gNextCNID
= kHFSFirstUserCatalogNodeID
;
104 int gNoCreate
= FALSE
;
105 int gUserCatNodeSize
= FALSE
;
106 int gCaseSensitive
= FALSE
;
107 int gUserAttrSize
= FALSE
;
108 int gContentProtect
= FALSE
;
110 static UInt32 attrExtCount
= 1, blkallocExtCount
= 1, catExtCount
= 1, extExtCount
= 1;
111 static UInt32 attrExtStart
= 0, blkallocExtStart
= 0, catExtStart
= 0, extExtStart
= 0;
112 static UInt32 jibStart
= 0, jnlStart
= 0, allocStart
= 0;
115 uint16_t gProtectLevel
= 0;
118 #define JOURNAL_DEFAULT_SIZE (8*1024*1024)
119 int gJournaled
= FALSE
;
120 char *gJournalDevice
= NULL
;
121 UInt64 gJournalSize
= 0;
123 uid_t gUserID
= (uid_t
)NOVAL
;
124 gid_t gGroupID
= (gid_t
)NOVAL
;
125 mode_t gModeMask
= (mode_t
)NOVAL
;
127 /* Starting allocation block number for the file system,
128 * all btrees, including journal will be laid down at this
129 * alloation block offset.
131 UInt32 gFSStartBlock
= 0;
133 UInt64 gPartitionSize
= 0;
135 UInt32 catnodesiz
= 8192;
136 UInt32 extnodesiz
= 4096;
137 UInt32 atrnodesiz
= 8192;
139 UInt32 catclumpblks
= 0;
140 UInt32 extclumpblks
= 0;
141 UInt32 atrclumpblks
= 0;
142 UInt32 bmclumpblks
= 0;
143 UInt32 rsrclumpblks
= 0;
144 UInt32 datclumpblks
= 0;
145 uint32_t hfsgrowblks
= 0; /* maximum growable size of wrapper */
154 num
= strtoull(str
, &ptr
, 0);
157 char scale
= tolower(*ptr
);
200 if ((progname
= strrchr(*argv
, '/')))
205 // No semicolon at end of line deliberately!
207 static const char *options
= "G:J:D:M:N:PU:hsb:c:i:n:v:"
213 while ((ch
= getopt(argc
, argv
, options
)) != -1)
216 gGroupID
= a_gid(optarg
);
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
;
229 /* back up because there was no size argument */
235 gJournalDevice
= (char *)optarg
;
240 if (isdigit(optarg
[0])) {
241 gPartitionSize
= get_num(optarg
);
243 /* back up because there was no size argument */
249 gContentProtect
= TRUE
;
254 if (isdigit (optarg
[0])) {
255 uint64_t level
= get_num (optarg
);
256 gProtectLevel
= (uint16_t) level
;
259 /* back up because no level was provided */
266 gModeMask
= a_mask(optarg
);
270 gUserID
= a_uid(optarg
);
275 getstartopts(optarg
);
286 UInt64 tempBlockSize
;
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
;
298 getclumpopts(optarg
);
302 gNextCNID
= atoi(optarg
);
304 * make sure its at least kHFSFirstUserCatalogNodeID
306 if (gNextCNID
< kHFSFirstUserCatalogNodeID
)
307 fatal("%s: starting catalog node id too small (must be > 15)", optarg
);
315 gCaseSensitive
= TRUE
;
320 if ((size_t)n
> (sizeof(gVolumeName
) - 1))
321 fatal("\"%s\" is too long (%d byte maximum)",
322 optarg
, sizeof(gVolumeName
) - 1);
324 fatal("name required with -v option");
325 strlcpy(gVolumeName
, optarg
, sizeof(gVolumeName
));
337 if ((gProtectLevel
) && !(gContentProtect
)) {
338 fatal ("content protection must be specified to set a protection level");
342 if (gPartitionSize
!= 0) {
344 * If we are given -N, a size, and a device, that's a usage error.
349 rawdevice
[0] = blkdevice
[0] = 0;
355 cp
= strrchr(special
, '/');
360 (void) snprintf(rawdevice
, sizeof(rawdevice
), "%sr%s", _PATH_DEV
, special
);
361 (void) snprintf(blkdevice
, sizeof(blkdevice
), "%s%s", _PATH_DEV
, special
);
364 if (gPartitionSize
== 0) {
366 * Check if target device is aready mounted
368 n
= getmntinfo(&mp
, MNT_NOWAIT
);
370 fatal("%s: getmntinfo: %s", blkdevice
, strerror(errno
));
373 if (strcmp(blkdevice
, mp
->f_mntfromname
) == 0)
374 fatal("%s is mounted on %s", blkdevice
, mp
->f_mntonname
);
379 if (hfs_newfs(rawdevice
) < 0) {
380 err(1, "cannot create filesystem on %s", rawdevice
);
387 static void getnodeopts(char* optlist
)
389 char *strp
= optlist
;
394 while((ndarg
= strsep(&strp
, ",")) != NULL
&& *ndarg
!= '\0') {
396 p
= strchr(ndarg
, '=');
404 if (ndsize
< 4096 || ndsize
> 32768 || (ndsize
& (ndsize
-1)) != 0)
405 fatal("%s: invalid catalog b-tree node size", ndarg
);
407 gUserCatNodeSize
= TRUE
;
411 if (ndsize
< 1024 || ndsize
> 32768 || (ndsize
& (ndsize
-1)) != 0)
412 fatal("%s: invalid extents b-tree node size", ndarg
);
417 if (ndsize
< 4096 || ndsize
> 32768 || (ndsize
& (ndsize
-1)) != 0)
418 fatal("%s: invalid atrribute b-tree node size", ndarg
);
429 static void getclumpopts(char* optlist
)
431 char *strp
= optlist
;
436 while((ndarg
= strsep(&strp
, ",")) != NULL
&& *ndarg
!= '\0') {
438 p
= strchr(ndarg
, '=');
442 clpblocks
= atoi(p
+1);
446 atrclumpblks
= clpblocks
;
447 gUserAttrSize
= TRUE
;
450 bmclumpblks
= clpblocks
;
453 catclumpblks
= clpblocks
;
456 datclumpblks
= clpblocks
;
459 extclumpblks
= clpblocks
;
462 rsrclumpblks
= clpblocks
;
472 static void getextsopts(char* optlist
)
474 char *strp
= optlist
;
479 while((ndarg
= strsep(&strp
, ",")) != NULL
&& *ndarg
!= '\0') {
481 p
= strchr(ndarg
, '=');
489 attrExtCount
= numexts
;
492 blkallocExtCount
= numexts
;
495 catExtCount
= numexts
;
498 extExtCount
= numexts
;
506 static void getstartopts(char* optlist
)
511 unsigned long startat
= 0;
513 startat
= strtoul(optlist
, &strp
, 0);
514 if (startat
== ULONG_MAX
&& errno
!= 0) {
515 err(1, "invalid allocation start block string %s", optlist
);
517 if (startat
> UINT_MAX
) {
518 errx(1, "Allocation block %lu larger than max", startat
);
520 if (strp
&& *strp
== ',')
523 gFSStartBlock
= startat
;
525 while((ndarg
= strsep(&strp
, ",")) != NULL
&& *ndarg
!= '\0') {
527 startat
= strtoul(optlist
, NULL
, 0);
528 p
= strchr(ndarg
, '=');
536 attrExtStart
= startat
;
539 blkallocExtStart
= startat
;
542 catExtStart
= startat
;
545 extExtStart
= startat
;
554 allocStart
= startat
;
564 static a_gid(char *s
)
570 if ((gr
= getgrnam(s
)) != NULL
)
573 for (gname
= s
; *s
&& isdigit(*s
); ++s
);
577 errx(1, "unknown group id: %s", gname
);
589 if ((pw
= getpwnam(s
)) != NULL
)
592 for (uname
= s
; *s
&& isdigit(*s
); ++s
);
596 errx(1, "unknown user id: %s", uname
);
609 if (*s
>= '0' && *s
<= '7') {
611 rv
= strtol(s
, &ep
, 8);
613 if (!done
|| rv
< 0 || *ep
)
614 errx(1, "invalid access mask: %s", s
);
619 * Check to see if the volume is too big.
622 * 0 if it is appropriately sized.
623 * 1 if HFS+ cannot be formatted onto the disk.
626 static int bad_disk_size (u_int64_t numsectors
, u_int64_t sectorsize
) {
628 u_int32_t maxSectorBits
= 0;
629 u_int32_t maxSectorSizeBits
= 0;
630 u_int32_t maxBits
= 0;
634 * The essential problem here is that we cannot simply multiply the sector size by the
635 * number of sectors because the product could overflow a 64 bit integer. We do a cursory
636 * check and then a longer check once we know the product will not overflow.
639 maxSectorBits
= get_high_bit (numsectors
);
640 maxSectorSizeBits
= get_high_bit (sectorsize
);
643 * We get the number of bits to represent the number of sectors and the sector size.
644 * Adding the two numbers gives us the number of bits required to represent the product.
645 * If the product is > 63 then it must be too big.
648 maxBits
= maxSectorBits
+ maxSectorSizeBits
;
653 /* Well, now we know that the two values won't overflow. Time to multiply */
654 bytes
= numsectors
* sectorsize
;
656 if (bytes
> MAXHFSVOLSIZE
) {
661 /* Otherwise, it looks good */
667 * The allocation block size must be defined as a power of 2 value, with a floor of
668 * 512 bytes. However, we never default to anything less than 4096 bytes, so that
669 * gives us 20 block size values from 4kb -> 2GB block size.
671 * See inline comments for how this table is used to determine the minimum fs size that
672 * will use a specified allocation block size.
674 * The growth boundary is used to figure out if we need a bigger block size than the
675 * 4 KB default. We get the index of the highest bit set in the FS size, then subtract the
676 * growth boundary to index into the block allocation size array.
678 * Note that 8K appears twice in table since we want to use it for the range 2 TB < 8 TB FS size.
679 * This means that when the 2TB bit or the 4TB bit is the high bit set, we prefer the 8K block size.
681 #define NUM_ALLOC_BLOCKSIZES 21
682 #define GROWTH_BOUNDARY 41
684 u_int64_t alloc_blocksize
[NUM_ALLOC_BLOCKSIZES
] = {
685 /* Block Size*/ /* Min Dflt FS Size */ /* Max FS Size */
686 4096, /* 0 bytes */ /* 16 TB */
687 8192, /* 2 TB */ /* 32 TB */ /* Note that 8K appears twice in table ! */
688 8192, /* 4 TB */ /* 32 TB */ /* Note that 8K appears twice in table ! */
689 16384, /* 8 TB */ /* 64 TB */
690 32768, /* 16 TB */ /* 128 TB */
691 65536, /* 32 TB */ /* 256 TB */
692 131072, /* 64 TB */ /* 512 TB */
693 262144, /* 128 TB */ /* 1 PB */
694 524288, /* 256 TB */ /* 2 PB */
695 1048576, /* 512 TB */ /* 4 PB */
696 2097152, /* 1 PB */ /* 8 PB */
697 4194304, /* 2 PB */ /* 16 PB */
698 8388608, /* 4 PB */ /* 32 PB */
699 16777216, /* 8 PB */ /* 64 PB */
700 33554432, /* 16 PB */ /* 128 PB */
701 67108864, /* 32 PB */ /* 256 PB */
702 134217728, /* 64 PB */ /* 512 PB */
703 268435456, /* 128 PB */ /* 1 EB */
704 536870912, /* 256 PB */ /* 2 EB */
705 1073741824, /* 512 PB */ /* 4 EB */
706 2147483648ULL /* 1 EB */ /* 8 EB */
709 static int get_high_bit (u_int64_t bitstring
) {
710 u_int64_t bits
= bitstring
;
721 * Validate the HFS Plus allocation block size in gBlockSize. If none was
722 * specified, then calculate a suitable default.
724 * Modifies the global variable gBlockSize.
726 static void validate_hfsplus_block_size(UInt64 sectorCount
, UInt32 sectorSize
)
728 if (gBlockSize
== 0) {
730 /* Start by calculating the fs size */
731 u_int64_t fs_size
= sectorCount
* sectorSize
;
734 * Determine the default based on a sliding scale. The maximum number of
735 * allocation blocks is always 4294967295 == (32 bits worth). At 1 bit per
736 * allocation block, that yields 512 MB of bitmap no matter what size we use
737 * for the allocation block.
739 * The general default policy is to allow the filesystem to grow up to 8x the
740 * current maximum size. So for a 1.5TB filesystem, an 8x multiplier would be
741 * 12TB. That means we can use the default size of 4096 bytes. The boundary begins
742 * at 2TB, since at that point, we can no longer use the default 4096 block size to
743 * extend the filesystem by 8x. For a 16KB block size, the max is 64 TB, but the 8x
744 * multiplier begins at 8 TB. Thereafter, we increase for every power of 2 that
745 * the current filesystem size grows.
748 gBlockSize
= DFL_BLKSIZE
; /* Prefer the default of 4K */
750 int bit_index
= get_high_bit (fs_size
);
751 bit_index
-= GROWTH_BOUNDARY
;
754 * After subtracting the GROWTH_BOUNDARY to index into the array, we'll
755 * use the values in the static array if we have a non-negative index.
756 * That means that if the filesystem is >= 1 TB, then we'll use the index
757 * value. At 2TB, we grow to the 8K block size.
759 if ((bit_index
>= 0) && (bit_index
< 22)) {
760 gBlockSize
= alloc_blocksize
[bit_index
];
763 if (bit_index
>= 22) {
764 fatal("Error: Disk Device is too big (%llu sectors, %d bytes per sector", sectorCount
, sectorSize
);
768 /* Make sure a user-specified block size is reasonable */
769 if ((gBlockSize
& (gBlockSize
-1)) != 0) {
770 fatal("%s: bad HFS Plus allocation block size (must be a power of two)", optarg
);
773 if ((sectorCount
/ (gBlockSize
/ sectorSize
)) > 0xFFFFFFFF) {
774 fatal("%s: block size is too small for %lld sectors", optarg
, gBlockSize
, sectorCount
);
777 if (gBlockSize
< HFSOPTIMALBLKSIZE
) {
778 warnx("Warning: %u is a non-optimal block size (4096 would be a better choice)", (unsigned int)gBlockSize
);
783 u_int64_t fs_size
= sectorCount
* sectorSize
;
784 u_int32_t totalBlocks
= fs_size
/gBlockSize
;
786 if (gFSStartBlock
>= totalBlocks
) {
787 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
);
788 warnx("Warning: Resetting file system start block to zero");
797 hfs_newfs(char *device
)
800 DriveInfo dip
= { 0 };
803 hfsparams_t defaults
= {0};
804 UInt64 maxPhysPerIO
= 0;
806 if (gPartitionSize
) {
807 dip
.sectorSize
= kBytesPerSector
;
808 dip
.physTotalSectors
= dip
.totalSectors
= gPartitionSize
/ kBytesPerSector
;
809 dip
.physSectorSize
= kBytesPerSector
; /* 512-byte sectors */
813 fso
= open( device
, O_RDONLY
| O_NDELAY
, 0 );
815 fso
= open( device
, O_RDWR
| O_NDELAY
, 0 );
822 fcntl(fso
, F_NOCACHE
, 1);
825 fatal("%s: %s", device
, strerror(errno
));
827 if (fstat( fso
, &stbuf
) < 0)
828 fatal("%s: %s", device
, strerror(errno
));
830 if (ioctl(fso
, DKIOCGETBLOCKSIZE
, &dip
.physSectorSize
) < 0)
831 fatal("%s: %s", device
, strerror(errno
));
833 if ((dip
.physSectorSize
% kBytesPerSector
) != 0)
834 fatal("%d is an unsupported sector size\n", dip
.physSectorSize
);
836 if (ioctl(fso
, DKIOCGETBLOCKCOUNT
, &dip
.physTotalSectors
) < 0)
837 fatal("%s: %s", device
, strerror(errno
));
841 dip
.physSectorsPerIO
= (1024 * 1024) / dip
.physSectorSize
; /* use 1M as default */
843 if (fso
!= -1 && ioctl(fso
, DKIOCGETMAXBLOCKCOUNTREAD
, &maxPhysPerIO
) < 0)
844 fatal("%s: %s", device
, strerror(errno
));
847 dip
.physSectorsPerIO
= MIN(dip
.physSectorsPerIO
, maxPhysPerIO
);
849 if (fso
!= -1 && ioctl(fso
, DKIOCGETMAXBLOCKCOUNTWRITE
, &maxPhysPerIO
) < 0)
850 fatal("%s: %s", device
, strerror(errno
));
853 dip
.physSectorsPerIO
= MIN(dip
.physSectorsPerIO
, maxPhysPerIO
);
855 if (fso
!= -1 && ioctl(fso
, DKIOCGETMAXBYTECOUNTREAD
, &maxPhysPerIO
) < 0)
856 fatal("%s: %s", device
, strerror(errno
));
859 dip
.physSectorsPerIO
= MIN(dip
.physSectorsPerIO
, maxPhysPerIO
/ dip
.physSectorSize
);
861 if (fso
!= -1 && ioctl(fso
, DKIOCGETMAXBYTECOUNTWRITE
, &maxPhysPerIO
) < 0)
862 fatal("%s: %s", device
, strerror(errno
));
865 dip
.physSectorsPerIO
= MIN(dip
.physSectorsPerIO
, maxPhysPerIO
/ dip
.physSectorSize
);
867 dip
.sectorSize
= kBytesPerSector
;
868 dip
.totalSectors
= dip
.physTotalSectors
* dip
.physSectorSize
/ dip
.sectorSize
;
870 dip
.sectorOffset
= 0;
873 /* Check to see if the disk is too big */
874 u_int64_t secsize
= (u_int64_t
) dip
.sectorSize
;
875 if (bad_disk_size(dip
.totalSectors
, secsize
)) {
876 fatal("%s: partition is too big (maximum is %llu KB)", device
, MAXHFSVOLSIZE
/1024);
880 * If we're going to make an HFS Plus disk (with or without a wrapper), validate the
881 * HFS Plus allocation block size. This will also calculate a default allocation
882 * block size if none (or zero) was specified.
884 validate_hfsplus_block_size(dip
.totalSectors
, dip
.sectorSize
);
886 /* Make an HFS Plus disk */
888 if ((dip
.totalSectors
* dip
.sectorSize
) < kMinHFSPlusVolumeSize
)
889 fatal("%s: partition is too small (minimum is %d KB)", device
, kMinHFSPlusVolumeSize
/1024);
891 hfsplus_params(&dip
, &defaults
);
892 if (gNoCreate
== 0) {
893 retval
= make_hfsplus(&dip
, &defaults
);
895 printf("Initialized %s as a ", device
);
896 if (dip
.totalSectors
> 2048ULL*1024*1024)
898 (long)((dip
.totalSectors
+ (1024ULL*1024*1024))/(2048ULL*1024*1024)));
899 else if (dip
.totalSectors
> 2048*1024)
901 (long)((dip
.totalSectors
+ (1024*1024))/(2048*1024)));
902 else if (dip
.totalSectors
> 2048)
904 (long)((dip
.totalSectors
+ 1024)/2048));
907 (long)((dip
.totalSectors
+ 1)/2));
909 if (gCaseSensitive
) {
910 printf(" case-sensitive");
913 printf(" case-insensitive");
916 printf(" HFS Plus volume with a %uk journal\n",
917 (u_int32_t
)defaults
.journalSize
/1024);
919 printf(" HFS Plus volume\n");
924 fatal("%s: %s", device
, strerror(errno
));
934 typedef struct block_info {
937 _blk_info bi; //64 bit
938 struct buf *bp; //64 bit on K64, 32 bit on K32
940 }__attribute__((__packed__)) block_info;
942 total size == 16 bytes
945 #define BLOCK_INFO_SIZE 16
947 static void hfsplus_params (const DriveInfo
* dip
, hfsparams_t
*defaults
)
949 UInt64 sectorCount
= dip
->totalSectors
;
950 UInt32 sectorSize
= dip
->sectorSize
;
951 uint32_t totalBlocks
;
954 UInt32 oddBitmapBytes
;
957 defaults
->blockSize
= gBlockSize
;
958 defaults
->fsStartBlock
= gFSStartBlock
;
959 defaults
->nextFreeFileID
= gNextCNID
;
960 defaults
->createDate
= createtime
+ MAC_GMT_FACTOR
; /* Mac OS GMT time */
961 defaults
->hfsAlignment
= 0;
962 defaults
->journaledHFS
= gJournaled
;
963 defaults
->journalDevice
= gJournalDevice
;
967 * Always set kUseAccessPerms now; this also
968 * means we have to always have an owner, group,
971 defaults
->owner
= (gUserID
== (uid_t
)NOVAL
) ? geteuid() : gUserID
;
972 defaults
->group
= (gGroupID
== (gid_t
)NOVAL
) ? getegid() : gGroupID
;
973 defaults
->mask
= (gModeMask
== (mode_t
)NOVAL
) ? UMASK
: (gModeMask
& ACCESSMASK
);
974 defaults
->flags
|= kUseAccessPerms
;
977 * We want at least 8 megs of journal for each 100 gigs of
978 * disk space. We cap the size at 512 megs (64x default), unless
979 * the allocation block size is larger, in which case we use one
982 * Only scale if it's the default, otherwise just take what
983 * the user specified, with the caveat below.
986 uint32_t min_size
= 0;
989 * Check to ensure the journal size is not too small relative to the
990 * sector size of the device. This is the check in the kernel:
991 if (tr->blhdr && (tr->blhdr->max_blocks <= 0 ||
992 tr->blhdr->max_blocks > (tr->jnl->jhdr->size/tr->jnl->jhdr->jhdr_size)))
993 * We assume that there will be a block header and that there will be a
994 * non-negative max_blocks value.
996 * The 2nd check is the problematic one. We cannot have a journal that's too
997 * small relative to the sector size. max_blocks == (blhdr_size / 16). However,
998 * this only matters where the current block header size is smaller than the current
999 * sector size. So, assume that the blhdr_size == sector size for now. We look
1000 * at the condition above to get the rest of the equation -- (journal size / sector size).
1001 * Then, it's simple algebra to figure out what the new minimum journal size
1004 * (sector_size / 16) > (journal_size / sector_size)
1005 * (sector_size / 16) = (journal_size / sector_size)
1006 * (sector_size / 16) * sector_size = (journal_size / sector_size) * sector_size
1007 * (sector_size / 16) * sector_size = journal_size
1009 * This becomes our new _floor_ for the journal_size.
1012 if (dip
->physSectorSize
!= 0) {
1013 min_size
= dip
->physSectorSize
* (dip
->physSectorSize
/ BLOCK_INFO_SIZE
);
1016 if (gJournalSize
!= 0) {
1018 /* Was the supplied journal size at least the minimum computed above? */
1019 if (gJournalSize
< min_size
) {
1020 printf("%s: journal size %lldk too small. Reset to %dk.\n",
1021 progname
, gJournalSize
/1024, JOURNAL_DEFAULT_SIZE
/1024);
1025 /* defaults->journalSize will get reset below if it is 0 */
1026 defaults
->journalSize
= gJournalSize
;
1029 if ((gJournalSize
== 0) || (defaults
->journalSize
== 0)) {
1031 uint32_t target_size
;
1032 /* Figure out how many 100's of GBs this filesystem represents */
1033 jscale
= (sectorCount
* sectorSize
) / ((UInt64
)100 * 1024 * 1024 * 1024);
1038 target_size
= JOURNAL_DEFAULT_SIZE
* (jscale
+ 1);
1039 /* Is the target size at least the min_size computed above? */
1040 if (target_size
< min_size
) {
1041 target_size
= min_size
;
1044 defaults
->journalSize
= target_size
;
1049 // volumes that are 128 megs or less in size have such
1050 // a small bitmap (one 4k-block) and inherhently such
1051 // a small btree that we can get by with a much smaller
1052 // journal. even in a worst case scenario of a catalog
1053 // filled with very long korean file names we should
1054 // never touch more than 256k of meta-data for a single
1055 // transaction. therefore we'll make the journal 512k,
1056 // or as small as possible, given the sector size,
1057 // which is safe and doesn't waste much space.
1058 // However, be careful not to let the journal size drop BELOW
1059 // 512k, since the min_size computations can create an artificially
1060 // tiny journal (16k or so) with 512byte sectors.
1062 if (sectorCount
* sectorSize
< 128*1024*1024) {
1063 /* This is a small (<128MB) FS */
1064 uint32_t small_default
= (512 * 1024);
1066 if (small_default
<= min_size
) {
1068 * If 512k is too small given the sector size,
1069 * then use the larger sector size
1071 defaults
->journalSize
= min_size
;
1074 /* 512k was bigger than the min size; we can use it */
1075 defaults
->journalSize
= small_default
;
1080 if (defaults
->journalSize
> 512 * 1024 * 1024) {
1081 defaults
->journalSize
= 512 * 1024 * 1024;
1084 if (defaults
->journalSize
< defaults
->blockSize
) {
1085 defaults
->journalSize
= defaults
->blockSize
;
1089 strncpy((char *)defaults
->volumeName
, gVolumeName
, sizeof(defaults
->volumeName
) - 1);
1090 defaults
->volumeName
[sizeof(defaults
->volumeName
) - 1] = '\0';
1092 if (rsrclumpblks
== 0) {
1093 if (gBlockSize
> DFL_BLKSIZE
)
1094 defaults
->rsrcClumpSize
= ROUNDUP(kHFSPlusRsrcClumpFactor
* DFL_BLKSIZE
, gBlockSize
);
1096 defaults
->rsrcClumpSize
= kHFSPlusRsrcClumpFactor
* gBlockSize
;
1098 defaults
->rsrcClumpSize
= clumpsizecalc(rsrclumpblks
);
1100 if (datclumpblks
== 0) {
1101 if (gBlockSize
> DFL_BLKSIZE
)
1102 defaults
->dataClumpSize
= ROUNDUP(kHFSPlusRsrcClumpFactor
* DFL_BLKSIZE
, gBlockSize
);
1104 defaults
->dataClumpSize
= kHFSPlusRsrcClumpFactor
* gBlockSize
;
1106 defaults
->dataClumpSize
= clumpsizecalc(datclumpblks
);
1109 * The default b-tree node size is 8K. However, if the
1110 * volume is small (< 1 GB) we use 4K instead.
1112 if (!gUserCatNodeSize
) {
1113 if ((gBlockSize
< HFSOPTIMALBLKSIZE
) ||
1114 ((UInt64
)(sectorCount
* sectorSize
) < (UInt64
)0x40000000))
1118 if (catclumpblks
== 0) {
1119 clumpSize
= CalcHFSPlusBTreeClumpSize(gBlockSize
, catnodesiz
, sectorCount
, kHFSCatalogFileID
);
1122 clumpSize
= clumpsizecalc(catclumpblks
);
1124 if (clumpSize
% catnodesiz
!= 0)
1125 fatal("c=%ld: clump size is not a multiple of node size\n", clumpSize
/gBlockSize
);
1127 defaults
->catalogClumpSize
= clumpSize
;
1128 defaults
->catalogNodeSize
= catnodesiz
;
1129 defaults
->catalogExtsCount
= catExtCount
;
1130 defaults
->catalogStartBlock
= catExtStart
;
1132 if (gBlockSize
< 4096 && gBlockSize
< catnodesiz
)
1133 warnx("Warning: block size %u is less than catalog b-tree node size %u", (unsigned int)gBlockSize
, (unsigned int)catnodesiz
);
1135 if (extclumpblks
== 0) {
1136 clumpSize
= CalcHFSPlusBTreeClumpSize(gBlockSize
, extnodesiz
, sectorCount
, kHFSExtentsFileID
);
1139 clumpSize
= clumpsizecalc(extclumpblks
);
1140 if (clumpSize
% extnodesiz
!= 0)
1141 fatal("e=%ld: clump size is not a multiple of node size\n", clumpSize
/gBlockSize
);
1143 defaults
->extentsClumpSize
= clumpSize
;
1144 defaults
->extentsNodeSize
= extnodesiz
;
1145 defaults
->extentsExtsCount
= extExtCount
;
1146 defaults
->extentsStartBlock
= extExtStart
;
1148 if (gBlockSize
< extnodesiz
)
1149 warnx("Warning: block size %u is less than extents b-tree node size %u", (unsigned int)gBlockSize
, (unsigned int)extnodesiz
);
1150 if (defaults
->extentsExtsCount
> 8) {
1151 warnx("Warning: extents overflow extent requested count %u exceeds maximum 8, capping at 8\n", defaults
->extentsExtsCount
);
1152 defaults
->extentsExtsCount
= 8;
1154 if (atrclumpblks
== 0) {
1155 if (gUserAttrSize
) {
1159 clumpSize
= CalcHFSPlusBTreeClumpSize(gBlockSize
, atrnodesiz
, sectorCount
, kHFSAttributesFileID
);
1163 clumpSize
= clumpsizecalc(atrclumpblks
);
1164 if (clumpSize
% atrnodesiz
!= 0)
1165 fatal("a=%ld: clump size is not a multiple of node size\n", clumpSize
/gBlockSize
);
1167 defaults
->attributesClumpSize
= clumpSize
;
1168 defaults
->attributesNodeSize
= atrnodesiz
;
1169 defaults
->attributesExtsCount
= attrExtCount
;
1170 defaults
->attributesStartBlock
= attrExtStart
;
1173 * Calculate the number of blocks needed for bitmap (rounded up to a multiple of the block size).
1177 * Figure out how many bytes we need for the given totalBlocks
1178 * Note: this minimum value may be too large when it counts the
1179 * space used by the wrapper
1181 totalBlocks
= sectorCount
/ (gBlockSize
/ sectorSize
);
1183 minClumpSize
= totalBlocks
>> 3; /* convert bits to bytes by dividing by 8 */
1184 if (totalBlocks
& 7)
1185 ++minClumpSize
; /* round up to whole bytes */
1187 /* Round up to a multiple of blockSize */
1188 if ((oddBitmapBytes
= minClumpSize
% gBlockSize
))
1189 minClumpSize
= minClumpSize
- oddBitmapBytes
+ gBlockSize
;
1191 if (bmclumpblks
== 0) {
1192 clumpSize
= minClumpSize
;
1195 clumpSize
= clumpsizecalc(bmclumpblks
);
1197 if (clumpSize
< minClumpSize
)
1198 fatal("b=%ld: bitmap clump size is too small\n", clumpSize
/gBlockSize
);
1200 defaults
->allocationClumpSize
= clumpSize
;
1201 defaults
->allocationExtsCount
= blkallocExtCount
;
1202 defaults
->allocationStartBlock
= blkallocExtStart
;
1204 defaults
->journalInfoBlock
= jibStart
;
1205 defaults
->journalBlock
= jnlStart
;
1206 defaults
->nextAllocBlock
= allocStart
;
1209 defaults
->flags
|= kMakeCaseSensitive
;
1211 if (gContentProtect
)
1212 defaults
->flags
|= kMakeContentProtect
;
1216 defaults
->protectlevel
= gProtectLevel
;
1220 if (gPartitionSize
== 0)
1221 printf("%llu sectors (%u bytes per sector)\n", dip
->physTotalSectors
, dip
->physSectorSize
);
1222 printf("HFS Plus format parameters:\n");
1223 printf("\tvolume name: \"%s\"\n", gVolumeName
);
1224 printf("\tblock-size: %u\n", defaults
->blockSize
);
1225 printf("\ttotal blocks: %u\n", totalBlocks
);
1227 printf("\tjournal-size: %uk\n", defaults
->journalSize
/1024);
1228 printf("\tfirst free catalog node id: %u\n", defaults
->nextFreeFileID
);
1229 printf("\tcatalog b-tree node size: %u\n", defaults
->catalogNodeSize
);
1230 printf("\tinitial catalog file size: %u\n", defaults
->catalogClumpSize
);
1231 printf("\textents b-tree node size: %u\n", defaults
->extentsNodeSize
);
1232 printf("\tinitial extents file size: %u\n", defaults
->extentsClumpSize
);
1233 printf("\tattributes b-tree node size: %u\n", defaults
->attributesNodeSize
);
1234 printf("\tinitial attributes file size: %u\n", defaults
->attributesClumpSize
);
1235 printf("\tinitial allocation file size: %u (%u blocks)\n",
1236 defaults
->allocationClumpSize
, defaults
->allocationClumpSize
/ gBlockSize
);
1237 printf("\tdata fork clump size: %u\n", defaults
->dataClumpSize
);
1238 printf("\tresource fork clump size: %u\n", defaults
->rsrcClumpSize
);
1239 if (defaults
->flags
& kUseAccessPerms
) {
1240 printf("\tuser ID: %d\n", (int)defaults
->owner
);
1241 printf("\tgroup ID: %d\n", (int)defaults
->group
);
1242 printf("\taccess mask: %o\n", (int)defaults
->mask
);
1244 printf("\tfile system start block: %u\n", defaults
->fsStartBlock
);
1250 clumpsizecalc(UInt32 clumpblocks
)
1254 clumpsize
= (UInt64
)clumpblocks
* (UInt64
)gBlockSize
;
1256 if (clumpsize
& (UInt64
)(0xFFFFFFFF00000000ULL
))
1257 fatal("=%ld: too many blocks for clump size!", clumpblocks
);
1259 return ((UInt32
)clumpsize
);
1263 #define CLUMP_ENTRIES 15
1265 short clumptbl
[CLUMP_ENTRIES
* 3] = {
1267 * Volume Attributes Catalog Extents
1268 * Size Clump (MB) Clump (MB) Clump (MB)
1273 /* 8GB */ 11, 11, 5,
1275 * For volumes 16GB and larger, we want to make sure that a full OS
1276 * install won't require fragmentation of the Catalog or Attributes
1277 * B-trees. We do this by making the clump sizes sufficiently large,
1278 * and by leaving a gap after the B-trees for them to grow into.
1280 * For SnowLeopard 10A298, a FullNetInstall with all packages selected
1282 * Catalog B-tree Header
1286 * (used = 231.55 MB)
1287 * Attributes B-tree Header
1291 * (used = 486.52 MB)
1293 * We also want Time Machine backup volumes to have a sufficiently
1294 * large clump size to reduce fragmentation.
1296 * The series of numbers for Catalog and Attribute form a geometric series.
1297 * For Catalog (16GB to 512GB), each term is 8**(1/5) times the previous
1298 * term. For Attributes (16GB to 512GB), each term is 4**(1/5) times
1299 * the previous term. For 1TB to 16TB, each term is 2**(1/5) times the
1302 /* 16GB */ 64, 32, 5,
1303 /* 32GB */ 84, 49, 6,
1304 /* 64GB */ 111, 74, 7,
1305 /* 128GB */ 147, 111, 8,
1306 /* 256GB */ 194, 169, 9,
1307 /* 512GB */ 256, 256, 11,
1308 /* 1TB */ 294, 294, 14,
1309 /* 2TB */ 338, 338, 16,
1310 /* 4TB */ 388, 388, 20,
1311 /* 8TB */ 446, 446, 25,
1312 /* 16TB */ 512, 512, 32
1316 * CalcHFSPlusBTreeClumpSize
1318 * This routine calculates the file clump size for either
1319 * the catalog file or the extents overflow file.
1322 CalcHFSPlusBTreeClumpSize(UInt32 blockSize
, UInt32 nodeSize
, UInt64 sectors
, int fileID
)
1324 UInt32 mod
= MAX(nodeSize
, blockSize
);
1329 /* Figure out which column of the above table to use for this file. */
1331 case kHFSAttributesFileID
:
1334 case kHFSCatalogFileID
:
1343 * The default clump size is 0.8% of the volume size. And
1344 * it must also be a multiple of the node and block size.
1346 if (sectors
< 0x200000) {
1347 clumpSize
= sectors
<< 2; /* 0.8 % */
1348 if (clumpSize
< (8 * nodeSize
))
1349 clumpSize
= 8 * nodeSize
;
1352 * XXX This should scale more smoothly!
1354 /* turn exponent into table index... */
1355 for (i
= 0, sectors
= sectors
>> 22;
1356 sectors
&& (i
< CLUMP_ENTRIES
-1);
1357 ++i
, sectors
= sectors
>> 1);
1359 clumpSize
= clumptbl
[column
+ (i
) * 3] * 1024 * 1024;
1363 * Round the clump size to a multiple of node and block size.
1364 * NOTE: This rounds down.
1370 * Rounding down could have rounded down to 0 if the block size was
1371 * greater than the clump size. If so, just use one block or node.
1383 fatal(const char *fmt
, ...)
1385 fatal(fmt
, va_alist
)
1397 if (fcntl(STDERR_FILENO
, F_GETFL
) < 0) {
1398 openlog(progname
, LOG_CONS
, LOG_DAEMON
);
1399 vsyslog(LOG_ERR
, fmt
, ap
);
1412 fprintf(stderr
, "usage: %s [-N [partition-size]] [hfsplus-options] special-device\n", progname
);
1414 fprintf(stderr
, " options:\n");
1415 fprintf(stderr
, "\t-N do not create file system, just print out parameters\n");
1416 fprintf(stderr
, "\t-s use case-sensitive filenames (default is case-insensitive)\n");
1418 fprintf(stderr
, " where hfsplus-options are:\n");
1419 fprintf(stderr
, "\t-J [journal-size] make this HFS+ volume journaled\n");
1420 fprintf(stderr
, "\t-D journal-dev use 'journal-dev' for an external journal\n");
1421 fprintf(stderr
, "\t-G group-id (for root directory)\n");
1422 fprintf(stderr
, "\t-U user-id (for root directory)\n");
1423 fprintf(stderr
, "\t-M octal access-mask (for root directory)\n");
1424 fprintf(stderr
, "\t-b allocation block size (4096 optimal)\n");
1425 fprintf(stderr
, "\t-c clump size list (comma separated)\n");
1426 fprintf(stderr
, "\t\ta=blocks (attributes file)\n");
1427 fprintf(stderr
, "\t\tb=blocks (bitmap file)\n");
1428 fprintf(stderr
, "\t\tc=blocks (catalog file)\n");
1429 fprintf(stderr
, "\t\td=blocks (user data fork)\n");
1430 fprintf(stderr
, "\t\te=blocks (extents file)\n");
1431 fprintf(stderr
, "\t\tr=blocks (user resource fork)\n");
1432 fprintf(stderr
, "\t-i starting catalog node id\n");
1433 fprintf(stderr
, "\t-n b-tree node size list (comma separated)\n");
1434 fprintf(stderr
, "\t\te=size (extents b-tree)\n");
1435 fprintf(stderr
, "\t\tc=size (catalog b-tree)\n");
1436 fprintf(stderr
, "\t\ta=size (attributes b-tree)\n");
1437 fprintf(stderr
, "\t-v volume name (in ascii or UTF-8)\n");
1439 fprintf(stderr
, "\t-E extent count list (comma separated)\n");
1440 fprintf(stderr
, "\t\ta=count (attributes file)\n");
1441 fprintf(stderr
, "\t\tb=count (bitmap file)\n");
1442 fprintf(stderr
, "\t\tc=count (catalog file)\n");
1443 fprintf(stderr
, "\t\te=count (extents file)\n");
1444 fprintf(stderr
, "\t-a <num>[,list] metadata start allocation block, all btrees and journal will be created starting at this allocation block offset\n");
1445 fprintf(stderr
, "\t\tlist is as with -E above, plus:\n");
1446 fprintf(stderr
, "\t\tj=addr (JournalInfoBlock)\n");
1447 fprintf(stderr
, "\t\tJ=addr (Journal)\n");
1448 fprintf(stderr
, "\t\tN=addr (Next Allocation Block)\n");
1449 fprintf(stderr
, "\t\tExample: -a 100,e=200,c=500\n");
1452 fprintf(stderr
, " examples:\n");
1453 fprintf(stderr
, "\t%s -v Untitled /dev/rdisk0s7 \n", progname
);
1454 fprintf(stderr
, "\t%s -v Untitled -n c=4096,e=1024 /dev/rdisk0s7 \n", progname
);
1455 fprintf(stderr
, "\t%s -v Untitled -c b=64,c=1024 /dev/rdisk0s7 \n\n", progname
);