1b33a7e92SMatthew Dillon /*
2fd8fd3dfSMatthew Dillon  * Copyright (c) 2011-2015 The DragonFly Project.  All rights reserved.
3b33a7e92SMatthew Dillon  *
4b33a7e92SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5b33a7e92SMatthew Dillon  * by Matthew Dillon <dillon@dragonflybsd.org>
6b33a7e92SMatthew Dillon  *
7b33a7e92SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
8b33a7e92SMatthew Dillon  * modification, are permitted provided that the following conditions
9b33a7e92SMatthew Dillon  * are met:
10b33a7e92SMatthew Dillon  *
11b33a7e92SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
12b33a7e92SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
13b33a7e92SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
14b33a7e92SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
15b33a7e92SMatthew Dillon  *    the documentation and/or other materials provided with the
16b33a7e92SMatthew Dillon  *    distribution.
17b33a7e92SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
18b33a7e92SMatthew Dillon  *    contributors may be used to endorse or promote products derived
19b33a7e92SMatthew Dillon  *    from this software without specific, prior written permission.
20b33a7e92SMatthew Dillon  *
21b33a7e92SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22b33a7e92SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23b33a7e92SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24b33a7e92SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25b33a7e92SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26b33a7e92SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27b33a7e92SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28b33a7e92SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29b33a7e92SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30b33a7e92SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31b33a7e92SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32b33a7e92SMatthew Dillon  * SUCH DAMAGE.
33b33a7e92SMatthew Dillon  */
34b33a7e92SMatthew Dillon 
35b33a7e92SMatthew Dillon #include <sys/types.h>
36b33a7e92SMatthew Dillon 
37b33a7e92SMatthew Dillon #include <stdio.h>
38b33a7e92SMatthew Dillon #include <stdlib.h>
39b33a7e92SMatthew Dillon #include <stddef.h>
40b33a7e92SMatthew Dillon #include <unistd.h>
41b33a7e92SMatthew Dillon #include <string.h>
4260e242c5STomohiro Kusumi #include <assert.h>
43b33a7e92SMatthew Dillon #include <err.h>
44b33a7e92SMatthew Dillon 
452d60b848STomohiro Kusumi #include "mkfs_hammer2.h"
4689d864a2SMatthew Dillon 
472dc244c9STomohiro Kusumi static void parse_fs_size(hammer2_mkfs_options_t *, const char *);
48b33a7e92SMatthew Dillon static void usage(void);
49b33a7e92SMatthew Dillon 
50b33a7e92SMatthew Dillon int
main(int ac,char ** av)51b33a7e92SMatthew Dillon main(int ac, char **av)
52b33a7e92SMatthew Dillon {
532d60b848STomohiro Kusumi 	hammer2_mkfs_options_t opt;
54b33a7e92SMatthew Dillon 	int ch;
552d60b848STomohiro Kusumi 	int label_specified = 0;
5689d864a2SMatthew Dillon 
57b33a7e92SMatthew Dillon 	/*
582d60b848STomohiro Kusumi 	 * Initialize option structure.
59b33a7e92SMatthew Dillon 	 */
602d60b848STomohiro Kusumi 	hammer2_mkfs_init(&opt);
61b33a7e92SMatthew Dillon 
62b33a7e92SMatthew Dillon 	/*
632d60b848STomohiro Kusumi 	 * Parse arguments.
64b33a7e92SMatthew Dillon 	 */
656dd91095STomohiro Kusumi 	while ((ch = getopt(ac, av, "L:b:r:V:s:d")) != -1) {
66b33a7e92SMatthew Dillon 		switch(ch) {
672d60b848STomohiro Kusumi 		case 'b':
682d60b848STomohiro Kusumi 			opt.BootAreaSize = getsize(optarg,
692d60b848STomohiro Kusumi 					 HAMMER2_NEWFS_ALIGN,
702d60b848STomohiro Kusumi 					 HAMMER2_BOOT_MAX_BYTES, 2);
712d60b848STomohiro Kusumi 			break;
722d60b848STomohiro Kusumi 		case 'r':
732d60b848STomohiro Kusumi 			opt.AuxAreaSize = getsize(optarg,
742d60b848STomohiro Kusumi 					 HAMMER2_NEWFS_ALIGN,
752d60b848STomohiro Kusumi 					 HAMMER2_AUX_MAX_BYTES, 2);
762d60b848STomohiro Kusumi 			break;
772d60b848STomohiro Kusumi 		case 'V':
782d60b848STomohiro Kusumi 			opt.Hammer2Version = strtol(optarg, NULL, 0);
792d60b848STomohiro Kusumi 			if (opt.Hammer2Version < HAMMER2_VOL_VERSION_MIN ||
802d60b848STomohiro Kusumi 			    opt.Hammer2Version >= HAMMER2_VOL_VERSION_WIP) {
812d60b848STomohiro Kusumi 				errx(1, "I don't understand how to format "
822d60b848STomohiro Kusumi 				     "HAMMER2 version %d",
832d60b848STomohiro Kusumi 				     opt.Hammer2Version);
842d60b848STomohiro Kusumi 			}
852d60b848STomohiro Kusumi 			break;
86b33a7e92SMatthew Dillon 		case 'L':
872d60b848STomohiro Kusumi 			label_specified = 1;
8889d864a2SMatthew Dillon 			if (strcasecmp(optarg, "none") == 0) {
8989d864a2SMatthew Dillon 				break;
9089d864a2SMatthew Dillon 			}
912d60b848STomohiro Kusumi 			if (opt.NLabels >= MAXLABELS) {
92234b2171STomohiro Kusumi 				errx(1, "Limit of %d local labels",
935cebbe36SMatthew Dillon 				     MAXLABELS - 1);
9489d864a2SMatthew Dillon 			}
95eabc9a2cSMatthew Dillon 			if (strlen(optarg) == 0) {
962e1975d5STomohiro Kusumi 				errx(1, "Volume label '%s' cannot be 0-length",
97eabc9a2cSMatthew Dillon 					optarg);
98b33a7e92SMatthew Dillon 			}
99eabc9a2cSMatthew Dillon 			if (strlen(optarg) >= HAMMER2_INODE_MAXNAME) {
100eabc9a2cSMatthew Dillon 				errx(1, "Volume label '%s' is too long "
1012e1975d5STomohiro Kusumi 					"(%d chars max)",
102eabc9a2cSMatthew Dillon 					optarg,
103eabc9a2cSMatthew Dillon 					HAMMER2_INODE_MAXNAME - 1);
104eabc9a2cSMatthew Dillon 			}
1052d60b848STomohiro Kusumi 			opt.Label[opt.NLabels++] = strdup(optarg);
106b33a7e92SMatthew Dillon 			break;
1076dd91095STomohiro Kusumi 		case 's':
1082dc244c9STomohiro Kusumi 			parse_fs_size(&opt, optarg);
1096dd91095STomohiro Kusumi 			break;
1100b738157STomohiro Kusumi 		case 'd':
1112d60b848STomohiro Kusumi 			opt.DebugOpt = 1;
1120b738157STomohiro Kusumi 			break;
113b33a7e92SMatthew Dillon 		default:
114b33a7e92SMatthew Dillon 			usage();
115b33a7e92SMatthew Dillon 			break;
116b33a7e92SMatthew Dillon 		}
117b33a7e92SMatthew Dillon 	}
118b33a7e92SMatthew Dillon 
119b33a7e92SMatthew Dillon 	ac -= optind;
120b33a7e92SMatthew Dillon 	av += optind;
121b33a7e92SMatthew Dillon 
1220b738157STomohiro Kusumi 	if (ac == 0)
1230b738157STomohiro Kusumi 		errx(1, "You must specify at least one disk device");
1240b738157STomohiro Kusumi 	if (ac > HAMMER2_MAX_VOLUMES)
1250b738157STomohiro Kusumi 		errx(1, "The maximum number of volumes is %d",
1260b738157STomohiro Kusumi 		     HAMMER2_MAX_VOLUMES);
127fd8fd3dfSMatthew Dillon 
128fd8fd3dfSMatthew Dillon 	/*
1292d60b848STomohiro Kusumi 	 * Check default label type.
130fd8fd3dfSMatthew Dillon 	 */
1312d60b848STomohiro Kusumi 	if (!label_specified) {
132fd8fd3dfSMatthew Dillon 		char c = av[0][strlen(av[0]) - 1];
133fd8fd3dfSMatthew Dillon 		if (c == 'a')
1342d60b848STomohiro Kusumi 			opt.DefaultLabelType = HAMMER2_LABEL_BOOT;
135fd8fd3dfSMatthew Dillon 		else if (c == 'd')
1362d60b848STomohiro Kusumi 			opt.DefaultLabelType = HAMMER2_LABEL_ROOT;
137fd8fd3dfSMatthew Dillon 		else
1382d60b848STomohiro Kusumi 			opt.DefaultLabelType = HAMMER2_LABEL_DATA;
139fd8fd3dfSMatthew Dillon 	}
140fd8fd3dfSMatthew Dillon 
141fd8fd3dfSMatthew Dillon 	/*
1422d60b848STomohiro Kusumi 	 * Create Hammer2 filesystem.
143fd8fd3dfSMatthew Dillon 	 */
144a071436bSTomohiro Kusumi 	assert(opt.CompType == HAMMER2_COMP_DEFAULT);
145*9046282cSTomohiro Kusumi 	assert(opt.CheckType == HAMMER2_CHECK_DEFAULT);
1462d60b848STomohiro Kusumi 	hammer2_mkfs(ac, av, &opt);
147b33a7e92SMatthew Dillon 
148b33a7e92SMatthew Dillon 	/*
1492d60b848STomohiro Kusumi 	 * Cleanup option structure.
150b33a7e92SMatthew Dillon 	 */
1512d60b848STomohiro Kusumi 	hammer2_mkfs_cleanup(&opt);
1520b738157STomohiro Kusumi 
153b33a7e92SMatthew Dillon 	return(0);
154b33a7e92SMatthew Dillon }
155b33a7e92SMatthew Dillon 
156b33a7e92SMatthew Dillon static
157b33a7e92SMatthew Dillon void
parse_fs_size(hammer2_mkfs_options_t * opt,const char * arg)1582dc244c9STomohiro Kusumi parse_fs_size(hammer2_mkfs_options_t *opt, const char *arg)
1592dc244c9STomohiro Kusumi {
1602dc244c9STomohiro Kusumi 	char *o, *p, *s;
1612dc244c9STomohiro Kusumi 
1622dc244c9STomohiro Kusumi 	opt->NFileSystemSizes = 0;
1632dc244c9STomohiro Kusumi 	o = p = strdup(arg);
1642dc244c9STomohiro Kusumi 
1652dc244c9STomohiro Kusumi 	while ((s = p) != NULL) {
1662dc244c9STomohiro Kusumi 		if ((p = strchr(p, ':')) != NULL)
1672dc244c9STomohiro Kusumi 			*p++ = 0;
1682dc244c9STomohiro Kusumi 		/* XXX 0x7fffffffffffffff isn't limitation of HAMMER2 */
1692dc244c9STomohiro Kusumi 		opt->FileSystemSize[opt->NFileSystemSizes++] = getsize(s,
1702dc244c9STomohiro Kusumi 				 HAMMER2_FREEMAP_LEVEL1_SIZE,
1712dc244c9STomohiro Kusumi 				 0x7fffffffffffffff, 2);
172af73f535STomohiro Kusumi 		if (opt->NFileSystemSizes >= HAMMER2_MAX_VOLUMES)
173af73f535STomohiro Kusumi 			break;
1742dc244c9STomohiro Kusumi 	}
1752dc244c9STomohiro Kusumi 	free(o);
1762dc244c9STomohiro Kusumi }
1772dc244c9STomohiro Kusumi 
1782dc244c9STomohiro Kusumi static
1792dc244c9STomohiro Kusumi void
usage(void)180b33a7e92SMatthew Dillon usage(void)
181b33a7e92SMatthew Dillon {
182b33a7e92SMatthew Dillon 	fprintf(stderr,
1837b2944d3STomohiro Kusumi 		"usage: newfs_hammer2 [-b bootsize] [-r auxsize] "
1846dd91095STomohiro Kusumi 		"[-V version] [-L label ...] [-s size] special ...\n"
185b33a7e92SMatthew Dillon 	);
186b33a7e92SMatthew Dillon 	exit(1);
187b33a7e92SMatthew Dillon }
188