1/*
2 * Copyright 2008-2017 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Marco Minutoli, mminutoli@gmail.com
7 *		Axel D��rfler, axeld@pinc-software.de
8 */
9
10#include <getopt.h>
11#include <stdio.h>
12#include <stdlib.h>
13
14#include <DiskSystem.h>
15
16#include "FsCreator.h"
17
18
19extern "C" const char* __progname;
20static const char* kProgramName = __progname;
21
22
23/*!	Print program help on the right stream */
24static void
25print_help(bool out)
26{
27	fprintf(out ? stdout : stderr,
28		"Usage: %s <options> <device> <volume name>\n"
29		"\n"
30		"Options:\n"
31		"  -t, --type       <fs>   - set type of file system to create\n\n"
32		"  -l, --list-types        - list file systems that support initializing\n"
33		"  -h, --help              - print this help text\n"
34		"  -o, --options    <opt>  - set fs specific options\n"
35		"  -q, --dont-ask          - do not ask before initializing\n"
36		"  -v, --verbose           - set verbose output\n"
37		"\n"
38		"Example:\n"
39		"  mkfs -t bfs -o 'block_size 4096; noindex' ./test.image Data\n"
40		"\tThis will initialize \"test.image\" with BFS with a block\n"
41		"\tsize of 4096 bytes, without index, and named \"Data\".\n",
42		kProgramName);
43}
44
45
46/*!	Print program help and exit */
47static void
48print_help_exit(bool out)
49{
50	print_help(out);
51	exit(out ? 0 : 1);
52}
53
54
55static void
56list_types()
57{
58	const char* kFormat = "%-10s  %-25s  %s\n";
59	BDiskDeviceRoster roster;
60	BDiskSystem diskSystem;
61
62	printf("Installed file systems that support initializing:\n\n");
63	printf(kFormat, "Name", "Pretty Name", "Module");
64	printf(kFormat, "--", "--", "--");
65
66	while (roster.GetNextDiskSystem(&diskSystem) == B_OK) {
67		if (!diskSystem.SupportsInitializing()
68			|| !diskSystem.IsFileSystem())
69			continue;
70
71		printf(kFormat, diskSystem.ShortName(), diskSystem.PrettyName(),
72			diskSystem.Name());
73	}
74}
75
76
77int
78main(int argc, char* const* argv)
79{
80	const struct option kLongOptions[] = {
81		{ "help", 0, NULL, 'h' },
82		{ "options", 0, NULL, 'o' },
83		{ "type", 1, NULL, 't' },
84		{ "list-types", 0, NULL, 'l' },
85		{ "verbose", 0, NULL, 'v' },
86		{ "dont-ask", 0, NULL, 'q' },
87		{ NULL, 0, NULL, 0 }
88	};
89	const char* kShortOptions = "t:o:lhvq";
90
91	// parse argument list
92	const char* fsType = "bfs";
93	const char* fsOptions = NULL;
94	bool verbose = false;
95	bool quick = false;
96
97	while (true) {
98		int nextOption = getopt_long(argc, argv, kShortOptions, kLongOptions,
99			NULL);
100		if (nextOption == -1)
101			break;
102
103		switch (nextOption) {
104			case 't':	// -t or --type
105				fsType = optarg;
106				break;
107			case 'h':	// -h or --help
108				print_help_exit(true);
109				break;
110			case 'v':	// -v or --verbose
111				verbose = true;
112				break;
113			case 'o':	// -o or --options
114				fsOptions = optarg;
115				break;
116			case 'q':	// -q or --quick
117				quick = true;
118				break;
119			case 'l':	// list types
120				list_types();
121				return 0;
122			case '?':	// invalid option
123				break;
124			case -1:	// done with options
125				break;
126			default:	// everything else
127				print_help(false);
128				abort();
129		}
130	}
131
132	// the device name should be the first non-option element
133	// right before the volume name
134	if (optind > argc - 1)
135		print_help_exit(false);
136
137	const char* device = argv[optind];
138	const char* volumeName = NULL;
139	if (optind == argc - 2)
140		volumeName = argv[argc - 1];
141	else {
142		if (!strncmp(device, "/dev", 4))
143			volumeName = "Unnamed";
144		else
145			volumeName = "Unnamed Image";
146	}
147
148	FsCreator creator(device, fsType, volumeName, fsOptions, quick, verbose);
149	return creator.Run() ? 0 : 1;
150}
151