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