xref: /haiku/src/bin/mkfs/FsCreator.cpp (revision 7e7aeaeba470ab792c9c1862dfbc8b12dbce1b2c)
17557d131SStephan Aßmus /*
2*7e7aeaebSAxel Dörfler  * Copyright 2008-2009 Haiku Inc. All rights reserved.
37557d131SStephan Aßmus  * Distributed under the terms of the MIT License.
47557d131SStephan Aßmus  *
57557d131SStephan Aßmus  * Authors:
67557d131SStephan Aßmus  *		Marco Minutoli, mminutoli@gmail.com
76835a76dSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
87557d131SStephan Aßmus  */
97557d131SStephan Aßmus 
107557d131SStephan Aßmus #include "FsCreator.h"
117557d131SStephan Aßmus 
127557d131SStephan Aßmus #include <iostream>
137557d131SStephan Aßmus 
147557d131SStephan Aßmus #include <DiskSystem.h>
157557d131SStephan Aßmus 
167557d131SStephan Aßmus 
176835a76dSAxel Dörfler class UnregisterFileDevice {
186835a76dSAxel Dörfler public:
UnregisterFileDevice()196835a76dSAxel Dörfler 	UnregisterFileDevice()
206835a76dSAxel Dörfler 		:
216835a76dSAxel Dörfler 		fID(-1)
226835a76dSAxel Dörfler 	{
236835a76dSAxel Dörfler 	}
246835a76dSAxel Dörfler 
~UnregisterFileDevice()256835a76dSAxel Dörfler 	~UnregisterFileDevice()
266835a76dSAxel Dörfler 	{
276835a76dSAxel Dörfler 		if (fID >= 0) {
286835a76dSAxel Dörfler 			BDiskDeviceRoster roster;
296835a76dSAxel Dörfler 			roster.UnregisterFileDevice(fID);
306835a76dSAxel Dörfler 		}
316835a76dSAxel Dörfler 	}
326835a76dSAxel Dörfler 
SetTo(partition_id id)336835a76dSAxel Dörfler 	void SetTo(partition_id id)
346835a76dSAxel Dörfler 	{
356835a76dSAxel Dörfler 		fID = id;
366835a76dSAxel Dörfler 	}
376835a76dSAxel Dörfler 
Detach()386835a76dSAxel Dörfler 	void Detach()
396835a76dSAxel Dörfler 	{
406835a76dSAxel Dörfler 		fID = -1;
416835a76dSAxel Dörfler 	}
426835a76dSAxel Dörfler 
436835a76dSAxel Dörfler private:
446835a76dSAxel Dörfler 	partition_id	fID;
456835a76dSAxel Dörfler };
466835a76dSAxel Dörfler 
476835a76dSAxel Dörfler 
486835a76dSAxel Dörfler extern "C" const char* __progname;
496835a76dSAxel Dörfler static const char* kProgramName = __progname;
506835a76dSAxel Dörfler 
516835a76dSAxel Dörfler 
FsCreator(const char * path,const char * type,const char * volumeName,const char * fsOptions,bool quick,bool verbose)526835a76dSAxel Dörfler FsCreator::FsCreator(const char* path, const char* type, const char* volumeName,
536835a76dSAxel Dörfler 		const char* fsOptions, bool quick, bool verbose)
547557d131SStephan Aßmus 	:
557557d131SStephan Aßmus 	fType(type),
566835a76dSAxel Dörfler 	fPath(path),
577557d131SStephan Aßmus 	fVolumeName(volumeName),
586835a76dSAxel Dörfler 	fFsOptions(fsOptions),
596835a76dSAxel Dörfler 	fVerbose(verbose),
606835a76dSAxel Dörfler 	fQuick(quick)
617557d131SStephan Aßmus {
627557d131SStephan Aßmus }
637557d131SStephan Aßmus 
647557d131SStephan Aßmus 
657557d131SStephan Aßmus bool
Run()667557d131SStephan Aßmus FsCreator::Run()
677557d131SStephan Aßmus {
686835a76dSAxel Dörfler 	UnregisterFileDevice unregisterFileDevice;
696835a76dSAxel Dörfler 
706835a76dSAxel Dörfler 	BDiskDeviceRoster roster;
716835a76dSAxel Dörfler 	BPartition* partition;
726835a76dSAxel Dörfler 	BDiskDevice device;
736835a76dSAxel Dörfler 
746835a76dSAxel Dörfler 	status_t status = roster.GetPartitionForPath(fPath, &device,
756835a76dSAxel Dörfler 		&partition);
766835a76dSAxel Dörfler 	if (status != B_OK) {
776835a76dSAxel Dörfler 		if (!strncmp(fPath, "/dev", 4)) {
786835a76dSAxel Dörfler 			std::cerr << kProgramName << ": Failed to get disk device for path "
796835a76dSAxel Dörfler 				<< fPath << ": " << strerror(status) << std::endl;
806835a76dSAxel Dörfler 			return false;
816835a76dSAxel Dörfler 		}
826835a76dSAxel Dörfler 
836835a76dSAxel Dörfler 		// try to register file device
846835a76dSAxel Dörfler 
856835a76dSAxel Dörfler 		partition_id id = roster.RegisterFileDevice(fPath);
866835a76dSAxel Dörfler 		if (id < B_OK) {
876835a76dSAxel Dörfler 			std::cerr << kProgramName << ": Could not register file device for "
886835a76dSAxel Dörfler 				"path " << fPath << ": " << strerror(status) << std::endl;
896835a76dSAxel Dörfler 			return false;
906835a76dSAxel Dörfler 		}
916835a76dSAxel Dörfler 
926835a76dSAxel Dörfler 		unregisterFileDevice.SetTo(id);
936835a76dSAxel Dörfler 
946835a76dSAxel Dörfler 		status = roster.GetPartitionWithID(id, &device, &partition);
956835a76dSAxel Dörfler 		if (!strncmp(fPath, "/dev", 4)) {
966835a76dSAxel Dörfler 			std::cerr << kProgramName << ": Cannot find registered file device "
976835a76dSAxel Dörfler 				"for path " << fPath << ": " << strerror(status)
986835a76dSAxel Dörfler 				<< std::endl;
996835a76dSAxel Dörfler 			return false;
1006835a76dSAxel Dörfler 		}
1016835a76dSAxel Dörfler 	}
1026835a76dSAxel Dörfler 
1037557d131SStephan Aßmus 	// check that the device is writable
1046835a76dSAxel Dörfler 	if (partition->IsReadOnly()) {
1056835a76dSAxel Dörfler 		std::cerr << kProgramName << ": Cannot initialize read-only device.\n";
1067557d131SStephan Aßmus 		return false;
1077557d131SStephan Aßmus 	}
1087557d131SStephan Aßmus 
1097557d131SStephan Aßmus 	// check if the device is mounted
1106835a76dSAxel Dörfler 	if (partition->IsMounted()) {
1116835a76dSAxel Dörfler 		std::cerr << kProgramName << ": Cannot initialize mounted device.\n";
1127557d131SStephan Aßmus 		return false;
1137557d131SStephan Aßmus 	}
1147557d131SStephan Aßmus 
1157557d131SStephan Aßmus 	BDiskSystem diskSystem;
1166835a76dSAxel Dörfler 	if (roster.GetDiskSystem(&diskSystem, fType) != B_OK) {
1176835a76dSAxel Dörfler 		std::cerr << kProgramName << ": " << fType
1187557d131SStephan Aßmus 			<< " is an invalid or unsupported file system type.\n";
1197557d131SStephan Aßmus 		return false;
1207557d131SStephan Aßmus 	}
1217557d131SStephan Aßmus 
1227557d131SStephan Aßmus 	// prepare the device for modifications
1236835a76dSAxel Dörfler 	status = device.PrepareModifications();
1246835a76dSAxel Dörfler 	if (status != B_OK) {
1256835a76dSAxel Dörfler 		std::cerr << kProgramName << ": A problem occurred preparing the "
1266835a76dSAxel Dörfler 			"device for the modifications\n";
1277557d131SStephan Aßmus 		return false;
1287557d131SStephan Aßmus 	}
1297557d131SStephan Aßmus 	if (fVerbose)
1307557d131SStephan Aßmus 		std::cout << "Preparing for modifications...\n\n";
1317557d131SStephan Aßmus 
1327557d131SStephan Aßmus 	// validate parameters
1337557d131SStephan Aßmus 	BString name(fVolumeName);
1346835a76dSAxel Dörfler 	if (partition->ValidateInitialize(diskSystem.PrettyName(),
1356835a76dSAxel Dörfler 			&name, fFsOptions) != B_OK) {
1366835a76dSAxel Dörfler 		std::cerr << kProgramName << ": Parameters validation failed. "
1377557d131SStephan Aßmus 			"Check what you wrote\n";
1386835a76dSAxel Dörfler 		std::cerr << status;
1397557d131SStephan Aßmus 		return false;
1407557d131SStephan Aßmus 	}
1417557d131SStephan Aßmus 	if (fVerbose)
1427557d131SStephan Aßmus 		std::cout << "Parameters Validation...\n\n";
1436835a76dSAxel Dörfler 	if (name != fVolumeName) {
1447557d131SStephan Aßmus 		std::cout << "Volume name was adjusted to "
1456835a76dSAxel Dörfler 			<< name.String() << std::endl;
1466835a76dSAxel Dörfler 	}
1477557d131SStephan Aßmus 
1487557d131SStephan Aßmus 	// Initialize the partition
1496835a76dSAxel Dörfler 	status = partition->Initialize(diskSystem.PrettyName(), name.String(),
1506835a76dSAxel Dörfler 		fFsOptions);
1516835a76dSAxel Dörfler 	if (status != B_OK) {
1526835a76dSAxel Dörfler 		std::cerr << kProgramName << ": Initialization failed: "
1536835a76dSAxel Dörfler 			<< strerror(status) << std::endl;
1547557d131SStephan Aßmus 		return false;
1557557d131SStephan Aßmus 	}
1567557d131SStephan Aßmus 
1576835a76dSAxel Dörfler 	if (!fQuick) {
1586835a76dSAxel Dörfler 		std::cout << "\nAbout to initialize " << fPath << " with "
1596835a76dSAxel Dörfler 			<< diskSystem.PrettyName()
1606835a76dSAxel Dörfler 			<< "\nAre you sure you want to do this now?\n"
1616835a76dSAxel Dörfler 			<< "\nALL YOUR DATA in " << fPath << " will be lost forever.\n";
1627557d131SStephan Aßmus 
1637557d131SStephan Aßmus 		BString reply;
1647557d131SStephan Aßmus 		do {
1656835a76dSAxel Dörfler 			std::cout << "Continue (yes|[no])? ";
1667557d131SStephan Aßmus 			reply = _ReadLine();
1677557d131SStephan Aßmus 			if (reply == "")
1687557d131SStephan Aßmus 				reply = "no"; // silence is dissence
1697557d131SStephan Aßmus 		} while (reply != "yes" && reply != "no");
1707557d131SStephan Aßmus 
1716835a76dSAxel Dörfler 		if (reply != "yes")
1726835a76dSAxel Dörfler 			return true;
1736835a76dSAxel Dörfler 	}
1746835a76dSAxel Dörfler 
175*7e7aeaebSAxel Dörfler 	BString contentName = partition->ContentName();
176*7e7aeaebSAxel Dörfler 		// CommitModifications() will invalidate our partition object
177*7e7aeaebSAxel Dörfler 
1786835a76dSAxel Dörfler 	status = device.CommitModifications();
1796835a76dSAxel Dörfler 	if (status == B_OK) {
1807557d131SStephan Aßmus 		if (fVerbose) {
181*7e7aeaebSAxel Dörfler 			std::cout << "Volume \"" << contentName.String()
182*7e7aeaebSAxel Dörfler 				<< "\" has been initialized successfully!" << std::endl;
1837557d131SStephan Aßmus 		}
1847557d131SStephan Aßmus 	} else {
185*7e7aeaebSAxel Dörfler 		std::cout << kProgramName << ": Initialization of \""
186*7e7aeaebSAxel Dörfler 			<< contentName.String() << "\" failed: " << strerror(status)
1876835a76dSAxel Dörfler 			<< std::endl;
1887557d131SStephan Aßmus 		return false;
1897557d131SStephan Aßmus 	}
1906835a76dSAxel Dörfler 
1916835a76dSAxel Dörfler 	// TODO: should we keep the file device around, or unregister it
1926835a76dSAxel Dörfler 	// after we're done? This could be an option, too (for now, we'll
1936835a76dSAxel Dörfler 	// just keep them if everything went well).
1946835a76dSAxel Dörfler 	unregisterFileDevice.Detach();
1957557d131SStephan Aßmus 	return true;
1967557d131SStephan Aßmus }
1977557d131SStephan Aßmus 
1987557d131SStephan Aßmus 
1997557d131SStephan Aßmus inline BString
_ReadLine()2007557d131SStephan Aßmus FsCreator::_ReadLine()
2017557d131SStephan Aßmus {
2027557d131SStephan Aßmus 	char line[255];
2037557d131SStephan Aßmus 
20420993ed9SMaurice Kalinowski 	std::cin.getline(line, sizeof(line), '\n');
2057557d131SStephan Aßmus 
2067557d131SStephan Aßmus 	return line;
2077557d131SStephan Aßmus }
208