]> git.saurik.com Git - apple/hfs.git/blob - newfs_hfs/newfs_hfs.c
hfs-226.1.1.tar.gz
[apple/hfs.git] / newfs_hfs / newfs_hfs.c
1 /*
2 * Copyright (c) 1999-2011 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
75 static void getnodeopts __P((char* optlist));
76 static void getclumpopts __P((char* optlist));
77 #ifdef DEBUG_BUILD
78 static void getstartopts __P((char *optlist));
79 static void getextsopts __P((char* optlist));
80 #endif
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);
92
93
94
95 char *progname;
96 char gVolumeName[kHFSPlusMaxFileNameChars + 1] = {kDefaultVolumeNameStr};
97 char rawdevice[MAXPATHLEN];
98 char blkdevice[MAXPATHLEN];
99 uint32_t gBlockSize = 0;
100 UInt32 gNextCNID = kHFSFirstUserCatalogNodeID;
101
102 time_t createtime;
103
104 int gNoCreate = FALSE;
105 int gUserCatNodeSize = FALSE;
106 int gCaseSensitive = FALSE;
107 int gUserAttrSize = FALSE;
108 int gContentProtect = FALSE;
109
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;
113
114 #ifdef DEBUG_BUILD
115 uint16_t gProtectLevel = 0;
116 #endif
117
118 #define JOURNAL_DEFAULT_SIZE (8*1024*1024)
119 int gJournaled = FALSE;
120 char *gJournalDevice = NULL;
121 UInt64 gJournalSize = 0;
122
123 uid_t gUserID = (uid_t)NOVAL;
124 gid_t gGroupID = (gid_t)NOVAL;
125 mode_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 */
131 UInt32 gFSStartBlock = 0;
132
133 UInt64 gPartitionSize = 0;
134
135 UInt32 catnodesiz = 8192;
136 UInt32 extnodesiz = 4096;
137 UInt32 atrnodesiz = 8192;
138
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 */
146
147
148 UInt64
149 get_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
188 int
189 main(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 n = strlen(optarg);
320 if ((size_t)n > (sizeof(gVolumeName) - 1))
321 fatal("\"%s\" is too long (%d byte maximum)",
322 optarg, sizeof(gVolumeName) - 1);
323 if (n == 0)
324 fatal("name required with -v option");
325 strlcpy(gVolumeName, optarg, sizeof(gVolumeName));
326 break;
327
328 case '?':
329 default:
330 usage();
331 }
332
333 argc -= optind;
334 argv += optind;
335
336 #ifdef DEBUG_BUILD
337 if ((gProtectLevel) && !(gContentProtect)) {
338 fatal ("content protection must be specified to set a protection level");
339 }
340 #endif
341
342 if (gPartitionSize != 0) {
343 /*
344 * If we are given -N, a size, and a device, that's a usage error.
345 */
346 if (argc != 0)
347 usage();
348
349 rawdevice[0] = blkdevice[0] = 0;
350 } else {
351 if (argc != 1)
352 usage();
353
354 special = argv[0];
355 cp = strrchr(special, '/');
356 if (cp != 0)
357 special = cp + 1;
358 if (*special == 'r')
359 special++;
360 (void) snprintf(rawdevice, sizeof(rawdevice), "%sr%s", _PATH_DEV, special);
361 (void) snprintf(blkdevice, sizeof(blkdevice), "%s%s", _PATH_DEV, special);
362 }
363
364 if (gPartitionSize == 0) {
365 /*
366 * Check if target device is aready mounted
367 */
368 n = getmntinfo(&mp, MNT_NOWAIT);
369 if (n == 0)
370 fatal("%s: getmntinfo: %s", blkdevice, strerror(errno));
371
372 while (--n >= 0) {
373 if (strcmp(blkdevice, mp->f_mntfromname) == 0)
374 fatal("%s is mounted on %s", blkdevice, mp->f_mntonname);
375 ++mp;
376 }
377 }
378
379 if (hfs_newfs(rawdevice) < 0) {
380 err(1, "cannot create filesystem on %s", rawdevice);
381 }
382
383 exit(0);
384 }
385
386
387 static void getnodeopts(char* optlist)
388 {
389 char *strp = optlist;
390 char *ndarg;
391 char *p;
392 UInt32 ndsize;
393
394 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') {
395
396 p = strchr(ndarg, '=');
397 if (p == NULL)
398 usage();
399
400 ndsize = atoi(p+1);
401
402 switch (*ndarg) {
403 case 'c':
404 if (ndsize < 4096 || ndsize > 32768 || (ndsize & (ndsize-1)) != 0)
405 fatal("%s: invalid catalog b-tree node size", ndarg);
406 catnodesiz = ndsize;
407 gUserCatNodeSize = TRUE;
408 break;
409
410 case 'e':
411 if (ndsize < 1024 || ndsize > 32768 || (ndsize & (ndsize-1)) != 0)
412 fatal("%s: invalid extents b-tree node size", ndarg);
413 extnodesiz = ndsize;
414 break;
415
416 case 'a':
417 if (ndsize < 4096 || ndsize > 32768 || (ndsize & (ndsize-1)) != 0)
418 fatal("%s: invalid atrribute b-tree node size", ndarg);
419 atrnodesiz = ndsize;
420 break;
421
422 default:
423 usage();
424 }
425 }
426 }
427
428
429 static void getclumpopts(char* optlist)
430 {
431 char *strp = optlist;
432 char *ndarg;
433 char *p;
434 UInt32 clpblocks;
435
436 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') {
437
438 p = strchr(ndarg, '=');
439 if (p == NULL)
440 usage();
441
442 clpblocks = atoi(p+1);
443
444 switch (*ndarg) {
445 case 'a':
446 atrclumpblks = clpblocks;
447 gUserAttrSize = TRUE;
448 break;
449 case 'b':
450 bmclumpblks = clpblocks;
451 break;
452 case 'c':
453 catclumpblks = clpblocks;
454 break;
455 case 'd':
456 datclumpblks = clpblocks;
457 break;
458 case 'e':
459 extclumpblks = clpblocks;
460 break;
461 case 'r':
462 rsrclumpblks = clpblocks;
463 break;
464
465 default:
466 usage();
467 }
468 }
469 }
470
471 #ifdef DEBUG_BUILD
472 static void getextsopts(char* optlist)
473 {
474 char *strp = optlist;
475 char *ndarg;
476 char *p;
477 UInt32 numexts;
478
479 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') {
480
481 p = strchr(ndarg, '=');
482 if (p == NULL)
483 usage();
484
485 numexts = atoi(p+1);
486
487 switch (*ndarg) {
488 case 'a':
489 attrExtCount = numexts;
490 break;
491 case 'b':
492 blkallocExtCount = numexts;
493 break;
494 case 'c':
495 catExtCount = numexts;
496 break;
497 case 'e':
498 extExtCount = numexts;
499 break;
500 default:
501 usage();
502 }
503 }
504 }
505
506 static void getstartopts(char* optlist)
507 {
508 char *strp;
509 char *ndarg;
510 char *p;
511 unsigned long startat = 0;
512
513 startat = strtoul(optlist, &strp, 0);
514 if (startat == ULONG_MAX && errno != 0) {
515 err(1, "invalid allocation start block string %s", optlist);
516 }
517 if (startat > UINT_MAX) {
518 errx(1, "Allocation block %lu larger than max", startat);
519 }
520 if (strp && *strp == ',')
521 strp++;
522
523 gFSStartBlock = startat;
524
525 while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') {
526
527 startat = strtoul(optlist, NULL, 0);
528 p = strchr(ndarg, '=');
529 if (p == NULL)
530 usage();
531
532 startat = atoi(p+1);
533
534 switch (*ndarg) {
535 case 'a':
536 attrExtStart = startat;
537 break;
538 case 'b':
539 blkallocExtStart = startat;
540 break;
541 case 'c':
542 catExtStart = startat;
543 break;
544 case 'e':
545 extExtStart = startat;
546 break;
547 case 'j':
548 jibStart = startat;
549 break;
550 case 'J':
551 jnlStart = startat;
552 break;
553 case 'N':
554 allocStart = startat;
555 break;
556 default:
557 usage();
558 }
559 }
560 }
561 #endif
562
563 gid_t
564 static a_gid(char *s)
565 {
566 struct group *gr;
567 char *gname;
568 gid_t gid = 0;
569
570 if ((gr = getgrnam(s)) != NULL)
571 gid = gr->gr_gid;
572 else {
573 for (gname = s; *s && isdigit(*s); ++s);
574 if (!*s)
575 gid = atoi(gname);
576 else
577 errx(1, "unknown group id: %s", gname);
578 }
579 return (gid);
580 }
581
582 static uid_t
583 a_uid(char *s)
584 {
585 struct passwd *pw;
586 char *uname;
587 uid_t uid = 0;
588
589 if ((pw = getpwnam(s)) != NULL)
590 uid = pw->pw_uid;
591 else {
592 for (uname = s; *s && isdigit(*s); ++s);
593 if (!*s)
594 uid = atoi(uname);
595 else
596 errx(1, "unknown user id: %s", uname);
597 }
598 return (uid);
599 }
600
601 static mode_t
602 a_mask(char *s)
603 {
604 int done, rv;
605 char *ep;
606
607 done = 0;
608 rv = -1;
609 if (*s >= '0' && *s <= '7') {
610 done = 1;
611 rv = strtol(s, &ep, 8);
612 }
613 if (!done || rv < 0 || *ep)
614 errx(1, "invalid access mask: %s", s);
615 return (rv);
616 }
617
618 /*
619 * Check to see if the volume is too big.
620 *
621 * Returns:
622 * 0 if it is appropriately sized.
623 * 1 if HFS+ cannot be formatted onto the disk.
624 */
625
626 static int bad_disk_size (u_int64_t numsectors, u_int64_t sectorsize) {
627
628 u_int32_t maxSectorBits = 0;
629 u_int32_t maxSectorSizeBits = 0;
630 u_int32_t maxBits = 0;
631 u_int64_t bytes;
632
633 /*
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.
637 */
638
639 maxSectorBits = get_high_bit (numsectors);
640 maxSectorSizeBits = get_high_bit (sectorsize);
641
642 /*
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.
646 */
647
648 maxBits = maxSectorBits + maxSectorSizeBits;
649 if (maxBits > 63) {
650 return 1;
651 }
652
653 /* Well, now we know that the two values won't overflow. Time to multiply */
654 bytes = numsectors * sectorsize;
655
656 if (bytes > MAXHFSVOLSIZE) {
657 /* Too big! */
658 return 1;
659 }
660
661 /* Otherwise, it looks good */
662 return 0;
663
664 }
665
666 /*
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.
670 *
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.
673 *
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.
677 *
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.
680 */
681 #define NUM_ALLOC_BLOCKSIZES 21
682 #define GROWTH_BOUNDARY 41
683
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 */
707 };
708
709 static int get_high_bit (u_int64_t bitstring) {
710 u_int64_t bits = bitstring;
711 int counter = 0;
712 while (bits) {
713 bits = (bits >> 1);
714 counter++;
715 }
716 return counter;
717 }
718
719
720 /*
721 * Validate the HFS Plus allocation block size in gBlockSize. If none was
722 * specified, then calculate a suitable default.
723 *
724 * Modifies the global variable gBlockSize.
725 */
726 static void validate_hfsplus_block_size(UInt64 sectorCount, UInt32 sectorSize)
727 {
728 if (gBlockSize == 0) {
729
730 /* Start by calculating the fs size */
731 u_int64_t fs_size = sectorCount * sectorSize;
732
733 /*
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.
738 *
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.
746 */
747
748 gBlockSize = DFL_BLKSIZE; /* Prefer the default of 4K */
749
750 int bit_index = get_high_bit (fs_size);
751 bit_index -= GROWTH_BOUNDARY;
752
753 /*
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.
758 */
759 if ((bit_index >= 0) && (bit_index < 22)) {
760 gBlockSize = alloc_blocksize[bit_index];
761 }
762
763 if (bit_index >= 22) {
764 fatal("Error: Disk Device is too big (%llu sectors, %d bytes per sector", sectorCount, sectorSize);
765 }
766 }
767 else {
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);
771 }
772
773 if ((sectorCount / (gBlockSize / sectorSize)) > 0xFFFFFFFF) {
774 fatal("%s: block size is too small for %lld sectors", optarg, gBlockSize, sectorCount);
775 }
776
777 if (gBlockSize < HFSOPTIMALBLKSIZE) {
778 warnx("Warning: %u is a non-optimal block size (4096 would be a better choice)", (unsigned int)gBlockSize);
779 }
780 }
781
782 if (gFSStartBlock) {
783 u_int64_t fs_size = sectorCount * sectorSize;
784 u_int32_t totalBlocks = fs_size/gBlockSize;
785
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");
789 gFSStartBlock = 0;
790 }
791 }
792 }
793
794
795
796 static int
797 hfs_newfs(char *device)
798 {
799 struct stat stbuf;
800 DriveInfo dip = { 0 };
801 int fso = -1;
802 int retval = 0;
803 hfsparams_t defaults = {0};
804 UInt64 maxPhysPerIO = 0;
805
806 if (gPartitionSize) {
807 dip.sectorSize = kBytesPerSector;
808 dip.physTotalSectors = dip.totalSectors = gPartitionSize / kBytesPerSector;
809 dip.physSectorSize = kBytesPerSector; /* 512-byte sectors */
810 dip.fd = 0;
811 } else {
812 if (gNoCreate) {
813 fso = open( device, O_RDONLY | O_NDELAY, 0 );
814 } else {
815 fso = open( device, O_RDWR | O_NDELAY, 0 );
816 }
817 if (fso == -1) {
818 return -1;
819 }
820
821 dip.fd = fso;
822 fcntl(fso, F_NOCACHE, 1);
823
824 if (fso < 0)
825 fatal("%s: %s", device, strerror(errno));
826
827 if (fstat( fso, &stbuf) < 0)
828 fatal("%s: %s", device, strerror(errno));
829
830 if (ioctl(fso, DKIOCGETBLOCKSIZE, &dip.physSectorSize) < 0)
831 fatal("%s: %s", device, strerror(errno));
832
833 if ((dip.physSectorSize % kBytesPerSector) != 0)
834 fatal("%d is an unsupported sector size\n", dip.physSectorSize);
835
836 if (ioctl(fso, DKIOCGETBLOCKCOUNT, &dip.physTotalSectors) < 0)
837 fatal("%s: %s", device, strerror(errno));
838
839 }
840
841 dip.physSectorsPerIO = (1024 * 1024) / dip.physSectorSize; /* use 1M as default */
842
843 if (fso != -1 && ioctl(fso, DKIOCGETMAXBLOCKCOUNTREAD, &maxPhysPerIO) < 0)
844 fatal("%s: %s", device, strerror(errno));
845
846 if (maxPhysPerIO)
847 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO);
848
849 if (fso != -1 && ioctl(fso, DKIOCGETMAXBLOCKCOUNTWRITE, &maxPhysPerIO) < 0)
850 fatal("%s: %s", device, strerror(errno));
851
852 if (maxPhysPerIO)
853 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO);
854
855 if (fso != -1 && ioctl(fso, DKIOCGETMAXBYTECOUNTREAD, &maxPhysPerIO) < 0)
856 fatal("%s: %s", device, strerror(errno));
857
858 if (maxPhysPerIO)
859 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO / dip.physSectorSize);
860
861 if (fso != -1 && ioctl(fso, DKIOCGETMAXBYTECOUNTWRITE, &maxPhysPerIO) < 0)
862 fatal("%s: %s", device, strerror(errno));
863
864 if (maxPhysPerIO)
865 dip.physSectorsPerIO = MIN(dip.physSectorsPerIO, maxPhysPerIO / dip.physSectorSize);
866
867 dip.sectorSize = kBytesPerSector;
868 dip.totalSectors = dip.physTotalSectors * dip.physSectorSize / dip.sectorSize;
869
870 dip.sectorOffset = 0;
871 time(&createtime);
872
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);
877 }
878
879 /*
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.
883 */
884 validate_hfsplus_block_size(dip.totalSectors, dip.sectorSize);
885
886 /* Make an HFS Plus disk */
887
888 if ((dip.totalSectors * dip.sectorSize ) < kMinHFSPlusVolumeSize)
889 fatal("%s: partition is too small (minimum is %d KB)", device, kMinHFSPlusVolumeSize/1024);
890
891 hfsplus_params(&dip, &defaults);
892 if (gNoCreate == 0) {
893 retval = make_hfsplus(&dip, &defaults);
894 if (retval == 0) {
895 printf("Initialized %s as a ", device);
896 if (dip.totalSectors > 2048ULL*1024*1024)
897 printf("%ld TB",
898 (long)((dip.totalSectors + (1024ULL*1024*1024))/(2048ULL*1024*1024)));
899 else if (dip.totalSectors > 2048*1024)
900 printf("%ld GB",
901 (long)((dip.totalSectors + (1024*1024))/(2048*1024)));
902 else if (dip.totalSectors > 2048)
903 printf("%ld MB",
904 (long)((dip.totalSectors + 1024)/2048));
905 else
906 printf("%ld KB",
907 (long)((dip.totalSectors + 1)/2));
908
909 if (gCaseSensitive) {
910 printf(" case-sensitive");
911 }
912 else {
913 printf(" case-insensitive");
914 }
915 if (gJournaled)
916 printf(" HFS Plus volume with a %uk journal\n",
917 (u_int32_t)defaults.journalSize/1024);
918 else
919 printf(" HFS Plus volume\n");
920 }
921 }
922
923 if (retval)
924 fatal("%s: %s", device, strerror(errno));
925
926 if ( fso > 0 ) {
927 close(fso);
928 }
929
930 return retval;
931 }
932
933 /*
934 typedef struct block_info {
935 off_t bnum; //64 bit
936 union {
937 _blk_info bi; //64 bit
938 struct buf *bp; //64 bit on K64, 32 bit on K32
939 } u;
940 }__attribute__((__packed__)) block_info;
941
942 total size == 16 bytes
943 */
944
945 #define BLOCK_INFO_SIZE 16
946
947 static void hfsplus_params (const DriveInfo* dip, hfsparams_t *defaults)
948 {
949 UInt64 sectorCount = dip->totalSectors;
950 UInt32 sectorSize = dip->sectorSize;
951 uint32_t totalBlocks;
952 UInt32 minClumpSize;
953 UInt32 clumpSize;
954 UInt32 oddBitmapBytes;
955
956 defaults->flags = 0;
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;
964
965 /*
966 * 8429818
967 * Always set kUseAccessPerms now; this also
968 * means we have to always have an owner, group,
969 * and mask.
970 */
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;
975
976 /*
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
980 * allocation block.
981 *
982 * Only scale if it's the default, otherwise just take what
983 * the user specified, with the caveat below.
984 */
985 if (gJournaled) {
986 uint32_t min_size = 0;
987
988 /*
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.
995 *
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
1002 * should be:
1003 *
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
1008 *
1009 * This becomes our new _floor_ for the journal_size.
1010 */
1011
1012 if (dip->physSectorSize != 0) {
1013 min_size = dip->physSectorSize * (dip->physSectorSize / BLOCK_INFO_SIZE);
1014 }
1015
1016 if (gJournalSize != 0) {
1017
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);
1022 gJournalSize = 0;
1023
1024 }
1025 /* defaults->journalSize will get reset below if it is 0 */
1026 defaults->journalSize = gJournalSize;
1027 }
1028
1029 if ((gJournalSize == 0) || (defaults->journalSize == 0)) {
1030 UInt32 jscale;
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);
1034 if (jscale > 64) {
1035 jscale = 64;
1036 }
1037
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;
1042 }
1043
1044 defaults->journalSize = target_size;
1045 }
1046
1047
1048 #ifndef DEBUG_BUILD
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.
1061 //
1062 if (sectorCount * sectorSize < 128*1024*1024) {
1063 /* This is a small (<128MB) FS */
1064 uint32_t small_default = (512 * 1024);
1065
1066 if (small_default <= min_size) {
1067 /*
1068 * If 512k is too small given the sector size,
1069 * then use the larger sector size
1070 */
1071 defaults->journalSize = min_size;
1072 }
1073 else {
1074 /* 512k was bigger than the min size; we can use it */
1075 defaults->journalSize = small_default;
1076 }
1077 }
1078 #endif
1079
1080 if (defaults->journalSize > 512 * 1024 * 1024) {
1081 defaults->journalSize = 512 * 1024 * 1024;
1082 }
1083
1084 if (defaults->journalSize < defaults->blockSize) {
1085 defaults->journalSize = defaults->blockSize;
1086 }
1087 }
1088
1089 strncpy((char *)defaults->volumeName, gVolumeName, sizeof(defaults->volumeName) - 1);
1090 defaults->volumeName[sizeof(defaults->volumeName) - 1] = '\0';
1091
1092 if (rsrclumpblks == 0) {
1093 if (gBlockSize > DFL_BLKSIZE)
1094 defaults->rsrcClumpSize = ROUNDUP(kHFSPlusRsrcClumpFactor * DFL_BLKSIZE, gBlockSize);
1095 else
1096 defaults->rsrcClumpSize = kHFSPlusRsrcClumpFactor * gBlockSize;
1097 } else
1098 defaults->rsrcClumpSize = clumpsizecalc(rsrclumpblks);
1099
1100 if (datclumpblks == 0) {
1101 if (gBlockSize > DFL_BLKSIZE)
1102 defaults->dataClumpSize = ROUNDUP(kHFSPlusRsrcClumpFactor * DFL_BLKSIZE, gBlockSize);
1103 else
1104 defaults->dataClumpSize = kHFSPlusRsrcClumpFactor * gBlockSize;
1105 } else
1106 defaults->dataClumpSize = clumpsizecalc(datclumpblks);
1107
1108 /*
1109 * The default b-tree node size is 8K. However, if the
1110 * volume is small (< 1 GB) we use 4K instead.
1111 */
1112 if (!gUserCatNodeSize) {
1113 if ((gBlockSize < HFSOPTIMALBLKSIZE) ||
1114 ((UInt64)(sectorCount * sectorSize) < (UInt64)0x40000000))
1115 catnodesiz = 4096;
1116 }
1117
1118 if (catclumpblks == 0) {
1119 clumpSize = CalcHFSPlusBTreeClumpSize(gBlockSize, catnodesiz, sectorCount, kHFSCatalogFileID);
1120 }
1121 else {
1122 clumpSize = clumpsizecalc(catclumpblks);
1123
1124 if (clumpSize % catnodesiz != 0)
1125 fatal("c=%ld: clump size is not a multiple of node size\n", clumpSize/gBlockSize);
1126 }
1127 defaults->catalogClumpSize = clumpSize;
1128 defaults->catalogNodeSize = catnodesiz;
1129 defaults->catalogExtsCount = catExtCount;
1130 defaults->catalogStartBlock = catExtStart;
1131
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);
1134
1135 if (extclumpblks == 0) {
1136 clumpSize = CalcHFSPlusBTreeClumpSize(gBlockSize, extnodesiz, sectorCount, kHFSExtentsFileID);
1137 }
1138 else {
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);
1142 }
1143 defaults->extentsClumpSize = clumpSize;
1144 defaults->extentsNodeSize = extnodesiz;
1145 defaults->extentsExtsCount = extExtCount;
1146 defaults->extentsStartBlock = extExtStart;
1147
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;
1153 }
1154 if (atrclumpblks == 0) {
1155 if (gUserAttrSize) {
1156 clumpSize = 0;
1157 }
1158 else {
1159 clumpSize = CalcHFSPlusBTreeClumpSize(gBlockSize, atrnodesiz, sectorCount, kHFSAttributesFileID);
1160 }
1161 }
1162 else {
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);
1166 }
1167 defaults->attributesClumpSize = clumpSize;
1168 defaults->attributesNodeSize = atrnodesiz;
1169 defaults->attributesExtsCount = attrExtCount;
1170 defaults->attributesStartBlock = attrExtStart;
1171
1172 /*
1173 * Calculate the number of blocks needed for bitmap (rounded up to a multiple of the block size).
1174 */
1175
1176 /*
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
1180 */
1181 totalBlocks = sectorCount / (gBlockSize / sectorSize);
1182
1183 minClumpSize = totalBlocks >> 3; /* convert bits to bytes by dividing by 8 */
1184 if (totalBlocks & 7)
1185 ++minClumpSize; /* round up to whole bytes */
1186
1187 /* Round up to a multiple of blockSize */
1188 if ((oddBitmapBytes = minClumpSize % gBlockSize))
1189 minClumpSize = minClumpSize - oddBitmapBytes + gBlockSize;
1190
1191 if (bmclumpblks == 0) {
1192 clumpSize = minClumpSize;
1193 }
1194 else {
1195 clumpSize = clumpsizecalc(bmclumpblks);
1196
1197 if (clumpSize < minClumpSize)
1198 fatal("b=%ld: bitmap clump size is too small\n", clumpSize/gBlockSize);
1199 }
1200 defaults->allocationClumpSize = clumpSize;
1201 defaults->allocationExtsCount = blkallocExtCount;
1202 defaults->allocationStartBlock = blkallocExtStart;
1203
1204 defaults->journalInfoBlock = jibStart;
1205 defaults->journalBlock = jnlStart;
1206 defaults->nextAllocBlock = allocStart;
1207
1208 if (gCaseSensitive)
1209 defaults->flags |= kMakeCaseSensitive;
1210
1211 if (gContentProtect)
1212 defaults->flags |= kMakeContentProtect;
1213
1214 #ifdef DEBUG_BUILD
1215 if (gProtectLevel)
1216 defaults->protectlevel = gProtectLevel;
1217 #endif
1218
1219 if (gNoCreate) {
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);
1226 if (gJournaled)
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);
1243 }
1244 printf("\tfile system start block: %u\n", defaults->fsStartBlock);
1245 }
1246 }
1247
1248
1249 static UInt32
1250 clumpsizecalc(UInt32 clumpblocks)
1251 {
1252 UInt64 clumpsize;
1253
1254 clumpsize = (UInt64)clumpblocks * (UInt64)gBlockSize;
1255
1256 if (clumpsize & (UInt64)(0xFFFFFFFF00000000ULL))
1257 fatal("=%ld: too many blocks for clump size!", clumpblocks);
1258
1259 return ((UInt32)clumpsize);
1260 }
1261
1262
1263 #define CLUMP_ENTRIES 15
1264
1265 short clumptbl[CLUMP_ENTRIES * 3] = {
1266 /*
1267 * Volume Attributes Catalog Extents
1268 * Size Clump (MB) Clump (MB) Clump (MB)
1269 */
1270 /* 1GB */ 4, 4, 4,
1271 /* 2GB */ 6, 6, 4,
1272 /* 4GB */ 8, 8, 4,
1273 /* 8GB */ 11, 11, 5,
1274 /*
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.
1279 *
1280 * For SnowLeopard 10A298, a FullNetInstall with all packages selected
1281 * results in:
1282 * Catalog B-tree Header
1283 * nodeSize: 8192
1284 * totalNodes: 31616
1285 * freeNodes: 1978
1286 * (used = 231.55 MB)
1287 * Attributes B-tree Header
1288 * nodeSize: 8192
1289 * totalNodes: 63232
1290 * freeNodes: 958
1291 * (used = 486.52 MB)
1292 *
1293 * We also want Time Machine backup volumes to have a sufficiently
1294 * large clump size to reduce fragmentation.
1295 *
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
1300 * previous term.
1301 */
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
1313 };
1314
1315 /*
1316 * CalcHFSPlusBTreeClumpSize
1317 *
1318 * This routine calculates the file clump size for either
1319 * the catalog file or the extents overflow file.
1320 */
1321 static UInt32
1322 CalcHFSPlusBTreeClumpSize(UInt32 blockSize, UInt32 nodeSize, UInt64 sectors, int fileID)
1323 {
1324 UInt32 mod = MAX(nodeSize, blockSize);
1325 UInt32 clumpSize;
1326 int column;
1327 int i;
1328
1329 /* Figure out which column of the above table to use for this file. */
1330 switch (fileID) {
1331 case kHFSAttributesFileID:
1332 column = 0;
1333 break;
1334 case kHFSCatalogFileID:
1335 column = 1;
1336 break;
1337 default:
1338 column = 2;
1339 break;
1340 }
1341
1342 /*
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.
1345 */
1346 if (sectors < 0x200000) {
1347 clumpSize = sectors << 2; /* 0.8 % */
1348 if (clumpSize < (8 * nodeSize))
1349 clumpSize = 8 * nodeSize;
1350 } else {
1351 /*
1352 * XXX This should scale more smoothly!
1353 */
1354 /* turn exponent into table index... */
1355 for (i = 0, sectors = sectors >> 22;
1356 sectors && (i < CLUMP_ENTRIES-1);
1357 ++i, sectors = sectors >> 1);
1358
1359 clumpSize = clumptbl[column + (i) * 3] * 1024 * 1024;
1360 }
1361
1362 /*
1363 * Round the clump size to a multiple of node and block size.
1364 * NOTE: This rounds down.
1365 */
1366 clumpSize /= mod;
1367 clumpSize *= mod;
1368
1369 /*
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.
1372 */
1373 if (clumpSize == 0)
1374 clumpSize = mod;
1375
1376 return (clumpSize);
1377 }
1378
1379
1380 /* VARARGS */
1381 void
1382 #if __STDC__
1383 fatal(const char *fmt, ...)
1384 #else
1385 fatal(fmt, va_alist)
1386 char *fmt;
1387 va_dcl
1388 #endif
1389 {
1390 va_list ap;
1391
1392 #if __STDC__
1393 va_start(ap, fmt);
1394 #else
1395 va_start(ap);
1396 #endif
1397 if (fcntl(STDERR_FILENO, F_GETFL) < 0) {
1398 openlog(progname, LOG_CONS, LOG_DAEMON);
1399 vsyslog(LOG_ERR, fmt, ap);
1400 closelog();
1401 } else {
1402 vwarnx(fmt, ap);
1403 }
1404 va_end(ap);
1405 exit(1);
1406 /* NOTREACHED */
1407 }
1408
1409
1410 void usage()
1411 {
1412 fprintf(stderr, "usage: %s [-N [partition-size]] [hfsplus-options] special-device\n", progname);
1413
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");
1417
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");
1438 #ifdef DEBUG_BUILD
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");
1450 #endif
1451
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);
1456
1457 exit(1);
1458 }