xref: /haiku/src/bin/mkfs/FsCreator.cpp (revision f75a7bf508f3156d63a14f8fd77c5e0ca4d08c42)
1 /*
2  * Copyright 2008 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 "FsCreator.h"
11 
12 #include <iostream>
13 
14 #include <DiskSystem.h>
15 
16 
17 class UnregisterFileDevice {
18 public:
19 	UnregisterFileDevice()
20 		:
21 		fID(-1)
22 	{
23 	}
24 
25 	~UnregisterFileDevice()
26 	{
27 		if (fID >= 0) {
28 			BDiskDeviceRoster roster;
29 			roster.UnregisterFileDevice(fID);
30 		}
31 	}
32 
33 	void SetTo(partition_id id)
34 	{
35 		fID = id;
36 	}
37 
38 	void Detach()
39 	{
40 		fID = -1;
41 	}
42 
43 private:
44 	partition_id	fID;
45 };
46 
47 
48 extern "C" const char* __progname;
49 static const char* kProgramName = __progname;
50 
51 
52 FsCreator::FsCreator(const char* path, const char* type, const char* volumeName,
53 		const char* fsOptions, bool quick, bool verbose)
54 	:
55 	fType(type),
56 	fPath(path),
57 	fVolumeName(volumeName),
58 	fFsOptions(fsOptions),
59 	fVerbose(verbose),
60 	fQuick(quick)
61 {
62 }
63 
64 
65 bool
66 FsCreator::Run()
67 {
68 	UnregisterFileDevice unregisterFileDevice;
69 
70 	BDiskDeviceRoster roster;
71 	BPartition* partition;
72 	BDiskDevice device;
73 
74 	status_t status = roster.GetPartitionForPath(fPath, &device,
75 		&partition);
76 	if (status != B_OK) {
77 		if (!strncmp(fPath, "/dev", 4)) {
78 			std::cerr << kProgramName << ": Failed to get disk device for path "
79 				<< fPath << ": " << strerror(status) << std::endl;
80 			return false;
81 		}
82 
83 		// try to register file device
84 
85 		partition_id id = roster.RegisterFileDevice(fPath);
86 		if (id < B_OK) {
87 			std::cerr << kProgramName << ": Could not register file device for "
88 				"path " << fPath << ": " << strerror(status) << std::endl;
89 			return false;
90 		}
91 
92 		unregisterFileDevice.SetTo(id);
93 
94 		status = roster.GetPartitionWithID(id, &device, &partition);
95 		if (!strncmp(fPath, "/dev", 4)) {
96 			std::cerr << kProgramName << ": Cannot find registered file device "
97 				"for path " << fPath << ": " << strerror(status)
98 				<< std::endl;
99 			return false;
100 		}
101 	}
102 
103 	// check that the device is writable
104 	if (partition->IsReadOnly()) {
105 		std::cerr << kProgramName << ": Cannot initialize read-only device.\n";
106 		return false;
107 	}
108 
109 	// check if the device is mounted
110 	if (partition->IsMounted()) {
111 		std::cerr << kProgramName << ": Cannot initialize mounted device.\n";
112 		return false;
113 	}
114 
115 	BDiskSystem diskSystem;
116 	if (roster.GetDiskSystem(&diskSystem, fType) != B_OK) {
117 		std::cerr << kProgramName << ": " << fType
118 			<< " is an invalid or unsupported file system type.\n";
119 		return false;
120 	}
121 
122 	// prepare the device for modifications
123 	status = device.PrepareModifications();
124 	if (status != B_OK) {
125 		std::cerr << kProgramName << ": A problem occurred preparing the "
126 			"device for the modifications\n";
127 		return false;
128 	}
129 	if (fVerbose)
130 		std::cout << "Preparing for modifications...\n\n";
131 
132 	// validate parameters
133 	BString name(fVolumeName);
134 	if (partition->ValidateInitialize(diskSystem.PrettyName(),
135 			&name, fFsOptions) != B_OK) {
136 		std::cerr << kProgramName << ": Parameters validation failed. "
137 			"Check what you wrote\n";
138 		std::cerr << status;
139 		return false;
140 	}
141 	if (fVerbose)
142 		std::cout << "Parameters Validation...\n\n";
143 	if (name != fVolumeName) {
144 		std::cout << "Volume name was adjusted to "
145 			<< name.String() << std::endl;
146 	}
147 
148 	// Initialize the partition
149 	status = partition->Initialize(diskSystem.PrettyName(), name.String(),
150 		fFsOptions);
151 	if (status != B_OK) {
152 		std::cerr << kProgramName << ": Initialization failed: "
153 			<< strerror(status) << std::endl;
154 		return false;
155 	}
156 
157 	if (!fQuick) {
158 		std::cout << "\nAbout to initialize " << fPath << " with "
159 			<< diskSystem.PrettyName()
160 			<< "\nAre you sure you want to do this now?\n"
161 			<< "\nALL YOUR DATA in " << fPath << " will be lost forever.\n";
162 
163 		BString reply;
164 		do {
165 			std::cout << "Continue (yes|[no])? ";
166 			reply = _ReadLine();
167 			if (reply == "")
168 				reply = "no"; // silence is dissence
169 		} while (reply != "yes" && reply != "no");
170 
171 		if (reply != "yes")
172 			return true;
173 	}
174 
175 	status = device.CommitModifications();
176 	if (status == B_OK) {
177 		if (fVerbose) {
178 			std::cout << "Volume " << partition->ContentName()
179 				<< " has been initialized successfully!\n";
180 		}
181 	} else {
182 		std::cout << kProgramName << ": Initialization of "
183 			<< partition->ContentName() << " failed: " << strerror(status)
184 			<< std::endl;
185 		return false;
186 	}
187 
188 	// TODO: should we keep the file device around, or unregister it
189 	// after we're done? This could be an option, too (for now, we'll
190 	// just keep them if everything went well).
191 	unregisterFileDevice.Detach();
192 	return true;
193 }
194 
195 
196 inline BString
197 FsCreator::_ReadLine()
198 {
199 	char line[255];
200 
201 	std::cin.getline(line, sizeof(line), '\n');
202 
203 	return line;
204 }
205