* Copyright 2008-2009 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Marco Minutoli, mminutoli@gmail.com
* Axel DΓΆrfler, axeld@pinc-software.de
*/
#include "FsCreator.h"
#include <iostream>
#include <DiskSystem.h>
class UnregisterFileDevice {
public:
UnregisterFileDevice()
:
fID(-1)
{
}
~UnregisterFileDevice()
{
if (fID >= 0) {
BDiskDeviceRoster roster;
roster.UnregisterFileDevice(fID);
}
}
void SetTo(partition_id id)
{
fID = id;
}
void Detach()
{
fID = -1;
}
private:
partition_id fID;
};
extern "C" const char* __progname;
static const char* kProgramName = __progname;
FsCreator::FsCreator(const char* path, const char* type, const char* volumeName,
const char* fsOptions, bool quick, bool verbose)
:
fType(type),
fPath(path),
fVolumeName(volumeName),
fFsOptions(fsOptions),
fVerbose(verbose),
fQuick(quick)
{
}
bool
FsCreator::Run()
{
UnregisterFileDevice unregisterFileDevice;
BDiskDeviceRoster roster;
BPartition* partition;
BDiskDevice device;
status_t status = roster.GetPartitionForPath(fPath, &device,
&partition);
if (status != B_OK) {
if (!strncmp(fPath, "/dev", 4)) {
std::cerr << kProgramName << ": Failed to get disk device for path "
<< fPath << ": " << strerror(status) << std::endl;
return false;
}
partition_id id = roster.RegisterFileDevice(fPath);
if (id < B_OK) {
std::cerr << kProgramName << ": Could not register file device for "
"path " << fPath << ": " << strerror(status) << std::endl;
return false;
}
unregisterFileDevice.SetTo(id);
status = roster.GetPartitionWithID(id, &device, &partition);
if (!strncmp(fPath, "/dev", 4)) {
std::cerr << kProgramName << ": Cannot find registered file device "
"for path " << fPath << ": " << strerror(status)
<< std::endl;
return false;
}
}
if (partition->IsReadOnly()) {
std::cerr << kProgramName << ": Cannot initialize read-only device.\n";
return false;
}
if (partition->IsMounted()) {
std::cerr << kProgramName << ": Cannot initialize mounted device.\n";
return false;
}
BDiskSystem diskSystem;
if (roster.GetDiskSystem(&diskSystem, fType) != B_OK) {
std::cerr << kProgramName << ": " << fType
<< " is an invalid or unsupported file system type.\n";
return false;
}
status = device.PrepareModifications();
if (status != B_OK) {
std::cerr << kProgramName << ": A problem occurred preparing the "
"device for the modifications\n";
return false;
}
if (fVerbose)
std::cout << "Preparing for modifications...\n\n";
BString name(fVolumeName);
if (partition->ValidateInitialize(diskSystem.PrettyName(),
&name, fFsOptions) != B_OK) {
std::cerr << kProgramName << ": Parameters validation failed. "
"Check what you wrote\n";
std::cerr << status;
return false;
}
if (fVerbose)
std::cout << "Parameters Validation...\n\n";
if (name != fVolumeName) {
std::cout << "Volume name was adjusted to "
<< name.String() << std::endl;
}
status = partition->Initialize(diskSystem.PrettyName(), name.String(),
fFsOptions);
if (status != B_OK) {
std::cerr << kProgramName << ": Initialization failed: "
<< strerror(status) << std::endl;
return false;
}
if (!fQuick) {
std::cout << "\nAbout to initialize " << fPath << " with "
<< diskSystem.PrettyName()
<< "\nAre you sure you want to do this now?\n"
<< "\nALL YOUR DATA in " << fPath << " will be lost forever.\n";
BString reply;
do {
std::cout << "Continue (yes|[no])? ";
reply = _ReadLine();
if (reply == "")
reply = "no";
} while (reply != "yes" && reply != "no");
if (reply != "yes")
return true;
}
BString contentName = partition->ContentName();
status = device.CommitModifications();
if (status == B_OK) {
if (fVerbose) {
std::cout << "Volume \"" << contentName.String()
<< "\" has been initialized successfully!" << std::endl;
}
} else {
std::cout << kProgramName << ": Initialization of \""
<< contentName.String() << "\" failed: " << strerror(status)
<< std::endl;
return false;
}
unregisterFileDevice.Detach();
return true;
}
inline BString
FsCreator::_ReadLine()
{
char line[255];
std::cin.getline(line, sizeof(line), '\n');
return line;
}