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 68efbc276SAxel Dörfler 791c21ff4SIngo Weinhold #include "ExtendedPartitionAddOn.h" 891c21ff4SIngo Weinhold 991c21ff4SIngo Weinhold #include <new> 107ba970b9SStephan Aßmus #include <stdio.h> 1191c21ff4SIngo Weinhold 1291c21ff4SIngo Weinhold #include <DiskDeviceTypes.h> 1391c21ff4SIngo Weinhold #include <MutablePartition.h> 14fd6477d3SStephan Aßmus #include <PartitioningInfo.h> 15fd6477d3SStephan Aßmus 16fd6477d3SStephan Aßmus #include <AutoDeleter.h> 1791c21ff4SIngo Weinhold 185f1b31deSAxel Dörfler #include "IntelDiskSystem.h" 195f1b31deSAxel Dörfler 208efbc276SAxel Dörfler 217ba970b9SStephan Aßmus //#define TRACE_EXTENDED_PARTITION_ADD_ON 227ba970b9SStephan Aßmus #undef TRACE 237ba970b9SStephan Aßmus #ifdef TRACE_EXTENDED_PARTITION_ADD_ON 247ba970b9SStephan Aßmus # define TRACE(x...) printf(x) 257ba970b9SStephan Aßmus #else 267ba970b9SStephan Aßmus # define TRACE(x...) do {} while (false) 277ba970b9SStephan Aßmus #endif 287ba970b9SStephan Aßmus 2993134c5eSBryce Groff #define PTS_OFFSET (63 * Partition()->BlockSize()) 3091c21ff4SIngo Weinhold 318efbc276SAxel Dörfler 3291c21ff4SIngo Weinhold using std::nothrow; 3391c21ff4SIngo Weinhold 3491c21ff4SIngo Weinhold 35fd6477d3SStephan Aßmus static const uint32 kDiskSystemFlags = 36fd6477d3SStephan Aßmus 0 37fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_CHECKING 38fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_REPAIRING 39fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_RESIZING 40fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_MOVING 41fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME 42fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS 431987b05aSBryce Groff // | B_DISK_SYSTEM_SUPPORTS_INITIALIZING 44fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME 45fd6477d3SStephan Aßmus 46fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD 47fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD 48fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME 49fd6477d3SStephan Aßmus | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE 50fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS 51fd6477d3SStephan Aßmus | B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD 52fd6477d3SStephan Aßmus | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD 53fd6477d3SStephan Aßmus // | B_DISK_SYSTEM_SUPPORTS_NAME 54fd6477d3SStephan Aßmus ; 55fd6477d3SStephan Aßmus 56fd6477d3SStephan Aßmus 5791c21ff4SIngo Weinhold // #pragma mark - ExtendedPartitionAddOn 5891c21ff4SIngo Weinhold 5991c21ff4SIngo Weinhold 6091c21ff4SIngo Weinhold ExtendedPartitionAddOn::ExtendedPartitionAddOn() 618efbc276SAxel Dörfler : 628efbc276SAxel Dörfler BDiskSystemAddOn(kPartitionTypeIntelExtended, kDiskSystemFlags) 6391c21ff4SIngo Weinhold { 6491c21ff4SIngo Weinhold } 6591c21ff4SIngo Weinhold 6691c21ff4SIngo Weinhold 6791c21ff4SIngo Weinhold ExtendedPartitionAddOn::~ExtendedPartitionAddOn() 6891c21ff4SIngo Weinhold { 6991c21ff4SIngo Weinhold } 7091c21ff4SIngo Weinhold 7191c21ff4SIngo Weinhold 7291c21ff4SIngo Weinhold status_t 7391c21ff4SIngo Weinhold ExtendedPartitionAddOn::CreatePartitionHandle(BMutablePartition* partition, 7491c21ff4SIngo Weinhold BPartitionHandle** _handle) 7591c21ff4SIngo Weinhold { 7691c21ff4SIngo Weinhold ExtendedPartitionHandle* handle 7791c21ff4SIngo Weinhold = new(nothrow) ExtendedPartitionHandle(partition); 7891c21ff4SIngo Weinhold if (!handle) 7991c21ff4SIngo Weinhold return B_NO_MEMORY; 8091c21ff4SIngo Weinhold 8191c21ff4SIngo Weinhold status_t error = handle->Init(); 8291c21ff4SIngo Weinhold if (error != B_OK) { 8391c21ff4SIngo Weinhold delete handle; 8491c21ff4SIngo Weinhold return error; 8591c21ff4SIngo Weinhold } 8691c21ff4SIngo Weinhold 8791c21ff4SIngo Weinhold *_handle = handle; 8891c21ff4SIngo Weinhold return B_OK; 8991c21ff4SIngo Weinhold } 9091c21ff4SIngo Weinhold 9191c21ff4SIngo Weinhold 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 status_t 101fd6477d3SStephan Aßmus ExtendedPartitionAddOn::ValidateInitialize(const BMutablePartition* partition, 102fd6477d3SStephan Aßmus BString* name, const char* parameters) 103fd6477d3SStephan Aßmus { 104fd6477d3SStephan Aßmus if (!CanInitialize(partition) 10510d05234SAxel Dörfler || (parameters != NULL && parameters[0] != '\0')) { 106fd6477d3SStephan Aßmus return B_BAD_VALUE; 107fd6477d3SStephan Aßmus } 108fd6477d3SStephan Aßmus 109fd6477d3SStephan Aßmus // we don't support a content name 110fd6477d3SStephan Aßmus if (name != NULL) 111fd6477d3SStephan Aßmus name->Truncate(0); 112fd6477d3SStephan Aßmus 113fd6477d3SStephan Aßmus return B_OK; 114fd6477d3SStephan Aßmus } 115fd6477d3SStephan Aßmus 116fd6477d3SStephan Aßmus 117fd6477d3SStephan Aßmus status_t 118fd6477d3SStephan Aßmus ExtendedPartitionAddOn::Initialize(BMutablePartition* partition, 119fd6477d3SStephan Aßmus const char* name, const char* parameters, BPartitionHandle** _handle) 120fd6477d3SStephan Aßmus { 121fd6477d3SStephan Aßmus if (!CanInitialize(partition) 12210d05234SAxel Dörfler || (name != NULL && name[0] != '\0') 12310d05234SAxel Dörfler || (parameters != NULL && parameters[0] != '\0')) { 124fd6477d3SStephan Aßmus return B_BAD_VALUE; 125fd6477d3SStephan Aßmus } 126fd6477d3SStephan Aßmus 127fd6477d3SStephan Aßmus // create the handle 128fd6477d3SStephan Aßmus ExtendedPartitionHandle* handle 129fd6477d3SStephan Aßmus = new(nothrow) ExtendedPartitionHandle(partition); 130fd6477d3SStephan Aßmus if (!handle) 131fd6477d3SStephan Aßmus return B_NO_MEMORY; 132fd6477d3SStephan Aßmus ObjectDeleter<ExtendedPartitionHandle> handleDeleter(handle); 133fd6477d3SStephan Aßmus 134fd6477d3SStephan Aßmus // init the partition 135fd6477d3SStephan Aßmus status_t error = partition->SetContentType(Name()); 136fd6477d3SStephan Aßmus if (error != B_OK) 137fd6477d3SStephan Aßmus return error; 138fd6477d3SStephan Aßmus // TODO: The content type could as well be set by the caller. 139fd6477d3SStephan Aßmus 140fd6477d3SStephan Aßmus partition->SetContentName(NULL); 141fd6477d3SStephan Aßmus partition->SetContentParameters(NULL); 1425f1b31deSAxel Dörfler partition->SetContentSize( 1435f1b31deSAxel Dörfler sector_align(partition->Size(), partition->BlockSize())); 144fd6477d3SStephan Aßmus 145fd6477d3SStephan Aßmus *_handle = handleDeleter.Detach(); 146fd6477d3SStephan Aßmus 147fd6477d3SStephan Aßmus return B_OK; 148fd6477d3SStephan Aßmus } 149fd6477d3SStephan Aßmus 150fd6477d3SStephan Aßmus 15191c21ff4SIngo Weinhold // #pragma mark - ExtendedPartitionHandle 15291c21ff4SIngo Weinhold 15391c21ff4SIngo Weinhold 15491c21ff4SIngo Weinhold ExtendedPartitionHandle::ExtendedPartitionHandle(BMutablePartition* partition) 1558efbc276SAxel Dörfler : 1568efbc276SAxel Dörfler BPartitionHandle(partition) 15791c21ff4SIngo Weinhold { 15891c21ff4SIngo Weinhold } 15991c21ff4SIngo Weinhold 16091c21ff4SIngo Weinhold 16191c21ff4SIngo Weinhold ExtendedPartitionHandle::~ExtendedPartitionHandle() 16291c21ff4SIngo Weinhold { 16391c21ff4SIngo Weinhold } 16491c21ff4SIngo Weinhold 16591c21ff4SIngo Weinhold 16691c21ff4SIngo Weinhold status_t 16791c21ff4SIngo Weinhold ExtendedPartitionHandle::Init() 16891c21ff4SIngo Weinhold { 16991c21ff4SIngo Weinhold // initialize the extended partition from the mutable partition 17091c21ff4SIngo Weinhold 17191c21ff4SIngo Weinhold BMutablePartition* partition = Partition(); 17291c21ff4SIngo Weinhold 17391c21ff4SIngo Weinhold // our parent has already set the child cookie to the primary partition. 17491c21ff4SIngo Weinhold fPrimaryPartition = (PrimaryPartition*)partition->ChildCookie(); 17591c21ff4SIngo Weinhold if (!fPrimaryPartition) 17691c21ff4SIngo Weinhold return B_BAD_VALUE; 17791c21ff4SIngo Weinhold 17891c21ff4SIngo Weinhold if (!fPrimaryPartition->IsExtended()) 17991c21ff4SIngo Weinhold return B_BAD_VALUE; 18091c21ff4SIngo Weinhold 18191c21ff4SIngo Weinhold // init the child partitions 18291c21ff4SIngo Weinhold int32 count = partition->CountChildren(); 18391c21ff4SIngo Weinhold for (int32 i = 0; i < count; i++) { 18491c21ff4SIngo Weinhold BMutablePartition* child = partition->ChildAt(i); 18593134c5eSBryce Groff 18691c21ff4SIngo Weinhold PartitionType type; 18791c21ff4SIngo Weinhold if (!type.SetType(child->Type())) 18891c21ff4SIngo Weinhold return B_BAD_VALUE; 18991c21ff4SIngo Weinhold 19093134c5eSBryce Groff void* handle = parse_driver_settings_string(child->Parameters()); 19193134c5eSBryce Groff if (handle == NULL) 19293134c5eSBryce Groff return B_ERROR; 19393134c5eSBryce Groff 19493134c5eSBryce Groff bool active = get_driver_boolean_parameter( 19593134c5eSBryce Groff handle, "active", false, true); 19693134c5eSBryce Groff 19791c21ff4SIngo Weinhold off_t ptsOffset = 0; 19893134c5eSBryce Groff const char* buffer = get_driver_parameter(handle, 19993134c5eSBryce Groff "partition_table_offset", NULL, NULL); 20093134c5eSBryce Groff if (buffer != NULL) 20193134c5eSBryce Groff ptsOffset = strtoull(buffer, NULL, 10); 20293134c5eSBryce Groff else { 20393134c5eSBryce Groff delete_driver_settings(handle); 20493134c5eSBryce Groff return B_BAD_VALUE; 20593134c5eSBryce Groff } 20693134c5eSBryce Groff delete_driver_settings(handle); 20791c21ff4SIngo Weinhold 20891c21ff4SIngo Weinhold LogicalPartition* logical = new(nothrow) LogicalPartition; 20991c21ff4SIngo Weinhold if (!logical) 21091c21ff4SIngo Weinhold return B_NO_MEMORY; 21191c21ff4SIngo Weinhold 21291c21ff4SIngo Weinhold logical->SetTo(child->Offset(), child->Size(), type.Type(), active, 21391c21ff4SIngo Weinhold ptsOffset, fPrimaryPartition); 21491c21ff4SIngo Weinhold 21591c21ff4SIngo Weinhold child->SetChildCookie(logical); 21691c21ff4SIngo Weinhold } 21791c21ff4SIngo Weinhold 21891c21ff4SIngo Weinhold return B_OK; 21991c21ff4SIngo Weinhold } 220fd6477d3SStephan Aßmus 221fd6477d3SStephan Aßmus 222fd6477d3SStephan Aßmus uint32 223fd6477d3SStephan Aßmus ExtendedPartitionHandle::SupportedOperations(uint32 mask) 224fd6477d3SStephan Aßmus { 22593134c5eSBryce Groff uint32 flags = 0; 226fd6477d3SStephan Aßmus 227fd6477d3SStephan Aßmus // creating child 2288efbc276SAxel Dörfler if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) { 229fd6477d3SStephan Aßmus BPartitioningInfo info; 230fd6477d3SStephan Aßmus if (GetPartitioningInfo(&info) == B_OK 231fd6477d3SStephan Aßmus && info.CountPartitionableSpaces() > 1) { 232fd6477d3SStephan Aßmus flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; 233fd6477d3SStephan Aßmus } 234fd6477d3SStephan Aßmus } 235fd6477d3SStephan Aßmus 236fd6477d3SStephan Aßmus return flags; 237fd6477d3SStephan Aßmus } 238fd6477d3SStephan Aßmus 239fd6477d3SStephan Aßmus 240fd6477d3SStephan Aßmus uint32 241fd6477d3SStephan Aßmus ExtendedPartitionHandle::SupportedChildOperations( 242fd6477d3SStephan Aßmus const BMutablePartition* child, uint32 mask) 243fd6477d3SStephan Aßmus { 244fd6477d3SStephan Aßmus return B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD; 245fd6477d3SStephan Aßmus } 246fd6477d3SStephan Aßmus 247fd6477d3SStephan Aßmus 248fd6477d3SStephan Aßmus status_t 249fd6477d3SStephan Aßmus ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child, 250fd6477d3SStephan Aßmus int32* cookie, BString* type) 251fd6477d3SStephan Aßmus { 2521987b05aSBryce Groff int32 index = *cookie; 2531987b05aSBryce Groff const partition_type* nextType; 2541987b05aSBryce Groff PartitionMap partitionMap; 2551987b05aSBryce Groff while (true) { 2561987b05aSBryce Groff nextType = partitionMap.GetNextSupportedPartitionType(index); 2571987b05aSBryce Groff if (nextType == NULL) 258fd6477d3SStephan Aßmus return B_ENTRY_NOT_FOUND; 2591987b05aSBryce Groff index++; 2601987b05aSBryce Groff if (nextType->used 2611987b05aSBryce Groff && strcmp(nextType->name, kPartitionTypeIntelExtended) != 0) 2621987b05aSBryce Groff break; 2631987b05aSBryce Groff } 2641987b05aSBryce Groff 2651987b05aSBryce Groff if (!nextType) 2661987b05aSBryce Groff return B_ENTRY_NOT_FOUND; 2671987b05aSBryce Groff 2681987b05aSBryce Groff type->SetTo(nextType->name); 2691987b05aSBryce Groff *cookie = index; 2701987b05aSBryce Groff 271fd6477d3SStephan Aßmus return B_OK; 272fd6477d3SStephan Aßmus } 273fd6477d3SStephan Aßmus 274fd6477d3SStephan Aßmus 275fd6477d3SStephan Aßmus status_t 276fd6477d3SStephan Aßmus ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) 277fd6477d3SStephan Aßmus { 27893134c5eSBryce Groff // init to the full size (minus the first PTS_OFFSET) 279fd6477d3SStephan Aßmus BMutablePartition* partition = Partition(); 28093134c5eSBryce Groff off_t offset = partition->Offset() + PTS_OFFSET; 28193134c5eSBryce Groff off_t size = partition->Size() - PTS_OFFSET; 282fd6477d3SStephan Aßmus status_t error = info->SetTo(offset, size); 283fd6477d3SStephan Aßmus if (error != B_OK) 284fd6477d3SStephan Aßmus return error; 285fd6477d3SStephan Aßmus 286fd6477d3SStephan Aßmus // exclude the space of the existing logical partitions 287fd6477d3SStephan Aßmus int32 count = partition->CountChildren(); 288fd6477d3SStephan Aßmus for (int32 i = 0; i < count; i++) { 289fd6477d3SStephan Aßmus BMutablePartition* child = partition->ChildAt(i); 29093134c5eSBryce Groff error = info->ExcludeOccupiedSpace(child->Offset(), 29193134c5eSBryce Groff child->Size() + PTS_OFFSET + Partition()->BlockSize()); 29293134c5eSBryce Groff if (error != B_OK) 29393134c5eSBryce Groff return error; 29493134c5eSBryce Groff 29593134c5eSBryce Groff LogicalPartition* logical = (LogicalPartition*)child->ChildCookie(); 29693134c5eSBryce Groff if (logical == NULL) 29793134c5eSBryce Groff return B_BAD_VALUE; 29893134c5eSBryce Groff error = info->ExcludeOccupiedSpace( 29993134c5eSBryce Groff logical->PartitionTableOffset(), 30093134c5eSBryce Groff PTS_OFFSET + Partition()->BlockSize()); 301fd6477d3SStephan Aßmus if (error != B_OK) 302fd6477d3SStephan Aßmus return error; 303fd6477d3SStephan Aßmus } 304fd6477d3SStephan Aßmus 305fd6477d3SStephan Aßmus return B_OK; 306fd6477d3SStephan Aßmus } 307fd6477d3SStephan Aßmus 308fd6477d3SStephan Aßmus 309fd6477d3SStephan Aßmus status_t 310*2f3ce2bfSBryce Groff ExtendedPartitionHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type, 3117f96148cSIngo Weinhold BPartitionParameterEditor** editor) 312fd6477d3SStephan Aßmus { 313fd6477d3SStephan Aßmus *editor = NULL; 314*2f3ce2bfSBryce Groff return B_NOT_SUPPORTED; 315fd6477d3SStephan Aßmus } 316fd6477d3SStephan Aßmus 317fd6477d3SStephan Aßmus 318fd6477d3SStephan Aßmus status_t 319fd6477d3SStephan Aßmus ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size, 320fd6477d3SStephan Aßmus const char* typeString, BString* name, const char* parameters) 321fd6477d3SStephan Aßmus { 322fd6477d3SStephan Aßmus // check type 3231987b05aSBryce Groff if (!typeString) 324fd6477d3SStephan Aßmus return B_BAD_VALUE; 325fd6477d3SStephan Aßmus 326fd6477d3SStephan Aßmus // check name 327fd6477d3SStephan Aßmus if (name) 328fd6477d3SStephan Aßmus name->Truncate(0); 329fd6477d3SStephan Aßmus 3301987b05aSBryce Groff // check the free space situation 3311987b05aSBryce Groff BPartitioningInfo info; 3321987b05aSBryce Groff status_t error = GetPartitioningInfo(&info); 3331987b05aSBryce Groff if (error != B_OK) 3341987b05aSBryce Groff return error; 335fd6477d3SStephan Aßmus 3361987b05aSBryce Groff // any space in the partition at all? 3371987b05aSBryce Groff int32 spacesCount = info.CountPartitionableSpaces(); 3381987b05aSBryce Groff if (spacesCount == 0) 3391987b05aSBryce Groff return B_BAD_VALUE; 3401987b05aSBryce Groff 3411987b05aSBryce Groff // check offset and size 3421987b05aSBryce Groff off_t offset = sector_align(*_offset, Partition()->BlockSize()); 3431987b05aSBryce Groff off_t size = sector_align(*_size, Partition()->BlockSize()); 3441987b05aSBryce Groff // TODO: Rather round size up? 3451987b05aSBryce Groff off_t end = offset + size; 3461987b05aSBryce Groff 3471987b05aSBryce Groff // get the first partitionable space the requested interval intersects with 3481987b05aSBryce Groff int32 spaceIndex = -1; 3491987b05aSBryce Groff int32 closestSpaceIndex = -1; 3501987b05aSBryce Groff off_t closestSpaceDistance = 0; 3511987b05aSBryce Groff for (int32 i = 0; i < spacesCount; i++) { 3521987b05aSBryce Groff off_t spaceOffset, spaceSize; 3531987b05aSBryce Groff info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); 3541987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize; 3551987b05aSBryce Groff 356f1143621SWim van der Meer if ((spaceOffset >= offset && spaceOffset < end) 357f1143621SWim van der Meer || (offset >= spaceOffset && offset < spaceEnd)) { 3581987b05aSBryce Groff spaceIndex = i; 3591987b05aSBryce Groff break; 3601987b05aSBryce Groff } 3611987b05aSBryce Groff 3621987b05aSBryce Groff off_t distance; 3631987b05aSBryce Groff if (offset < spaceOffset) 3641987b05aSBryce Groff distance = spaceOffset - end; 3651987b05aSBryce Groff else 3661987b05aSBryce Groff distance = spaceEnd - offset; 3671987b05aSBryce Groff 3681987b05aSBryce Groff if (closestSpaceIndex == -1 || distance < closestSpaceDistance) { 3691987b05aSBryce Groff closestSpaceIndex = i; 3701987b05aSBryce Groff closestSpaceDistance = distance; 3711987b05aSBryce Groff } 3721987b05aSBryce Groff } 3731987b05aSBryce Groff 3741987b05aSBryce Groff // get the space we found 3751987b05aSBryce Groff off_t spaceOffset, spaceSize; 3761987b05aSBryce Groff info.GetPartitionableSpaceAt( 3771987b05aSBryce Groff spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset, 3781987b05aSBryce Groff &spaceSize); 3791987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize; 3801987b05aSBryce Groff 3811987b05aSBryce Groff // If the requested intervald doesn't intersect with any space yet, move 3821987b05aSBryce Groff // it, so that it does. 3831987b05aSBryce Groff if (spaceIndex < 0) { 3841987b05aSBryce Groff spaceIndex = closestSpaceIndex; 3851987b05aSBryce Groff if (offset < spaceOffset) { 3861987b05aSBryce Groff offset = spaceOffset; 3871987b05aSBryce Groff end = offset + size; 3881987b05aSBryce Groff } else { 3891987b05aSBryce Groff end = spaceEnd; 3901987b05aSBryce Groff offset = end - size; 3911987b05aSBryce Groff } 3921987b05aSBryce Groff } 3931987b05aSBryce Groff 3941987b05aSBryce Groff // move/shrink the interval, so that it fully lies within the space 3951987b05aSBryce Groff if (offset < spaceOffset) { 3961987b05aSBryce Groff offset = spaceOffset; 3971987b05aSBryce Groff end = offset + size; 3981987b05aSBryce Groff if (end > spaceEnd) { 3991987b05aSBryce Groff end = spaceEnd; 4001987b05aSBryce Groff size = end - offset; 4011987b05aSBryce Groff } 4021987b05aSBryce Groff } else if (end > spaceEnd) { 4031987b05aSBryce Groff end = spaceEnd; 4041987b05aSBryce Groff offset = end - size; 4051987b05aSBryce Groff if (offset < spaceOffset) { 4061987b05aSBryce Groff offset = spaceOffset; 4071987b05aSBryce Groff size = end - offset; 4081987b05aSBryce Groff } 4091987b05aSBryce Groff } 4101987b05aSBryce Groff 4111987b05aSBryce Groff *_offset = offset; 4121987b05aSBryce Groff *_size = size; 4131987b05aSBryce Groff 4141987b05aSBryce Groff return B_OK; 415fd6477d3SStephan Aßmus } 416fd6477d3SStephan Aßmus 417fd6477d3SStephan Aßmus 418fd6477d3SStephan Aßmus status_t 419fd6477d3SStephan Aßmus ExtendedPartitionHandle::CreateChild(off_t offset, off_t size, 42093134c5eSBryce Groff const char* typeString, const char* name, const char* _parameters, 421fd6477d3SStephan Aßmus BMutablePartition** _child) 422fd6477d3SStephan Aßmus { 423fd6477d3SStephan Aßmus // check type 4241987b05aSBryce Groff PartitionType type; 4251987b05aSBryce Groff if (!type.SetType(typeString) || type.IsEmpty()) 426fd6477d3SStephan Aßmus return B_BAD_VALUE; 427fd6477d3SStephan Aßmus 428fd6477d3SStephan Aßmus // check name 42910d05234SAxel Dörfler if (name != NULL && name[0] != '\0') 430fd6477d3SStephan Aßmus return B_BAD_VALUE; 431fd6477d3SStephan Aßmus 4321987b05aSBryce Groff // offset properly aligned? 4331987b05aSBryce Groff if (offset != sector_align(offset, Partition()->BlockSize()) 4341987b05aSBryce Groff || size != sector_align(size, Partition()->BlockSize())) 4351987b05aSBryce Groff return B_BAD_VALUE; 436fd6477d3SStephan Aßmus 4371987b05aSBryce Groff // check the free space situation 4381987b05aSBryce Groff BPartitioningInfo info; 4391987b05aSBryce Groff status_t error = GetPartitioningInfo(&info); 4401987b05aSBryce Groff if (error != B_OK) 4411987b05aSBryce Groff return error; 4421987b05aSBryce Groff 4431987b05aSBryce Groff bool foundSpace = false; 4441987b05aSBryce Groff off_t end = offset + size; 4451987b05aSBryce Groff int32 spacesCount = info.CountPartitionableSpaces(); 4461987b05aSBryce Groff for (int32 i = 0; i < spacesCount; i++) { 4471987b05aSBryce Groff off_t spaceOffset, spaceSize; 4481987b05aSBryce Groff info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize); 4491987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize; 4501987b05aSBryce Groff 4511987b05aSBryce Groff if (offset >= spaceOffset && end <= spaceEnd) { 4521987b05aSBryce Groff foundSpace = true; 4531987b05aSBryce Groff break; 4541987b05aSBryce Groff } 455fd6477d3SStephan Aßmus } 456fd6477d3SStephan Aßmus 4571987b05aSBryce Groff if (!foundSpace) 4581987b05aSBryce Groff return B_BAD_VALUE; 4591987b05aSBryce Groff 46093134c5eSBryce Groff BString parameters(_parameters); 46193134c5eSBryce Groff parameters << "partition_table_offset " << offset - PTS_OFFSET << " ;\n"; 46293134c5eSBryce Groff // everything looks good, create the child 4631987b05aSBryce Groff BMutablePartition* child; 4641987b05aSBryce Groff error = Partition()->CreateChild(-1, typeString, 46593134c5eSBryce Groff NULL, parameters.String(), &child); 4661987b05aSBryce Groff if (error != B_OK) 4671987b05aSBryce Groff return error; 4681987b05aSBryce Groff 4691987b05aSBryce Groff // init the child 4701987b05aSBryce Groff child->SetOffset(offset); 4711987b05aSBryce Groff child->SetSize(size); 4721987b05aSBryce Groff child->SetBlockSize(Partition()->BlockSize()); 4731987b05aSBryce Groff //child->SetFlags(0); 4741987b05aSBryce Groff child->SetChildCookie(Partition()); 4751987b05aSBryce Groff 4761987b05aSBryce Groff *_child = child; 4771987b05aSBryce Groff return B_OK; 4781987b05aSBryce Groff } 4791987b05aSBryce Groff 4801987b05aSBryce Groff 4811987b05aSBryce Groff status_t 4821987b05aSBryce Groff ExtendedPartitionHandle::DeleteChild(BMutablePartition* child) 4831987b05aSBryce Groff { 4841987b05aSBryce Groff BMutablePartition* parent = child->Parent(); 4851987b05aSBryce Groff status_t error = parent->DeleteChild(child); 4861987b05aSBryce Groff 4871987b05aSBryce Groff return error; 4881987b05aSBryce Groff } 489