* Copyright 2013, Axel DΓΆrfler, axeld@pinc-software.de.
* Copyright 2007, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#include "GPTPartitionHandle.h"
#include <new>
#include <stdio.h>
#include <DiskDeviceTypes.h>
#include <MutablePartition.h>
#include <PartitioningInfo.h>
#include <PartitionParameterEditor.h>
#include <Path.h>
#include <SupportDefs.h>
#include <AutoDeleter.h>
#include "guid.h"
#include "gpt_known_guids.h"
#include "utility.h"
#undef TRACE
#ifdef TRACE_GPT_PARTITION_HANDLE
# define TRACE(x...) printf(x)
#else
# define TRACE(x...) do {} while (false)
#endif
GPTPartitionHandle::GPTPartitionHandle(BMutablePartition* partition)
:
BPartitionHandle(partition)
{
}
GPTPartitionHandle::~GPTPartitionHandle()
{
}
status_t
GPTPartitionHandle::Init()
{
return B_OK;
}
uint32
GPTPartitionHandle::SupportedOperations(uint32 mask)
{
uint32 flags = B_DISK_SYSTEM_SUPPORTS_RESIZING
| B_DISK_SYSTEM_SUPPORTS_MOVING
| B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
| B_DISK_SYSTEM_SUPPORTS_NAME
| B_DISK_SYSTEM_SUPPORTS_SETTING_NAME
| B_DISK_SYSTEM_SUPPORTS_INITIALIZING;
if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) {
BPartitioningInfo info;
if (GetPartitioningInfo(&info) == B_OK
&& info.CountPartitionableSpaces() > 1) {
flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
}
}
return flags;
}
uint32
GPTPartitionHandle::SupportedChildOperations(const BMutablePartition* child,
uint32 mask)
{
return B_DISK_SYSTEM_SUPPORTS_NAME
| B_DISK_SYSTEM_SUPPORTS_SETTING_NAME
| B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
| B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
| B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
| B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS
| B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD;
}
status_t
GPTPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
int32* cookie, BString* type)
{
int32 index = *cookie;
TRACE("GPTPartitionHandle::GetNextSupportedType(child: %p, cookie: %" B_PRId32 ")\n",
child, index);
if (index >= int32(B_COUNT_OF(kTypeMap)))
return B_ENTRY_NOT_FOUND;
type->SetTo(kTypeMap[index].type);
*cookie = index + 1;
return B_OK;
}
status_t
GPTPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info)
{
off_t size = Partition()->ContentSize();
size_t headerSize = Partition()->BlockSize() + 16384;
status_t status = info->SetTo(Partition()->BlockSize() + headerSize,
size - Partition()->BlockSize() - 2 * headerSize);
if (status != B_OK)
return status;
size_t count = Partition()->CountChildren();
for (size_t index = 0; index < count; index++) {
BMutablePartition* child = Partition()->ChildAt(index);
status = info->ExcludeOccupiedSpace(child->Offset(), child->Size());
if (status != B_OK)
return status;
}
return B_OK;
}
status_t
GPTPartitionHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,
BPartitionParameterEditor** editor)
{
*editor = NULL;
if (type == B_CREATE_PARAMETER_EDITOR || type == B_PROPERTIES_PARAMETER_EDITOR) {
try {
*editor = new BPartitionParameterEditor();
} catch (std::bad_alloc&) {
return B_NO_MEMORY;
}
return B_OK;
}
return B_NOT_SUPPORTED;
}
status_t
GPTPartitionHandle::ValidateSetName(const BMutablePartition *child, BString* name)
{
size_t length = name->CountChars();
if (length == 0)
return B_OK;
size_t size = length * 2;
uint16 buffer[size + 1];
do {
size = to_ucs2(name->String(), length, buffer, length * 2);
if (size <= 36)
return B_OK;
length--;
name->TruncateChars(length, false);
} while (size > 36 && length > 0);
return B_OK;
}
status_t
GPTPartitionHandle::SetName(BMutablePartition* child, const char* name)
{
return child->SetName(name);
}
status_t
GPTPartitionHandle::ValidateSetType(const BMutablePartition* child,
const char* type)
{
for (size_t i = 0; i < B_COUNT_OF(kTypeMap); i++) {
if (strcmp(type, kTypeMap[i].type) == 0)
return B_OK;
}
return B_BAD_VALUE;
}
status_t
GPTPartitionHandle::SetType(BMutablePartition* child, const char* type)
{
return child->SetType(type);
}
status_t
GPTPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
const char* typeString, BString* name, const char* parameters)
{
return B_OK;
}
status_t
GPTPartitionHandle::CreateChild(off_t offset, off_t size,
const char* typeString, const char* name, const char* parameters,
BMutablePartition** _child)
{
BMutablePartition* partition = Partition();
BMutablePartition* child;
status_t status = partition->CreateChild(partition->CountChildren(),
typeString, name, parameters, &child);
if (status != B_OK)
return status;
child->SetOffset(offset);
child->SetSize(size);
child->SetBlockSize(partition->BlockSize());
*_child = child;
return B_OK;
}
status_t
GPTPartitionHandle::DeleteChild(BMutablePartition* child)
{
BMutablePartition* parent = child->Parent();
return parent->DeleteChild(child);
}