status_t ExtendedPartitionHandle::DeleteChild(BMutablePartition* child) { BMutablePartition* parent = child->Parent(); status_t error = parent->DeleteChild(child); return error; }
status_t ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) { // init to the full size (minus the first PTS_OFFSET) BMutablePartition* partition = Partition(); off_t offset = partition->Offset() + PTS_OFFSET; off_t size = partition->Size() - PTS_OFFSET; status_t error = info->SetTo(offset, size); if (error != B_OK) return error; // exclude the space of the existing logical partitions int32 count = partition->CountChildren(); for (int32 i = 0; i < count; i++) { BMutablePartition* child = partition->ChildAt(i); error = info->ExcludeOccupiedSpace(child->Offset(), child->Size() + PTS_OFFSET + Partition()->BlockSize()); if (error != B_OK) return error; LogicalPartition* logical = (LogicalPartition*)child->ChildCookie(); if (logical == NULL) return B_BAD_VALUE; error = info->ExcludeOccupiedSpace( logical->PartitionTableOffset(), PTS_OFFSET + Partition()->BlockSize()); if (error != B_OK) return error; } return B_OK; }
status_t ExtendedPartitionHandle::Init() { // initialize the extended partition from the mutable partition BMutablePartition* partition = Partition(); // our parent has already set the child cookie to the primary partition. fPrimaryPartition = (PrimaryPartition*)partition->ChildCookie(); if (!fPrimaryPartition) return B_BAD_VALUE; if (!fPrimaryPartition->IsExtended()) return B_BAD_VALUE; // init the child partitions int32 count = partition->CountChildren(); for (int32 i = 0; i < count; i++) { BMutablePartition* child = partition->ChildAt(i); PartitionType type; if (!type.SetType(child->Type())) return B_BAD_VALUE; void* handle = parse_driver_settings_string(child->Parameters()); if (handle == NULL) return B_ERROR; bool active = get_driver_boolean_parameter( handle, "active", false, true); off_t ptsOffset = 0; const char* buffer = get_driver_parameter(handle, "partition_table_offset", NULL, NULL); if (buffer != NULL) ptsOffset = strtoull(buffer, NULL, 10); else { delete_driver_settings(handle); return B_BAD_VALUE; } delete_driver_settings(handle); LogicalPartition* logical = new(nothrow) LogicalPartition; if (!logical) return B_NO_MEMORY; logical->SetTo(child->Offset(), child->Size(), type.Type(), active, ptsOffset, fPrimaryPartition); child->SetChildCookie(logical); } return B_OK; }
// CreateChild status_t BPartition::Delegate::CreateChild(off_t start, off_t size, const char* type, const char* name, const char* parameters, BPartition** child) { if (!fPartitionHandle) return B_NO_INIT; BMutablePartition* mutableChild; status_t error = fPartitionHandle->CreateChild(start, size, type, name, parameters, &mutableChild); if (error != B_OK) return error; if (child) *child = mutableChild->GetDelegate()->Partition(); return B_OK; }
uint32 PartitionMapHandle::SupportedOperations(uint32 mask) { BMutablePartition* partition = Partition(); uint32 flags = B_DISK_SYSTEM_SUPPORTS_RESIZING | B_DISK_SYSTEM_SUPPORTS_MOVING | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS | B_DISK_SYSTEM_SUPPORTS_INITIALIZING; // creating child if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) { BPartitioningInfo info; if (partition->CountChildren() < 4 && GetPartitioningInfo(&info) == B_OK && info.CountPartitionableSpaces() > 1) { flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; } } return flags; }
status_t GPTPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) { // init to the full size (minus the GPT table header and entries) off_t size = Partition()->ContentSize(); // TODO: use fHeader 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; // Exclude the space of the existing partitions 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 PartitionMapHandle::Init() { // initialize the partition map from the mutable partition BMutablePartition* partition = Partition(); int32 count = partition->CountChildren(); if (count > 4) return B_BAD_VALUE; int32 extendedCount = 0; for (int32 i = 0; i < count; i++) { BMutablePartition* child = partition->ChildAt(i); PartitionType type; if (!type.SetType(child->Type())) return B_BAD_VALUE; // only one extended partition is allowed if (type.IsExtended()) { if (++extendedCount > 1) return B_BAD_VALUE; } // TODO: Get these from the parameters. int32 index = i; bool active = false; PrimaryPartition* primary = fPartitionMap.PrimaryPartitionAt(index); primary->SetTo(child->Offset(), child->Size(), type.Type(), active, partition->BlockSize()); child->SetChildCookie(primary); } // The extended partition (if any) is initialized by // ExtendedPartitionHandle::Init(). return B_OK; }
status_t GPTPartitionHandle::CreateChild(off_t offset, off_t size, const char* typeString, const char* name, const char* parameters, BMutablePartition** _child) { // create the child BMutablePartition* partition = Partition(); BMutablePartition* child; status_t status = partition->CreateChild(partition->CountChildren(), typeString, name, parameters, &child); if (status != B_OK) return status; // init the child child->SetOffset(offset); child->SetSize(size); child->SetBlockSize(partition->BlockSize()); *_child = child; return B_OK; }
status_t ExtendedPartitionHandle::CreateChild(off_t offset, off_t size, const char* typeString, const char* name, const char* _parameters, BMutablePartition** _child) { // check type PartitionType type; if (!type.SetType(typeString) || type.IsEmpty()) return B_BAD_VALUE; // check name if (name != NULL && name[0] != '\0') return B_BAD_VALUE; // offset properly aligned? if (offset != sector_align(offset, Partition()->BlockSize()) || size != sector_align(size, Partition()->BlockSize())) return B_BAD_VALUE; // check the free space situation BPartitioningInfo info; status_t error = GetPartitioningInfo(&info); if (error != B_OK) return error; bool foundSpace = false; off_t end = offset + size; int32 spacesCount = info.CountPartitionableSpaces(); for (int32 i = 0; i < spacesCount; i++) { off_t spaceOffset, spaceSize; info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); off_t spaceEnd = spaceOffset + spaceSize; if (offset >= spaceOffset && end <= spaceEnd) { foundSpace = true; break; } } if (!foundSpace) return B_BAD_VALUE; BString parameters(_parameters); parameters << "partition_table_offset " << offset - PTS_OFFSET << " ;\n"; // everything looks good, create the child BMutablePartition* child; error = Partition()->CreateChild(-1, typeString, NULL, parameters.String(), &child); if (error != B_OK) return error; // init the child child->SetOffset(offset); child->SetSize(size); child->SetBlockSize(Partition()->BlockSize()); //child->SetFlags(0); child->SetChildCookie(Partition()); *_child = child; return B_OK; }
status_t GPTPartitionHandle::DeleteChild(BMutablePartition* child) { BMutablePartition* parent = child->Parent(); return parent->DeleteChild(child); }
status_t PartitionMapHandle::CreateChild(off_t offset, off_t size, const char* typeString, const char* name, const char* parameters, BMutablePartition** _child) { // check type PartitionType type; if (!type.SetType(typeString) || type.IsEmpty()) return B_BAD_VALUE; if (type.IsExtended() && fPartitionMap.ExtendedPartitionIndex() >= 0) return B_BAD_VALUE; // check name if (name && *name != '\0') return B_BAD_VALUE; // check parameters void* handle = parse_driver_settings_string(parameters); if (handle == NULL) return B_ERROR; bool active = get_driver_boolean_parameter(handle, "active", false, true); delete_driver_settings(handle); // get a spare primary partition PrimaryPartition* primary = NULL; for (int32 i = 0; i < 4; i++) { if (fPartitionMap.PrimaryPartitionAt(i)->IsEmpty()) { primary = fPartitionMap.PrimaryPartitionAt(i); break; } } if (!primary) return B_BAD_VALUE; // offset properly aligned? if (offset != sector_align(offset, Partition()->BlockSize()) || size != sector_align(size, Partition()->BlockSize())) return B_BAD_VALUE; // check the free space situation BPartitioningInfo info; status_t error = GetPartitioningInfo(&info); if (error != B_OK) return error; bool foundSpace = false; off_t end = offset + size; int32 spacesCount = info.CountPartitionableSpaces(); for (int32 i = 0; i < spacesCount; i++) { off_t spaceOffset, spaceSize; info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); off_t spaceEnd = spaceOffset + spaceSize; if (offset >= spaceOffset && end <= spaceEnd) { foundSpace = true; break; } } if (!foundSpace) return B_BAD_VALUE; // create the child // (Note: the primary partition index is indeed the child index, since // we picked the first empty primary partition.) BMutablePartition* partition = Partition(); BMutablePartition* child; error = partition->CreateChild(primary->Index(), typeString, name, parameters, &child); if (error != B_OK) return error; // init the child child->SetOffset(offset); child->SetSize(size); child->SetBlockSize(partition->BlockSize()); //child->SetFlags(0); child->SetChildCookie(primary); // init the primary partition primary->SetTo(offset, size, type.Type(), active, partition->BlockSize()); *_child = child; return B_OK; }
// ChildAt BPartition::Delegate* BPartition::Delegate::ChildAt(int32 index) const { BMutablePartition* child = fMutablePartition.ChildAt(index); return child ? child->GetDelegate() : NULL; }