Beginnings of a little test partitioning tool.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21730 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src tests apps ;
|
SubDir HAIKU_TOP src tests apps ;
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src tests apps miniterminal ;
|
|
||||||
SubInclude HAIKU_TOP src tests apps fake_app_server ;
|
SubInclude HAIKU_TOP src tests apps fake_app_server ;
|
||||||
SubInclude HAIKU_TOP src tests apps installer ;
|
SubInclude HAIKU_TOP src tests apps installer ;
|
||||||
|
SubInclude HAIKU_TOP src tests apps miniterminal ;
|
||||||
|
SubInclude HAIKU_TOP src tests apps partitioner ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
SubDir HAIKU_TOP src tests apps partitioner ;
|
||||||
|
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
UsePrivateHeaders storage ;
|
||||||
|
|
||||||
|
SimpleTest Partitioner :
|
||||||
|
Partitioner.cpp
|
||||||
|
|
||||||
|
: be
|
||||||
|
;
|
||||||
@@ -0,0 +1,661 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <DiskDevice.h>
|
||||||
|
#include <DiskDeviceRoster.h>
|
||||||
|
#include <DiskDeviceVisitor.h>
|
||||||
|
#include <DiskSystem.h>
|
||||||
|
#include <PartitioningInfo.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" const char* __progname;
|
||||||
|
static const char* kProgramName = __progname;
|
||||||
|
|
||||||
|
static const char* kUsage =
|
||||||
|
"Usage: %s <options> <device>\n"
|
||||||
|
"\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -h, --help - print this help text\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_usage(bool error)
|
||||||
|
{
|
||||||
|
fprintf(error ? stderr : stdout, kUsage, kProgramName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_usage_and_exit(bool error)
|
||||||
|
{
|
||||||
|
print_usage(error);
|
||||||
|
exit(error ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_size_string(off_t _size, BString& string)
|
||||||
|
{
|
||||||
|
const char* suffixes[] = {
|
||||||
|
"", "K", "M", "G", "T", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
double size = _size;
|
||||||
|
int index = 0;
|
||||||
|
while (size > 1024 && suffixes[index + 1]) {
|
||||||
|
size /= 1024;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[128];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%.2f%s", size, suffixes[index]);
|
||||||
|
|
||||||
|
string = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PrintLongVisitor
|
||||||
|
class PrintLongVisitor : public BDiskDeviceVisitor {
|
||||||
|
public:
|
||||||
|
virtual bool Visit(BDiskDevice *device)
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
status_t error = device->GetPath(&path);
|
||||||
|
const char *pathString = NULL;
|
||||||
|
if (error == B_OK)
|
||||||
|
pathString = path.Path();
|
||||||
|
else
|
||||||
|
pathString = strerror(error);
|
||||||
|
printf("device %ld: \"%s\"\n", device->ID(), pathString);
|
||||||
|
printf(" has media: %d\n", device->HasMedia());
|
||||||
|
printf(" removable: %d\n", device->IsRemovableMedia());
|
||||||
|
printf(" read only: %d\n", device->IsReadOnlyMedia());
|
||||||
|
printf(" write once: %d\n", device->IsWriteOnceMedia());
|
||||||
|
printf(" ---\n");
|
||||||
|
Visit(device, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Visit(BPartition *partition, int32 level)
|
||||||
|
{
|
||||||
|
char prefix[128];
|
||||||
|
sprintf(prefix, "%*s", 2 * (int)level, "");
|
||||||
|
if (level > 0) {
|
||||||
|
BPath path;
|
||||||
|
status_t error = partition->GetPath(&path);
|
||||||
|
const char *pathString = NULL;
|
||||||
|
if (error == B_OK)
|
||||||
|
pathString = path.Path();
|
||||||
|
else
|
||||||
|
pathString = strerror(error);
|
||||||
|
printf("%spartition %ld: \"%s\"\n", prefix, partition->ID(),
|
||||||
|
pathString);
|
||||||
|
}
|
||||||
|
printf("%s offset: %lld\n", prefix, partition->Offset());
|
||||||
|
printf("%s size: %lld\n", prefix, partition->Size());
|
||||||
|
printf("%s block size: %lu\n", prefix, partition->BlockSize());
|
||||||
|
printf("%s index: %ld\n", prefix, partition->Index());
|
||||||
|
printf("%s status: %lu\n", prefix, partition->Status());
|
||||||
|
printf("%s file system: %d\n", prefix,
|
||||||
|
partition->ContainsFileSystem());
|
||||||
|
printf("%s part. system: %d\n", prefix,
|
||||||
|
partition->ContainsPartitioningSystem());
|
||||||
|
printf("%s device: %d\n", prefix, partition->IsDevice());
|
||||||
|
printf("%s read only: %d\n", prefix, partition->IsReadOnly());
|
||||||
|
printf("%s mounted: %d\n", prefix, partition->IsMounted());
|
||||||
|
printf("%s flags: %lx\n", prefix, partition->Flags());
|
||||||
|
printf("%s name: `%s'\n", prefix, partition->Name());
|
||||||
|
printf("%s content name: \"%s\"\n", prefix,
|
||||||
|
partition->ContentName());
|
||||||
|
printf("%s type: \"%s\"\n", prefix, partition->Type());
|
||||||
|
printf("%s content type: \"%s\"\n", prefix,
|
||||||
|
partition->ContentType());
|
||||||
|
// volume, icon,...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_partition_table_header()
|
||||||
|
{
|
||||||
|
printf(" Index Start Size Content Type "
|
||||||
|
"Content Name\n");
|
||||||
|
printf("--------------------------------------------------------------"
|
||||||
|
"------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_partition(BPartition* partition, int level, int index)
|
||||||
|
{
|
||||||
|
BString offset, size;
|
||||||
|
get_size_string(partition->Offset(), offset);
|
||||||
|
get_size_string(partition->Size(), size);
|
||||||
|
|
||||||
|
printf("%*s%02d%*s %8s %8s %26.26s %16.16s\n", 2 * level, "",
|
||||||
|
index,
|
||||||
|
2 * max_c(3 - level, 0), "",
|
||||||
|
offset.String(), size.String(),
|
||||||
|
(partition->ContentType() ? partition->ContentType() : "-"),
|
||||||
|
(partition->ContentName() ? partition->ContentName() : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PrintShortVisitor
|
||||||
|
class PrintShortVisitor : public BDiskDeviceVisitor {
|
||||||
|
public:
|
||||||
|
virtual bool Visit(BDiskDevice* device)
|
||||||
|
{
|
||||||
|
fIndex = 0;
|
||||||
|
|
||||||
|
// get path
|
||||||
|
BPath path;
|
||||||
|
status_t error = device->GetPath(&path);
|
||||||
|
const char *pathString = NULL;
|
||||||
|
if (error == B_OK)
|
||||||
|
pathString = path.Path();
|
||||||
|
else
|
||||||
|
pathString = strerror(error);
|
||||||
|
|
||||||
|
// check media present; if so which read/write abilities
|
||||||
|
const char* media;
|
||||||
|
const char* readWrite;
|
||||||
|
if (device->HasMedia()) {
|
||||||
|
if (device->IsRemovableMedia()) {
|
||||||
|
media = "removable media";
|
||||||
|
} else {
|
||||||
|
media = "fixed media";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device->IsReadOnlyMedia()) {
|
||||||
|
if (device->IsWriteOnceMedia())
|
||||||
|
readWrite = ", write once";
|
||||||
|
else
|
||||||
|
readWrite = ", read-only";
|
||||||
|
} else
|
||||||
|
readWrite = ", read/write";
|
||||||
|
} else {
|
||||||
|
media = "no media";
|
||||||
|
readWrite = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\ndevice %ld: \"%s\": %s%s\n\n", device->ID(), pathString,
|
||||||
|
media, readWrite);
|
||||||
|
print_partition_table_header();
|
||||||
|
|
||||||
|
Visit(device, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Visit(BPartition* partition, int32 level)
|
||||||
|
{
|
||||||
|
print_partition(partition, level, fIndex++);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// FindPartitionByIndexVisitor
|
||||||
|
class FindPartitionByIndexVisitor : public BDiskDeviceVisitor {
|
||||||
|
public:
|
||||||
|
FindPartitionByIndexVisitor(int index)
|
||||||
|
: fIndex(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Visit(BDiskDevice *device)
|
||||||
|
{
|
||||||
|
return Visit(device, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Visit(BPartition *partition, int32 level)
|
||||||
|
{
|
||||||
|
return (fIndex-- == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Partitioner
|
||||||
|
class Partitioner {
|
||||||
|
public:
|
||||||
|
Partitioner(BDiskDevice* device)
|
||||||
|
: fDevice(device),
|
||||||
|
fPrepared(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Run()
|
||||||
|
{
|
||||||
|
// prepare device modifications
|
||||||
|
if (fDevice->IsReadOnly()) {
|
||||||
|
printf("Device is read-only. Can't change anything.\n");
|
||||||
|
} else {
|
||||||
|
status_t error = fDevice->PrepareModifications();
|
||||||
|
fPrepared = (error == B_OK);
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf("Error: Failed to prepare device for modifications: "
|
||||||
|
"%s\n", strerror(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// main input loop
|
||||||
|
while (true) {
|
||||||
|
BString line;
|
||||||
|
if (!_ReadLine("> ", line))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (line == "") {
|
||||||
|
// do nothing
|
||||||
|
} else if (line == "h" || line == "help") {
|
||||||
|
_PrintHelp();
|
||||||
|
} else if (line == "i") {
|
||||||
|
_InitializePartition();
|
||||||
|
} else if (line == "l") {
|
||||||
|
_PrintPartitionsShort();
|
||||||
|
} else if (line == "ll") {
|
||||||
|
_PrintPartitionsLong();
|
||||||
|
} else if (line == "n") {
|
||||||
|
_NewPartition();
|
||||||
|
} else if (line == "q" || line == "quit") {
|
||||||
|
return;
|
||||||
|
} else if (line == "w") {
|
||||||
|
_WriteChanges();
|
||||||
|
} else {
|
||||||
|
printf("Invalid command \"%s\", type \"help\" for help\n",
|
||||||
|
line.String());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _PrintHelp()
|
||||||
|
{
|
||||||
|
printf("Valid commands:\n"
|
||||||
|
" h, help - prints this help text\n"
|
||||||
|
" i - initialize a partition\n"
|
||||||
|
" l - lists the device's partitions recursively\n"
|
||||||
|
" ll - lists the device's partitions recursively, long "
|
||||||
|
"format\n"
|
||||||
|
" l - create a new child partition\n"
|
||||||
|
" q, quit - quits the program, changes are discarded\n"
|
||||||
|
" w - write changes to disk\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _PrintPartitionsShort()
|
||||||
|
{
|
||||||
|
PrintShortVisitor visitor;
|
||||||
|
fDevice->VisitEachDescendant(&visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _PrintPartitionsLong()
|
||||||
|
{
|
||||||
|
PrintLongVisitor visitor;
|
||||||
|
fDevice->VisitEachDescendant(&visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _InitializePartition()
|
||||||
|
{
|
||||||
|
if (!fPrepared) {
|
||||||
|
if (fDevice->IsReadOnly())
|
||||||
|
printf("Device is read-only!\n");
|
||||||
|
else
|
||||||
|
printf("Sorry, not prepared for modifications!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the partition
|
||||||
|
int32 partitionIndex;
|
||||||
|
BPartition* partition = NULL;
|
||||||
|
if (!_SelectPartition("partition index [-1 to abort]: ", partition,
|
||||||
|
partitionIndex)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nselected partition:\n\n");
|
||||||
|
print_partition_table_header();
|
||||||
|
print_partition(partition, 0, partitionIndex);
|
||||||
|
|
||||||
|
// get available disk systems
|
||||||
|
BObjectList<BDiskSystem> diskSystems(20, true);
|
||||||
|
BDiskDeviceRoster roster;
|
||||||
|
{
|
||||||
|
BDiskSystem diskSystem;
|
||||||
|
while (roster.GetNextDiskSystem(&diskSystem) == B_OK) {
|
||||||
|
if (partition->CanInitialize(diskSystem.Name()))
|
||||||
|
diskSystems.AddItem(new BDiskSystem(diskSystem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diskSystems.IsEmpty()) {
|
||||||
|
printf("There are no disk systems, that can initialize this "
|
||||||
|
"partition.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the available disk systems
|
||||||
|
printf("\ndisk systems that can initialize the selected partition:\n");
|
||||||
|
for (int32 i = 0; BDiskSystem* diskSystem = diskSystems.ItemAt(i); i++)
|
||||||
|
printf("%2ld %s\n", i, diskSystem->Name());
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// get the disk system
|
||||||
|
BDiskSystem* diskSystem = NULL;
|
||||||
|
int64 diskSystemIndex;
|
||||||
|
do {
|
||||||
|
_ReadNumber("disk system index [-1 to abort]: ", diskSystemIndex);
|
||||||
|
if (diskSystemIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
diskSystem = diskSystems.ItemAt(diskSystemIndex);
|
||||||
|
if (!diskSystem)
|
||||||
|
printf("invalid index\n");
|
||||||
|
} while (!diskSystem);
|
||||||
|
|
||||||
|
BString name;
|
||||||
|
BString parameters;
|
||||||
|
while (true) {
|
||||||
|
// let the user enter name and parameters
|
||||||
|
// TODO: Obviously we should be able to check whether the disk system supports
|
||||||
|
// naming at all.
|
||||||
|
if (!_ReadLine("partition name: ", name)
|
||||||
|
|| !_ReadLine("partition parameters: ", parameters)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate parameters
|
||||||
|
char validatedName[B_OS_NAME_LENGTH];
|
||||||
|
strlcpy(validatedName, name.String(), sizeof(validatedName));
|
||||||
|
if (partition->ValidateInitialize(diskSystem->Name(), validatedName,
|
||||||
|
parameters.String()) != B_OK) {
|
||||||
|
printf("Validation of the given values failed. Sorry, can't "
|
||||||
|
"continue.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// did the disk system change the name?
|
||||||
|
if (name == validatedName) {
|
||||||
|
printf("Everything looks dandy.\n");
|
||||||
|
} else {
|
||||||
|
printf("The disk system adjusted the file name to \"%s\".\n",
|
||||||
|
validatedName);
|
||||||
|
name = validatedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let the user decide whether to continue, change parameters, or
|
||||||
|
// abort
|
||||||
|
bool changeParameters = false;
|
||||||
|
while (true) {
|
||||||
|
BString line;
|
||||||
|
_ReadLine("Everything looks dandy. [c]ontinue, change "
|
||||||
|
"[p]arameters, or [a]bort? ", line);
|
||||||
|
if (line == "a")
|
||||||
|
return;
|
||||||
|
if (line == "p") {
|
||||||
|
changeParameters = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (line == "c")
|
||||||
|
break;
|
||||||
|
|
||||||
|
printf("invalid input\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changeParameters)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize
|
||||||
|
status_t error = partition->Initialize(diskSystem->Name(),
|
||||||
|
name.String(), parameters.String());
|
||||||
|
if (error != B_OK)
|
||||||
|
printf("Initialization failed: %s\n", strerror(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _NewPartition()
|
||||||
|
{
|
||||||
|
if (!fPrepared) {
|
||||||
|
if (fDevice->IsReadOnly())
|
||||||
|
printf("Device is read-only!\n");
|
||||||
|
else
|
||||||
|
printf("Sorry, not prepared for modifications!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the parent partition
|
||||||
|
BPartition* partition = NULL;
|
||||||
|
int32 partitionIndex;
|
||||||
|
if (!_SelectPartition("parent partition index [-1 to abort]: ",
|
||||||
|
partition, partitionIndex)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nselected partition:\n\n");
|
||||||
|
print_partition_table_header();
|
||||||
|
print_partition(partition, 0, partitionIndex);
|
||||||
|
|
||||||
|
if (!partition->ContainsPartitioningSystem()) {
|
||||||
|
printf("The selected partition does not contain a partitioning "
|
||||||
|
"system.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the disk system
|
||||||
|
BDiskSystem diskSystem;
|
||||||
|
status_t error = partition->GetDiskSystem(&diskSystem);
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf("Failed to get disk system for partition: %s\n",
|
||||||
|
strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get supported types
|
||||||
|
BObjectList<BString> supportedTypes(20, true);
|
||||||
|
char typeBuffer[B_OS_NAME_LENGTH];
|
||||||
|
int32 cookie = 0;
|
||||||
|
while (diskSystem.GetNextSupportedType(partition, &cookie, typeBuffer)
|
||||||
|
== B_OK) {
|
||||||
|
supportedTypes.AddItem(new BString(typeBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportedTypes.IsEmpty()) {
|
||||||
|
printf("The partitioning system is not able to create any "
|
||||||
|
"child partition (no supported types).\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get partitioning info
|
||||||
|
BPartitioningInfo partitioningInfo;
|
||||||
|
error = partition->GetPartitioningInfo(&partitioningInfo);
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf("Failed to get partitioning info for partition: %s\n",
|
||||||
|
strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 spacesCount = partitioningInfo.CountPartitionableSpaces();
|
||||||
|
if (spacesCount == 0) {
|
||||||
|
printf("There's no space on the partition where a child partition "
|
||||||
|
"could be created\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// list partitionable spaces
|
||||||
|
printf("Unused regions where the new partition could be created:\n");
|
||||||
|
for (int32 i = 0; i < spacesCount; i++) {
|
||||||
|
off_t _offset;
|
||||||
|
off_t _size;
|
||||||
|
partitioningInfo.GetPartitionableSpaceAt(i, &_offset, &_size);
|
||||||
|
BString offset, size;
|
||||||
|
get_size_string(_offset, offset);
|
||||||
|
get_size_string(_size, size);
|
||||||
|
printf("%2ld start: %8s, size: %8s", i, offset.String(),
|
||||||
|
size.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:...
|
||||||
|
}
|
||||||
|
|
||||||
|
void _WriteChanges()
|
||||||
|
{
|
||||||
|
if (!fPrepared || !fDevice->IsModified()) {
|
||||||
|
printf("No changes have been made!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Writing changes to disk. This can take a while...\n");
|
||||||
|
|
||||||
|
// commit
|
||||||
|
status_t error = fDevice->CommitModifications();
|
||||||
|
if (error == B_OK) {
|
||||||
|
printf("All changes have been written successfully!\n");
|
||||||
|
} else {
|
||||||
|
printf("Failed to write all changes: %s\n", strerror(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare again
|
||||||
|
error = fDevice->PrepareModifications();
|
||||||
|
fPrepared = (error == B_OK);
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf("Error: Failed to prepare device for modifications: "
|
||||||
|
"%s\n", strerror(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _SelectPartition(const char* prompt, BPartition*& partition,
|
||||||
|
int32& _partitionIndex)
|
||||||
|
{
|
||||||
|
// if the disk device has no children, we select it without asking
|
||||||
|
if (fDevice->CountChildren() == 0) {
|
||||||
|
partition = fDevice;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise let the user select
|
||||||
|
partition = NULL;
|
||||||
|
int64 partitionIndex;
|
||||||
|
while (true) {
|
||||||
|
_ReadNumber(prompt, partitionIndex);
|
||||||
|
if (partitionIndex < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FindPartitionByIndexVisitor visitor(partitionIndex);
|
||||||
|
partition = fDevice->VisitEachDescendant(&visitor);
|
||||||
|
if (partition) {
|
||||||
|
_partitionIndex = partitionIndex;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("invalid partition index\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _ReadLine(const char* prompt, BString& _line)
|
||||||
|
{
|
||||||
|
// prompt
|
||||||
|
printf(prompt);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
// read line
|
||||||
|
char line[256];
|
||||||
|
if (!fgets(line, sizeof(line), stdin))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// remove trailing '\n'
|
||||||
|
if (char* trailingNL = strchr(line, '\n'))
|
||||||
|
*trailingNL = '\0';
|
||||||
|
|
||||||
|
_line = line;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _ReadNumber(const char* prompt, int64& number)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
BString line;
|
||||||
|
if (!_ReadLine(prompt, line))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
if (sscanf(line.String(), "%lld%s", &number, buffer) == 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
printf("invalid input\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BDiskDevice* fDevice;
|
||||||
|
bool fPrepared;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, const char* const* argv)
|
||||||
|
{
|
||||||
|
// parse arguments
|
||||||
|
int argi = 1;
|
||||||
|
for (; argi < argc; argi++) {
|
||||||
|
const char* arg = argv[argi];
|
||||||
|
if (arg[0] == '-') {
|
||||||
|
if (arg[1] == '-') {
|
||||||
|
// a double '-' option
|
||||||
|
if (strcmp(arg, "--help") == 0) {
|
||||||
|
print_usage_and_exit(false);
|
||||||
|
} else
|
||||||
|
print_usage_and_exit(true);
|
||||||
|
} else {
|
||||||
|
// single '-' options
|
||||||
|
for (int i = 1; arg[i] != '\0'; i++) {
|
||||||
|
switch (arg[i]) {
|
||||||
|
case 'h':
|
||||||
|
print_usage_and_exit(false);
|
||||||
|
default:
|
||||||
|
print_usage_and_exit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only the device path should remain
|
||||||
|
if (argi != argc - 1)
|
||||||
|
print_usage_and_exit(true);
|
||||||
|
const char* devicePath = argv[argi];
|
||||||
|
|
||||||
|
// get the disk device
|
||||||
|
BDiskDeviceRoster roster;
|
||||||
|
BDiskDevice device;
|
||||||
|
status_t error = roster.GetDeviceForPath(devicePath, &device);
|
||||||
|
if (error != B_OK) {
|
||||||
|
fprintf(stderr, "Error: Failed to get disk device for path \"%s\": "
|
||||||
|
"%s\n", devicePath, strerror(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
Partitioner partitioner(&device);
|
||||||
|
partitioner.Run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user