191c21ff4SIngo Weinhold /* 291c21ff4SIngo Weinhold * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. 391c21ff4SIngo Weinhold * Distributed under the terms of the MIT License. 491c21ff4SIngo Weinhold */ 591c21ff4SIngo Weinhold 691c21ff4SIngo Weinhold #include "ExtendedPartitionAddOn.h" 791c21ff4SIngo Weinhold 891c21ff4SIngo Weinhold #include <new> 97ba970b9SStephan Aßmus #include <stdio.h> 1091c21ff4SIngo Weinhold 1191c21ff4SIngo Weinhold #include <DiskDeviceTypes.h> 1291c21ff4SIngo Weinhold #include <MutablePartition.h> 13fd6477d3SStephan Aßmus #include <PartitioningInfo.h> 14fd6477d3SStephan Aßmus 15fd6477d3SStephan Aßmus #include <AutoDeleter.h> 1691c21ff4SIngo Weinhold 175f1b31deSAxel Dörfler #include "IntelDiskSystem.h" 185f1b31deSAxel Dörfler 197ba970b9SStephan Aßmus //#define TRACE_EXTENDED_PARTITION_ADD_ON 207ba970b9SStephan Aßmus #undef TRACE 217ba970b9SStephan Aßmus #ifdef TRACE_EXTENDED_PARTITION_ADD_ON 227ba970b9SStephan Aßmus # define TRACE(x...) printf(x) 237ba970b9SStephan Aßmus #else 247ba970b9SStephan Aßmus # define TRACE(x...) do {} while (false) 257ba970b9SStephan Aßmus #endif 267ba970b9SStephan Aßmus 2793134c5eSBryce Groff #define PTS_OFFSET (63 * Partition()->BlockSize()) 2891c21ff4SIngo Weinhold 2991c21ff4SIngo Weinhold using std::nothrow; 3091c21ff4SIngo Weinhold 3191c21ff4SIngo Weinhold 32fd6477d3SStephan Aßmus static const uint32 kDiskSystemFlags = 33fd6477d3SStephan Aßmus 0 34fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_CHECKING 35fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_REPAIRING 36fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_RESIZING 37fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_MOVING 38fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME 39fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS 401987b05aSBryce Groff // | B_DISK_SYSTEM_SUPPORTS_INITIALIZING 41fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME 42fd6477d3SStephan Aßmus 43fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD 44fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD 45fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME 46fd6477d3SStephan Aßmus | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE 47fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS 48fd6477d3SStephan Aßmus | B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD 49fd6477d3SStephan Aßmus | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD 50fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_NAME 51fd6477d3SStephan Aßmus ; 52fd6477d3SStephan Aßmus 53fd6477d3SStephan Aßmus 5491c21ff4SIngo Weinhold // #pragma mark - ExtendedPartitionAddOn 5591c21ff4SIngo Weinhold 5691c21ff4SIngo Weinhold 5791c21ff4SIngo Weinhold // constructor 5891c21ff4SIngo Weinhold ExtendedPartitionAddOn::ExtendedPartitionAddOn() 59fd6477d3SStephan Aßmus : BDiskSystemAddOn(kPartitionTypeIntelExtended, kDiskSystemFlags) 6091c21ff4SIngo Weinhold { 6191c21ff4SIngo Weinhold } 6291c21ff4SIngo Weinhold 6391c21ff4SIngo Weinhold 6491c21ff4SIngo Weinhold // destructor 6591c21ff4SIngo Weinhold ExtendedPartitionAddOn::~ExtendedPartitionAddOn() 6691c21ff4SIngo Weinhold { 6791c21ff4SIngo Weinhold } 6891c21ff4SIngo Weinhold 6991c21ff4SIngo Weinhold 7091c21ff4SIngo Weinhold // CreatePartitionHandle 7191c21ff4SIngo Weinhold status_t 7291c21ff4SIngo Weinhold ExtendedPartitionAddOn::CreatePartitionHandle(BMutablePartition* partition, 7391c21ff4SIngo Weinhold BPartitionHandle** _handle) 7491c21ff4SIngo Weinhold { 7591c21ff4SIngo Weinhold ExtendedPartitionHandle* handle 7691c21ff4SIngo Weinhold = new(nothrow) ExtendedPartitionHandle(partition); 7791c21ff4SIngo Weinhold if (!handle) 7891c21ff4SIngo Weinhold return B_NO_MEMORY; 7991c21ff4SIngo Weinhold 8091c21ff4SIngo Weinhold status_t error = handle->Init(); 8191c21ff4SIngo Weinhold if (error != B_OK) { 8291c21ff4SIngo Weinhold delete handle; 8391c21ff4SIngo Weinhold return error; 8491c21ff4SIngo Weinhold } 8591c21ff4SIngo Weinhold 8691c21ff4SIngo Weinhold *_handle = handle; 8791c21ff4SIngo Weinhold return B_OK; 8891c21ff4SIngo Weinhold } 8991c21ff4SIngo Weinhold 9091c21ff4SIngo Weinhold 91fd6477d3SStephan Aßmus // CanInitialize 92fd6477d3SStephan Aßmus bool 93fd6477d3SStephan Aßmus ExtendedPartitionAddOn::CanInitialize(const BMutablePartition* partition) 94fd6477d3SStephan Aßmus { 95fd6477d3SStephan Aßmus // If it's big enough, we can initialize it. 961987b05aSBryce Groff return false; 97fd6477d3SStephan Aßmus } 98fd6477d3SStephan Aßmus 99fd6477d3SStephan Aßmus 100fd6477d3SStephan Aßmus // GetInitializationParameterEditor 101fd6477d3SStephan Aßmus status_t 102fd6477d3SStephan Aßmus ExtendedPartitionAddOn::GetInitializationParameterEditor( 1037f96148cSIngo Weinhold const BMutablePartition* partition, BPartitionParameterEditor** editor) 104fd6477d3SStephan Aßmus { 105fd6477d3SStephan Aßmus // Nothing to edit, really. 106fd6477d3SStephan Aßmus *editor = NULL; 107fd6477d3SStephan Aßmus return B_OK; 108fd6477d3SStephan Aßmus } 109fd6477d3SStephan Aßmus 110fd6477d3SStephan Aßmus 111fd6477d3SStephan Aßmus // ValidateInitialize 112fd6477d3SStephan Aßmus status_t 113fd6477d3SStephan Aßmus ExtendedPartitionAddOn::ValidateInitialize(const BMutablePartition* partition, 114fd6477d3SStephan Aßmus BString* name, const char* parameters) 115fd6477d3SStephan Aßmus { 116fd6477d3SStephan Aßmus if (!CanInitialize(partition) 117*10d05234SAxel Dörfler || (parameters != NULL && parameters[0] != '\0')) { 118fd6477d3SStephan Aßmus return B_BAD_VALUE; 119fd6477d3SStephan Aßmus } 120fd6477d3SStephan Aßmus 121fd6477d3SStephan Aßmus // we don't support a content name 122fd6477d3SStephan Aßmus if (name != NULL) 123fd6477d3SStephan Aßmus name->Truncate(0); 124fd6477d3SStephan Aßmus 125fd6477d3SStephan Aßmus return B_OK; 126fd6477d3SStephan Aßmus } 127fd6477d3SStephan Aßmus 128fd6477d3SStephan Aßmus 129fd6477d3SStephan Aßmus // Initialize 130fd6477d3SStephan Aßmus status_t 131fd6477d3SStephan Aßmus ExtendedPartitionAddOn::Initialize(BMutablePartition* partition, 132fd6477d3SStephan Aßmus const char* name, const char* parameters, BPartitionHandle** _handle) 133fd6477d3SStephan Aßmus { 134fd6477d3SStephan Aßmus if (!CanInitialize(partition) 135*10d05234SAxel Dörfler || (name != NULL && name[0] != '\0') 136*10d05234SAxel Dörfler || (parameters != NULL && parameters[0] != '\0')) { 137fd6477d3SStephan Aßmus return B_BAD_VALUE; 138fd6477d3SStephan Aßmus } 139fd6477d3SStephan Aßmus 140fd6477d3SStephan Aßmus // create the handle 141fd6477d3SStephan Aßmus ExtendedPartitionHandle* handle 142fd6477d3SStephan Aßmus = new(nothrow) ExtendedPartitionHandle(partition); 143fd6477d3SStephan Aßmus if (!handle) 144fd6477d3SStephan Aßmus return B_NO_MEMORY; 145fd6477d3SStephan Aßmus ObjectDeleter<ExtendedPartitionHandle> handleDeleter(handle); 146fd6477d3SStephan Aßmus 147fd6477d3SStephan Aßmus // init the partition 148fd6477d3SStephan Aßmus status_t error = partition->SetContentType(Name()); 149fd6477d3SStephan Aßmus if (error != B_OK) 150fd6477d3SStephan Aßmus return error; 151fd6477d3SStephan Aßmus // TODO: The content type could as well be set by the caller. 152fd6477d3SStephan Aßmus 153fd6477d3SStephan Aßmus partition->SetContentName(NULL); 154fd6477d3SStephan Aßmus partition->SetContentParameters(NULL); 1555f1b31deSAxel Dörfler partition->SetContentSize( 1565f1b31deSAxel Dörfler sector_align(partition->Size(), partition->BlockSize())); 157fd6477d3SStephan Aßmus 158fd6477d3SStephan Aßmus *_handle = handleDeleter.Detach(); 159fd6477d3SStephan Aßmus 160fd6477d3SStephan Aßmus return B_OK; 161fd6477d3SStephan Aßmus } 162fd6477d3SStephan Aßmus 163fd6477d3SStephan Aßmus 16491c21ff4SIngo Weinhold // #pragma mark - ExtendedPartitionHandle 16591c21ff4SIngo Weinhold 16691c21ff4SIngo Weinhold 16791c21ff4SIngo Weinhold // constructor 16891c21ff4SIngo Weinhold ExtendedPartitionHandle::ExtendedPartitionHandle(BMutablePartition* partition) 16991c21ff4SIngo Weinhold : BPartitionHandle(partition) 17091c21ff4SIngo Weinhold { 17191c21ff4SIngo Weinhold } 17291c21ff4SIngo Weinhold 17391c21ff4SIngo Weinhold 17491c21ff4SIngo Weinhold // destructor 17591c21ff4SIngo Weinhold ExtendedPartitionHandle::~ExtendedPartitionHandle() 17691c21ff4SIngo Weinhold { 17791c21ff4SIngo Weinhold } 17891c21ff4SIngo Weinhold 17991c21ff4SIngo Weinhold 18091c21ff4SIngo Weinhold // Init 18191c21ff4SIngo Weinhold status_t 18291c21ff4SIngo Weinhold ExtendedPartitionHandle::Init() 18391c21ff4SIngo Weinhold { 18491c21ff4SIngo Weinhold // initialize the extended partition from the mutable partition 18591c21ff4SIngo Weinhold 18691c21ff4SIngo Weinhold BMutablePartition* partition = Partition(); 18791c21ff4SIngo Weinhold 18891c21ff4SIngo Weinhold // our parent has already set the child cookie to the primary partition. 18991c21ff4SIngo Weinhold fPrimaryPartition = (PrimaryPartition*)partition->ChildCookie(); 19091c21ff4SIngo Weinhold if (!fPrimaryPartition) 19191c21ff4SIngo Weinhold return B_BAD_VALUE; 19291c21ff4SIngo Weinhold 19391c21ff4SIngo Weinhold if (!fPrimaryPartition->IsExtended()) 19491c21ff4SIngo Weinhold return B_BAD_VALUE; 19591c21ff4SIngo Weinhold 19691c21ff4SIngo Weinhold // init the child partitions 19791c21ff4SIngo Weinhold int32 count = partition->CountChildren(); 19891c21ff4SIngo Weinhold for (int32 i = 0; i < count; i++) { 19991c21ff4SIngo Weinhold BMutablePartition* child = partition->ChildAt(i); 20093134c5eSBryce Groff 20191c21ff4SIngo Weinhold PartitionType type; 20291c21ff4SIngo Weinhold if (!type.SetType(child->Type())) 20391c21ff4SIngo Weinhold return B_BAD_VALUE; 20491c21ff4SIngo Weinhold 20593134c5eSBryce Groff void* handle = parse_driver_settings_string(child->Parameters()); 20693134c5eSBryce Groff if (handle == NULL) 20793134c5eSBryce Groff return B_ERROR; 20893134c5eSBryce Groff 20993134c5eSBryce Groff bool active = get_driver_boolean_parameter( 21093134c5eSBryce Groff handle, "active", false, true); 21193134c5eSBryce Groff 21291c21ff4SIngo Weinhold off_t ptsOffset = 0; 21393134c5eSBryce Groff const char* buffer = get_driver_parameter(handle, 21493134c5eSBryce Groff "partition_table_offset", NULL, NULL); 21593134c5eSBryce Groff if (buffer != NULL) 21693134c5eSBryce Groff ptsOffset = strtoull(buffer, NULL, 10); 21793134c5eSBryce Groff else { 21893134c5eSBryce Groff delete_driver_settings(handle); 21993134c5eSBryce Groff return B_BAD_VALUE; 22093134c5eSBryce Groff } 22193134c5eSBryce Groff delete_driver_settings(handle); 22291c21ff4SIngo Weinhold 22391c21ff4SIngo Weinhold LogicalPartition* logical = new(nothrow) LogicalPartition; 22491c21ff4SIngo Weinhold if (!logical) 22591c21ff4SIngo Weinhold return B_NO_MEMORY; 22691c21ff4SIngo Weinhold 22791c21ff4SIngo Weinhold logical->SetTo(child->Offset(), child->Size(), type.Type(), active, 22891c21ff4SIngo Weinhold ptsOffset, fPrimaryPartition); 22991c21ff4SIngo Weinhold 23091c21ff4SIngo Weinhold child->SetChildCookie(logical); 23191c21ff4SIngo Weinhold } 23291c21ff4SIngo Weinhold 23391c21ff4SIngo Weinhold return B_OK; 23491c21ff4SIngo Weinhold } 235fd6477d3SStephan Aßmus 236fd6477d3SStephan Aßmus 237fd6477d3SStephan Aßmus // SupportedOperations 238fd6477d3SStephan Aßmus uint32 239fd6477d3SStephan Aßmus ExtendedPartitionHandle::SupportedOperations(uint32 mask) 240fd6477d3SStephan Aßmus { 24193134c5eSBryce Groff uint32 flags = 0; 242fd6477d3SStephan Aßmus 243fd6477d3SStephan Aßmus // creating child 244fd6477d3SStephan Aßmus if (mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) { 245fd6477d3SStephan Aßmus BPartitioningInfo info; 246fd6477d3SStephan Aßmus if (GetPartitioningInfo(&info) == B_OK 247fd6477d3SStephan Aßmus && info.CountPartitionableSpaces() > 1) { 248fd6477d3SStephan Aßmus flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; 249fd6477d3SStephan Aßmus } 250fd6477d3SStephan Aßmus } 251fd6477d3SStephan Aßmus 252fd6477d3SStephan Aßmus return flags; 253fd6477d3SStephan Aßmus } 254fd6477d3SStephan Aßmus 255fd6477d3SStephan Aßmus 256fd6477d3SStephan Aßmus // SupportedChildOperations 257fd6477d3SStephan Aßmus uint32 258fd6477d3SStephan Aßmus ExtendedPartitionHandle::SupportedChildOperations( 259fd6477d3SStephan Aßmus const BMutablePartition* child, uint32 mask) 260fd6477d3SStephan Aßmus { 261fd6477d3SStephan Aßmus return B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD; 262fd6477d3SStephan Aßmus } 263fd6477d3SStephan Aßmus 264fd6477d3SStephan Aßmus 265fd6477d3SStephan Aßmus // GetNextSupportedType 266fd6477d3SStephan Aßmus status_t 267fd6477d3SStephan Aßmus ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child, 268fd6477d3SStephan Aßmus int32* cookie, BString* type) 269fd6477d3SStephan Aßmus { 2701987b05aSBryce Groff int32 index = *cookie; 2711987b05aSBryce Groff const partition_type* nextType; 2721987b05aSBryce Groff PartitionMap partitionMap; 2731987b05aSBryce Groff while (true) { 2741987b05aSBryce Groff nextType = partitionMap.GetNextSupportedPartitionType(index); 2751987b05aSBryce Groff if (nextType == NULL) 276fd6477d3SStephan Aßmus return B_ENTRY_NOT_FOUND; 2771987b05aSBryce Groff index++; 2781987b05aSBryce Groff if (nextType->used 2791987b05aSBryce Groff && strcmp(nextType->name, kPartitionTypeIntelExtended) != 0) 2801987b05aSBryce Groff break; 2811987b05aSBryce Groff } 2821987b05aSBryce Groff 2831987b05aSBryce Groff if (!nextType) 2841987b05aSBryce Groff return B_ENTRY_NOT_FOUND; 2851987b05aSBryce Groff 2861987b05aSBryce Groff type->SetTo(nextType->name); 2871987b05aSBryce Groff *cookie = index; 2881987b05aSBryce Groff 289fd6477d3SStephan Aßmus return B_OK; 290fd6477d3SStephan Aßmus } 291fd6477d3SStephan Aßmus 292fd6477d3SStephan Aßmus 293fd6477d3SStephan Aßmus // GetPartitioningInfo 294fd6477d3SStephan Aßmus status_t 295fd6477d3SStephan Aßmus ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) 296fd6477d3SStephan Aßmus { 29793134c5eSBryce Groff // init to the full size (minus the first PTS_OFFSET) 298fd6477d3SStephan Aßmus BMutablePartition* partition = Partition(); 29993134c5eSBryce Groff off_t offset = partition->Offset() + PTS_OFFSET; 30093134c5eSBryce Groff off_t size = partition->Size() - PTS_OFFSET; 301fd6477d3SStephan Aßmus status_t error = info->SetTo(offset, size); 302fd6477d3SStephan Aßmus if (error != B_OK) 303fd6477d3SStephan Aßmus return error; 304fd6477d3SStephan Aßmus 305fd6477d3SStephan Aßmus // exclude the space of the existing logical partitions 306fd6477d3SStephan Aßmus int32 count = partition->CountChildren(); 307fd6477d3SStephan Aßmus for (int32 i = 0; i < count; i++) { 308fd6477d3SStephan Aßmus BMutablePartition* child = partition->ChildAt(i); 30993134c5eSBryce Groff error = info->ExcludeOccupiedSpace(child->Offset(), 31093134c5eSBryce Groff child->Size() + PTS_OFFSET + Partition()->BlockSize()); 31193134c5eSBryce Groff if (error != B_OK) 31293134c5eSBryce Groff return error; 31393134c5eSBryce Groff 31493134c5eSBryce Groff LogicalPartition* logical = (LogicalPartition*)child->ChildCookie(); 31593134c5eSBryce Groff if (logical == NULL) 31693134c5eSBryce Groff return B_BAD_VALUE; 31793134c5eSBryce Groff error = info->ExcludeOccupiedSpace( 31893134c5eSBryce Groff logical->PartitionTableOffset(), 31993134c5eSBryce Groff PTS_OFFSET + Partition()->BlockSize()); 320fd6477d3SStephan Aßmus if (error != B_OK) 321fd6477d3SStephan Aßmus return error; 322fd6477d3SStephan Aßmus } 323fd6477d3SStephan Aßmus 324fd6477d3SStephan Aßmus return B_OK; 325fd6477d3SStephan Aßmus } 326fd6477d3SStephan Aßmus 327fd6477d3SStephan Aßmus 328fd6477d3SStephan Aßmus // GetChildCreationParameterEditor 329fd6477d3SStephan Aßmus status_t 330fd6477d3SStephan Aßmus ExtendedPartitionHandle::GetChildCreationParameterEditor(const char* type, 3317f96148cSIngo Weinhold BPartitionParameterEditor** editor) 332fd6477d3SStephan Aßmus { 333fd6477d3SStephan Aßmus *editor = NULL; 334fd6477d3SStephan Aßmus return B_OK; 335fd6477d3SStephan Aßmus } 336fd6477d3SStephan Aßmus 337fd6477d3SStephan Aßmus 338fd6477d3SStephan Aßmus // ValidateCreateChild 339fd6477d3SStephan Aßmus status_t 340fd6477d3SStephan Aßmus ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size, 341fd6477d3SStephan Aßmus const char* typeString, BString* name, const char* parameters) 342fd6477d3SStephan Aßmus { 343fd6477d3SStephan Aßmus // check type 3441987b05aSBryce Groff if (!typeString) 345fd6477d3SStephan Aßmus return B_BAD_VALUE; 346fd6477d3SStephan Aßmus 347fd6477d3SStephan Aßmus // check name 348fd6477d3SStephan Aßmus if (name) 349fd6477d3SStephan Aßmus name->Truncate(0); 350fd6477d3SStephan Aßmus 3511987b05aSBryce Groff // check the free space situation 3521987b05aSBryce Groff BPartitioningInfo info; 3531987b05aSBryce Groff status_t error = GetPartitioningInfo(&info); 3541987b05aSBryce Groff if (error != B_OK) 3551987b05aSBryce Groff return error; 356fd6477d3SStephan Aßmus 3571987b05aSBryce Groff // any space in the partition at all? 3581987b05aSBryce Groff int32 spacesCount = info.CountPartitionableSpaces(); 3591987b05aSBryce Groff if (spacesCount == 0) 3601987b05aSBryce Groff return B_BAD_VALUE; 3611987b05aSBryce Groff 3621987b05aSBryce Groff // check offset and size 3631987b05aSBryce Groff off_t offset = sector_align(*_offset, Partition()->BlockSize()); 3641987b05aSBryce Groff off_t size = sector_align(*_size, Partition()->BlockSize()); 3651987b05aSBryce Groff // TODO: Rather round size up? 3661987b05aSBryce Groff off_t end = offset + size; 3671987b05aSBryce Groff 3681987b05aSBryce Groff // get the first partitionable space the requested interval intersects with 3691987b05aSBryce Groff int32 spaceIndex = -1; 3701987b05aSBryce Groff int32 closestSpaceIndex = -1; 3711987b05aSBryce Groff off_t closestSpaceDistance = 0; 3721987b05aSBryce Groff for (int32 i = 0; i < spacesCount; i++) { 3731987b05aSBryce Groff off_t spaceOffset, spaceSize; 3741987b05aSBryce Groff info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); 3751987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize; 3761987b05aSBryce Groff 377f1143621SWim van der Meer if ((spaceOffset >= offset && spaceOffset < end) 378f1143621SWim van der Meer || (offset >= spaceOffset && offset < spaceEnd)) { 3791987b05aSBryce Groff spaceIndex = i; 3801987b05aSBryce Groff break; 3811987b05aSBryce Groff } 3821987b05aSBryce Groff 3831987b05aSBryce Groff off_t distance; 3841987b05aSBryce Groff if (offset < spaceOffset) 3851987b05aSBryce Groff distance = spaceOffset - end; 3861987b05aSBryce Groff else 3871987b05aSBryce Groff distance = spaceEnd - offset; 3881987b05aSBryce Groff 3891987b05aSBryce Groff if (closestSpaceIndex == -1 || distance < closestSpaceDistance) { 3901987b05aSBryce Groff closestSpaceIndex = i; 3911987b05aSBryce Groff closestSpaceDistance = distance; 3921987b05aSBryce Groff } 3931987b05aSBryce Groff } 3941987b05aSBryce Groff 3951987b05aSBryce Groff // get the space we found 3961987b05aSBryce Groff off_t spaceOffset, spaceSize; 3971987b05aSBryce Groff info.GetPartitionableSpaceAt( 3981987b05aSBryce Groff spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset, 3991987b05aSBryce Groff &spaceSize); 4001987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize; 4011987b05aSBryce Groff 4021987b05aSBryce Groff // If the requested intervald doesn't intersect with any space yet, move 4031987b05aSBryce Groff // it, so that it does. 4041987b05aSBryce Groff if (spaceIndex < 0) { 4051987b05aSBryce Groff spaceIndex = closestSpaceIndex; 4061987b05aSBryce Groff if (offset < spaceOffset) { 4071987b05aSBryce Groff offset = spaceOffset; 4081987b05aSBryce Groff end = offset + size; 4091987b05aSBryce Groff } else { 4101987b05aSBryce Groff end = spaceEnd; 4111987b05aSBryce Groff offset = end - size; 4121987b05aSBryce Groff } 4131987b05aSBryce Groff } 4141987b05aSBryce Groff 4151987b05aSBryce Groff // move/shrink the interval, so that it fully lies within the space 4161987b05aSBryce Groff if (offset < spaceOffset) { 4171987b05aSBryce Groff offset = spaceOffset; 4181987b05aSBryce Groff end = offset + size; 4191987b05aSBryce Groff if (end > spaceEnd) { 4201987b05aSBryce Groff end = spaceEnd; 4211987b05aSBryce Groff size = end - offset; 4221987b05aSBryce Groff } 4231987b05aSBryce Groff } else if (end > spaceEnd) { 4241987b05aSBryce Groff end = spaceEnd; 4251987b05aSBryce Groff offset = end - size; 4261987b05aSBryce Groff if (offset < spaceOffset) { 4271987b05aSBryce Groff offset = spaceOffset; 4281987b05aSBryce Groff size = end - offset; 4291987b05aSBryce Groff } 4301987b05aSBryce Groff } 4311987b05aSBryce Groff 4321987b05aSBryce Groff *_offset = offset; 4331987b05aSBryce Groff *_size = size; 4341987b05aSBryce Groff 4351987b05aSBryce Groff return B_OK; 436fd6477d3SStephan Aßmus } 437fd6477d3SStephan Aßmus 438fd6477d3SStephan Aßmus 439fd6477d3SStephan Aßmus // CreateChild 440fd6477d3SStephan Aßmus status_t 441fd6477d3SStephan Aßmus ExtendedPartitionHandle::CreateChild(off_t offset, off_t size, 44293134c5eSBryce Groff const char* typeString, const char* name, const char* _parameters, 443fd6477d3SStephan Aßmus BMutablePartition** _child) 444fd6477d3SStephan Aßmus { 445fd6477d3SStephan Aßmus // check type 4461987b05aSBryce Groff PartitionType type; 4471987b05aSBryce Groff if (!type.SetType(typeString) || type.IsEmpty()) 448fd6477d3SStephan Aßmus return B_BAD_VALUE; 449fd6477d3SStephan Aßmus 450fd6477d3SStephan Aßmus // check name 451*10d05234SAxel Dörfler if (name != NULL && name[0] != '\0') 452fd6477d3SStephan Aßmus return B_BAD_VALUE; 453fd6477d3SStephan Aßmus 4541987b05aSBryce Groff // offset properly aligned? 4551987b05aSBryce Groff if (offset != sector_align(offset, Partition()->BlockSize()) 4561987b05aSBryce Groff || size != sector_align(size, Partition()->BlockSize())) 4571987b05aSBryce Groff return B_BAD_VALUE; 458fd6477d3SStephan Aßmus 4591987b05aSBryce Groff // check the free space situation 4601987b05aSBryce Groff BPartitioningInfo info; 4611987b05aSBryce Groff status_t error = GetPartitioningInfo(&info); 4621987b05aSBryce Groff if (error != B_OK) 4631987b05aSBryce Groff return error; 4641987b05aSBryce Groff 4651987b05aSBryce Groff bool foundSpace = false; 4661987b05aSBryce Groff off_t end = offset + size; 4671987b05aSBryce Groff int32 spacesCount = info.CountPartitionableSpaces(); 4681987b05aSBryce Groff for (int32 i = 0; i < spacesCount; i++) { 4691987b05aSBryce Groff off_t spaceOffset, spaceSize; 4701987b05aSBryce Groff info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); 4711987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize; 4721987b05aSBryce Groff 4731987b05aSBryce Groff if (offset >= spaceOffset && end <= spaceEnd) { 4741987b05aSBryce Groff foundSpace = true; 4751987b05aSBryce Groff break; 4761987b05aSBryce Groff } 477fd6477d3SStephan Aßmus } 478fd6477d3SStephan Aßmus 4791987b05aSBryce Groff if (!foundSpace) 4801987b05aSBryce Groff return B_BAD_VALUE; 4811987b05aSBryce Groff 48293134c5eSBryce Groff BString parameters(_parameters); 48393134c5eSBryce Groff parameters << "partition_table_offset " << offset - PTS_OFFSET << " ;\n"; 48493134c5eSBryce Groff // everything looks good, create the child 4851987b05aSBryce Groff BMutablePartition* child; 4861987b05aSBryce Groff error = Partition()->CreateChild(-1, typeString, 48793134c5eSBryce Groff NULL, parameters.String(), &child); 4881987b05aSBryce Groff if (error != B_OK) 4891987b05aSBryce Groff return error; 4901987b05aSBryce Groff 4911987b05aSBryce Groff // init the child 4921987b05aSBryce Groff child->SetOffset(offset); 4931987b05aSBryce Groff child->SetSize(size); 4941987b05aSBryce Groff child->SetBlockSize(Partition()->BlockSize()); 4951987b05aSBryce Groff //child->SetFlags(0); 4961987b05aSBryce Groff child->SetChildCookie(Partition()); 4971987b05aSBryce Groff 4981987b05aSBryce Groff *_child = child; 4991987b05aSBryce Groff return B_OK; 5001987b05aSBryce Groff } 5011987b05aSBryce Groff 5021987b05aSBryce Groff 5031987b05aSBryce Groff // DeleteChild 5041987b05aSBryce Groff status_t 5051987b05aSBryce Groff ExtendedPartitionHandle::DeleteChild(BMutablePartition* child) 5061987b05aSBryce Groff { 5071987b05aSBryce Groff BMutablePartition* parent = child->Parent(); 5081987b05aSBryce Groff status_t error = parent->DeleteChild(child); 5091987b05aSBryce Groff 5101987b05aSBryce Groff return error; 5111987b05aSBryce Groff } 512fd6477d3SStephan Aßmus 513