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
ExtendedPartitionAddOn()6091c21ff4SIngo Weinhold ExtendedPartitionAddOn::ExtendedPartitionAddOn()
618efbc276SAxel Dörfler :
628efbc276SAxel Dörfler BDiskSystemAddOn(kPartitionTypeIntelExtended, kDiskSystemFlags)
6391c21ff4SIngo Weinhold {
6491c21ff4SIngo Weinhold }
6591c21ff4SIngo Weinhold
6691c21ff4SIngo Weinhold
~ExtendedPartitionAddOn()6791c21ff4SIngo Weinhold ExtendedPartitionAddOn::~ExtendedPartitionAddOn()
6891c21ff4SIngo Weinhold {
6991c21ff4SIngo Weinhold }
7091c21ff4SIngo Weinhold
7191c21ff4SIngo Weinhold
7291c21ff4SIngo Weinhold status_t
CreatePartitionHandle(BMutablePartition * partition,BPartitionHandle ** _handle)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
CanInitialize(const BMutablePartition * partition)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
ValidateInitialize(const BMutablePartition * partition,BString * name,const char * parameters)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
Initialize(BMutablePartition * partition,const char * name,const char * parameters,BPartitionHandle ** _handle)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()));
1440fbba5d7SAdrien Destugues partition->Changed(B_PARTITION_CHANGED_INITIALIZATION);
145fd6477d3SStephan Aßmus
146fd6477d3SStephan Aßmus *_handle = handleDeleter.Detach();
147fd6477d3SStephan Aßmus
148fd6477d3SStephan Aßmus return B_OK;
149fd6477d3SStephan Aßmus }
150fd6477d3SStephan Aßmus
151fd6477d3SStephan Aßmus
15291c21ff4SIngo Weinhold // #pragma mark - ExtendedPartitionHandle
15391c21ff4SIngo Weinhold
15491c21ff4SIngo Weinhold
ExtendedPartitionHandle(BMutablePartition * partition)15591c21ff4SIngo Weinhold ExtendedPartitionHandle::ExtendedPartitionHandle(BMutablePartition* partition)
1568efbc276SAxel Dörfler :
1578efbc276SAxel Dörfler BPartitionHandle(partition)
15891c21ff4SIngo Weinhold {
15991c21ff4SIngo Weinhold }
16091c21ff4SIngo Weinhold
16191c21ff4SIngo Weinhold
~ExtendedPartitionHandle()16291c21ff4SIngo Weinhold ExtendedPartitionHandle::~ExtendedPartitionHandle()
16391c21ff4SIngo Weinhold {
16491c21ff4SIngo Weinhold }
16591c21ff4SIngo Weinhold
16691c21ff4SIngo Weinhold
16791c21ff4SIngo Weinhold status_t
Init()16891c21ff4SIngo Weinhold ExtendedPartitionHandle::Init()
16991c21ff4SIngo Weinhold {
17091c21ff4SIngo Weinhold // initialize the extended partition from the mutable partition
17191c21ff4SIngo Weinhold
17291c21ff4SIngo Weinhold BMutablePartition* partition = Partition();
17391c21ff4SIngo Weinhold
17491c21ff4SIngo Weinhold // our parent has already set the child cookie to the primary partition.
17591c21ff4SIngo Weinhold fPrimaryPartition = (PrimaryPartition*)partition->ChildCookie();
17691c21ff4SIngo Weinhold if (!fPrimaryPartition)
17791c21ff4SIngo Weinhold return B_BAD_VALUE;
17891c21ff4SIngo Weinhold
17991c21ff4SIngo Weinhold if (!fPrimaryPartition->IsExtended())
18091c21ff4SIngo Weinhold return B_BAD_VALUE;
18191c21ff4SIngo Weinhold
18291c21ff4SIngo Weinhold // init the child partitions
18391c21ff4SIngo Weinhold int32 count = partition->CountChildren();
18491c21ff4SIngo Weinhold for (int32 i = 0; i < count; i++) {
18591c21ff4SIngo Weinhold BMutablePartition* child = partition->ChildAt(i);
18693134c5eSBryce Groff
18791c21ff4SIngo Weinhold PartitionType type;
18891c21ff4SIngo Weinhold if (!type.SetType(child->Type()))
18991c21ff4SIngo Weinhold return B_BAD_VALUE;
19091c21ff4SIngo Weinhold
19193134c5eSBryce Groff void* handle = parse_driver_settings_string(child->Parameters());
19293134c5eSBryce Groff if (handle == NULL)
19393134c5eSBryce Groff return B_ERROR;
19493134c5eSBryce Groff
19593134c5eSBryce Groff bool active = get_driver_boolean_parameter(
19693134c5eSBryce Groff handle, "active", false, true);
19793134c5eSBryce Groff
19891c21ff4SIngo Weinhold off_t ptsOffset = 0;
19993134c5eSBryce Groff const char* buffer = get_driver_parameter(handle,
20093134c5eSBryce Groff "partition_table_offset", NULL, NULL);
20193134c5eSBryce Groff if (buffer != NULL)
20293134c5eSBryce Groff ptsOffset = strtoull(buffer, NULL, 10);
20393134c5eSBryce Groff else {
204*af435dd1SX512 unload_driver_settings(handle);
20593134c5eSBryce Groff return B_BAD_VALUE;
20693134c5eSBryce Groff }
207*af435dd1SX512 unload_driver_settings(handle);
20891c21ff4SIngo Weinhold
20991c21ff4SIngo Weinhold LogicalPartition* logical = new(nothrow) LogicalPartition;
21091c21ff4SIngo Weinhold if (!logical)
21191c21ff4SIngo Weinhold return B_NO_MEMORY;
21291c21ff4SIngo Weinhold
21391c21ff4SIngo Weinhold logical->SetTo(child->Offset(), child->Size(), type.Type(), active,
21491c21ff4SIngo Weinhold ptsOffset, fPrimaryPartition);
21591c21ff4SIngo Weinhold
21691c21ff4SIngo Weinhold child->SetChildCookie(logical);
21791c21ff4SIngo Weinhold }
21891c21ff4SIngo Weinhold
21991c21ff4SIngo Weinhold return B_OK;
22091c21ff4SIngo Weinhold }
221fd6477d3SStephan Aßmus
222fd6477d3SStephan Aßmus
223fd6477d3SStephan Aßmus uint32
SupportedOperations(uint32 mask)224fd6477d3SStephan Aßmus ExtendedPartitionHandle::SupportedOperations(uint32 mask)
225fd6477d3SStephan Aßmus {
22693134c5eSBryce Groff uint32 flags = 0;
227fd6477d3SStephan Aßmus
228fd6477d3SStephan Aßmus // creating child
2298efbc276SAxel Dörfler if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) {
230fd6477d3SStephan Aßmus BPartitioningInfo info;
231fd6477d3SStephan Aßmus if (GetPartitioningInfo(&info) == B_OK
232fd6477d3SStephan Aßmus && info.CountPartitionableSpaces() > 1) {
233fd6477d3SStephan Aßmus flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
234fd6477d3SStephan Aßmus }
235fd6477d3SStephan Aßmus }
236fd6477d3SStephan Aßmus
237fd6477d3SStephan Aßmus return flags;
238fd6477d3SStephan Aßmus }
239fd6477d3SStephan Aßmus
240fd6477d3SStephan Aßmus
241fd6477d3SStephan Aßmus uint32
SupportedChildOperations(const BMutablePartition * child,uint32 mask)242fd6477d3SStephan Aßmus ExtendedPartitionHandle::SupportedChildOperations(
243fd6477d3SStephan Aßmus const BMutablePartition* child, uint32 mask)
244fd6477d3SStephan Aßmus {
245fd6477d3SStephan Aßmus return B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD;
246fd6477d3SStephan Aßmus }
247fd6477d3SStephan Aßmus
248fd6477d3SStephan Aßmus
249fd6477d3SStephan Aßmus status_t
GetNextSupportedType(const BMutablePartition * child,int32 * cookie,BString * type)250fd6477d3SStephan Aßmus ExtendedPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
251fd6477d3SStephan Aßmus int32* cookie, BString* type)
252fd6477d3SStephan Aßmus {
2531987b05aSBryce Groff int32 index = *cookie;
2541987b05aSBryce Groff const partition_type* nextType;
2551987b05aSBryce Groff PartitionMap partitionMap;
2561987b05aSBryce Groff while (true) {
2571987b05aSBryce Groff nextType = partitionMap.GetNextSupportedPartitionType(index);
2581987b05aSBryce Groff if (nextType == NULL)
259fd6477d3SStephan Aßmus return B_ENTRY_NOT_FOUND;
2601987b05aSBryce Groff index++;
2611987b05aSBryce Groff if (nextType->used
2621987b05aSBryce Groff && strcmp(nextType->name, kPartitionTypeIntelExtended) != 0)
2631987b05aSBryce Groff break;
2641987b05aSBryce Groff }
2651987b05aSBryce Groff
2661987b05aSBryce Groff if (!nextType)
2671987b05aSBryce Groff return B_ENTRY_NOT_FOUND;
2681987b05aSBryce Groff
2691987b05aSBryce Groff type->SetTo(nextType->name);
2701987b05aSBryce Groff *cookie = index;
2711987b05aSBryce Groff
272fd6477d3SStephan Aßmus return B_OK;
273fd6477d3SStephan Aßmus }
274fd6477d3SStephan Aßmus
275fd6477d3SStephan Aßmus
276fd6477d3SStephan Aßmus status_t
GetPartitioningInfo(BPartitioningInfo * info)277fd6477d3SStephan Aßmus ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info)
278fd6477d3SStephan Aßmus {
27993134c5eSBryce Groff // init to the full size (minus the first PTS_OFFSET)
280fd6477d3SStephan Aßmus BMutablePartition* partition = Partition();
28193134c5eSBryce Groff off_t offset = partition->Offset() + PTS_OFFSET;
28293134c5eSBryce Groff off_t size = partition->Size() - PTS_OFFSET;
283fd6477d3SStephan Aßmus status_t error = info->SetTo(offset, size);
284fd6477d3SStephan Aßmus if (error != B_OK)
285fd6477d3SStephan Aßmus return error;
286fd6477d3SStephan Aßmus
287fd6477d3SStephan Aßmus // exclude the space of the existing logical partitions
288fd6477d3SStephan Aßmus int32 count = partition->CountChildren();
289fd6477d3SStephan Aßmus for (int32 i = 0; i < count; i++) {
290fd6477d3SStephan Aßmus BMutablePartition* child = partition->ChildAt(i);
29193134c5eSBryce Groff error = info->ExcludeOccupiedSpace(child->Offset(),
29293134c5eSBryce Groff child->Size() + PTS_OFFSET + Partition()->BlockSize());
29393134c5eSBryce Groff if (error != B_OK)
29493134c5eSBryce Groff return error;
29593134c5eSBryce Groff
29693134c5eSBryce Groff LogicalPartition* logical = (LogicalPartition*)child->ChildCookie();
29793134c5eSBryce Groff if (logical == NULL)
29893134c5eSBryce Groff return B_BAD_VALUE;
29993134c5eSBryce Groff error = info->ExcludeOccupiedSpace(
30093134c5eSBryce Groff logical->PartitionTableOffset(),
30193134c5eSBryce Groff PTS_OFFSET + Partition()->BlockSize());
302fd6477d3SStephan Aßmus if (error != B_OK)
303fd6477d3SStephan Aßmus return error;
304fd6477d3SStephan Aßmus }
305fd6477d3SStephan Aßmus
306fd6477d3SStephan Aßmus return B_OK;
307fd6477d3SStephan Aßmus }
308fd6477d3SStephan Aßmus
309fd6477d3SStephan Aßmus
310fd6477d3SStephan Aßmus status_t
GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,BPartitionParameterEditor ** editor)3112f3ce2bfSBryce Groff ExtendedPartitionHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,
3127f96148cSIngo Weinhold BPartitionParameterEditor** editor)
313fd6477d3SStephan Aßmus {
314fd6477d3SStephan Aßmus *editor = NULL;
3152f3ce2bfSBryce Groff return B_NOT_SUPPORTED;
316fd6477d3SStephan Aßmus }
317fd6477d3SStephan Aßmus
318fd6477d3SStephan Aßmus
319fd6477d3SStephan Aßmus status_t
ValidateCreateChild(off_t * _offset,off_t * _size,const char * typeString,BString * name,const char * parameters)320fd6477d3SStephan Aßmus ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
321fd6477d3SStephan Aßmus const char* typeString, BString* name, const char* parameters)
322fd6477d3SStephan Aßmus {
323fd6477d3SStephan Aßmus // check type
3241987b05aSBryce Groff if (!typeString)
325fd6477d3SStephan Aßmus return B_BAD_VALUE;
326fd6477d3SStephan Aßmus
327fd6477d3SStephan Aßmus // check name
328fd6477d3SStephan Aßmus if (name)
329fd6477d3SStephan Aßmus name->Truncate(0);
330fd6477d3SStephan Aßmus
3311987b05aSBryce Groff // check the free space situation
3321987b05aSBryce Groff BPartitioningInfo info;
3331987b05aSBryce Groff status_t error = GetPartitioningInfo(&info);
3341987b05aSBryce Groff if (error != B_OK)
3351987b05aSBryce Groff return error;
336fd6477d3SStephan Aßmus
3371987b05aSBryce Groff // any space in the partition at all?
3381987b05aSBryce Groff int32 spacesCount = info.CountPartitionableSpaces();
3391987b05aSBryce Groff if (spacesCount == 0)
3401987b05aSBryce Groff return B_BAD_VALUE;
3411987b05aSBryce Groff
3421987b05aSBryce Groff // check offset and size
3431987b05aSBryce Groff off_t offset = sector_align(*_offset, Partition()->BlockSize());
3441987b05aSBryce Groff off_t size = sector_align(*_size, Partition()->BlockSize());
3451987b05aSBryce Groff // TODO: Rather round size up?
3461987b05aSBryce Groff off_t end = offset + size;
3471987b05aSBryce Groff
3481987b05aSBryce Groff // get the first partitionable space the requested interval intersects with
3491987b05aSBryce Groff int32 spaceIndex = -1;
3501987b05aSBryce Groff int32 closestSpaceIndex = -1;
3511987b05aSBryce Groff off_t closestSpaceDistance = 0;
3521987b05aSBryce Groff for (int32 i = 0; i < spacesCount; i++) {
3531987b05aSBryce Groff off_t spaceOffset, spaceSize;
3541987b05aSBryce Groff info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
3551987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize;
3561987b05aSBryce Groff
357f1143621SWim van der Meer if ((spaceOffset >= offset && spaceOffset < end)
358f1143621SWim van der Meer || (offset >= spaceOffset && offset < spaceEnd)) {
3591987b05aSBryce Groff spaceIndex = i;
3601987b05aSBryce Groff break;
3611987b05aSBryce Groff }
3621987b05aSBryce Groff
3631987b05aSBryce Groff off_t distance;
3641987b05aSBryce Groff if (offset < spaceOffset)
3651987b05aSBryce Groff distance = spaceOffset - end;
3661987b05aSBryce Groff else
3671987b05aSBryce Groff distance = spaceEnd - offset;
3681987b05aSBryce Groff
3691987b05aSBryce Groff if (closestSpaceIndex == -1 || distance < closestSpaceDistance) {
3701987b05aSBryce Groff closestSpaceIndex = i;
3711987b05aSBryce Groff closestSpaceDistance = distance;
3721987b05aSBryce Groff }
3731987b05aSBryce Groff }
3741987b05aSBryce Groff
3751987b05aSBryce Groff // get the space we found
3761987b05aSBryce Groff off_t spaceOffset, spaceSize;
3771987b05aSBryce Groff info.GetPartitionableSpaceAt(
3781987b05aSBryce Groff spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset,
3791987b05aSBryce Groff &spaceSize);
3801987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize;
3811987b05aSBryce Groff
3821987b05aSBryce Groff // If the requested intervald doesn't intersect with any space yet, move
3831987b05aSBryce Groff // it, so that it does.
3841987b05aSBryce Groff if (spaceIndex < 0) {
3851987b05aSBryce Groff spaceIndex = closestSpaceIndex;
3861987b05aSBryce Groff if (offset < spaceOffset) {
3871987b05aSBryce Groff offset = spaceOffset;
3881987b05aSBryce Groff end = offset + size;
3891987b05aSBryce Groff } else {
3901987b05aSBryce Groff end = spaceEnd;
3911987b05aSBryce Groff offset = end - size;
3921987b05aSBryce Groff }
3931987b05aSBryce Groff }
3941987b05aSBryce Groff
3951987b05aSBryce Groff // move/shrink the interval, so that it fully lies within the space
3961987b05aSBryce Groff if (offset < spaceOffset) {
3971987b05aSBryce Groff offset = spaceOffset;
3981987b05aSBryce Groff end = offset + size;
3991987b05aSBryce Groff if (end > spaceEnd) {
4001987b05aSBryce Groff end = spaceEnd;
4011987b05aSBryce Groff size = end - offset;
4021987b05aSBryce Groff }
4031987b05aSBryce Groff } else if (end > spaceEnd) {
4041987b05aSBryce Groff end = spaceEnd;
4051987b05aSBryce Groff offset = end - size;
4061987b05aSBryce Groff if (offset < spaceOffset) {
4071987b05aSBryce Groff offset = spaceOffset;
4081987b05aSBryce Groff size = end - offset;
4091987b05aSBryce Groff }
4101987b05aSBryce Groff }
4111987b05aSBryce Groff
4121987b05aSBryce Groff *_offset = offset;
4131987b05aSBryce Groff *_size = size;
4141987b05aSBryce Groff
4151987b05aSBryce Groff return B_OK;
416fd6477d3SStephan Aßmus }
417fd6477d3SStephan Aßmus
418fd6477d3SStephan Aßmus
419fd6477d3SStephan Aßmus status_t
CreateChild(off_t offset,off_t size,const char * typeString,const char * name,const char * _parameters,BMutablePartition ** _child)420fd6477d3SStephan Aßmus ExtendedPartitionHandle::CreateChild(off_t offset, off_t size,
42193134c5eSBryce Groff const char* typeString, const char* name, const char* _parameters,
422fd6477d3SStephan Aßmus BMutablePartition** _child)
423fd6477d3SStephan Aßmus {
424fd6477d3SStephan Aßmus // check type
4251987b05aSBryce Groff PartitionType type;
4261987b05aSBryce Groff if (!type.SetType(typeString) || type.IsEmpty())
427fd6477d3SStephan Aßmus return B_BAD_VALUE;
428fd6477d3SStephan Aßmus
429fd6477d3SStephan Aßmus // check name
43010d05234SAxel Dörfler if (name != NULL && name[0] != '\0')
431fd6477d3SStephan Aßmus return B_BAD_VALUE;
432fd6477d3SStephan Aßmus
4331987b05aSBryce Groff // offset properly aligned?
4341987b05aSBryce Groff if (offset != sector_align(offset, Partition()->BlockSize())
4351987b05aSBryce Groff || size != sector_align(size, Partition()->BlockSize()))
4361987b05aSBryce Groff return B_BAD_VALUE;
437fd6477d3SStephan Aßmus
4381987b05aSBryce Groff // check the free space situation
4391987b05aSBryce Groff BPartitioningInfo info;
4401987b05aSBryce Groff status_t error = GetPartitioningInfo(&info);
4411987b05aSBryce Groff if (error != B_OK)
4421987b05aSBryce Groff return error;
4431987b05aSBryce Groff
4441987b05aSBryce Groff bool foundSpace = false;
4451987b05aSBryce Groff off_t end = offset + size;
4461987b05aSBryce Groff int32 spacesCount = info.CountPartitionableSpaces();
4471987b05aSBryce Groff for (int32 i = 0; i < spacesCount; i++) {
4481987b05aSBryce Groff off_t spaceOffset, spaceSize;
4491987b05aSBryce Groff info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
4501987b05aSBryce Groff off_t spaceEnd = spaceOffset + spaceSize;
4511987b05aSBryce Groff
4521987b05aSBryce Groff if (offset >= spaceOffset && end <= spaceEnd) {
4531987b05aSBryce Groff foundSpace = true;
4541987b05aSBryce Groff break;
4551987b05aSBryce Groff }
456fd6477d3SStephan Aßmus }
457fd6477d3SStephan Aßmus
4581987b05aSBryce Groff if (!foundSpace)
4591987b05aSBryce Groff return B_BAD_VALUE;
4601987b05aSBryce Groff
46193134c5eSBryce Groff BString parameters(_parameters);
46293134c5eSBryce Groff parameters << "partition_table_offset " << offset - PTS_OFFSET << " ;\n";
46393134c5eSBryce Groff // everything looks good, create the child
4641987b05aSBryce Groff BMutablePartition* child;
4651987b05aSBryce Groff error = Partition()->CreateChild(-1, typeString,
46693134c5eSBryce Groff NULL, parameters.String(), &child);
4671987b05aSBryce Groff if (error != B_OK)
4681987b05aSBryce Groff return error;
4691987b05aSBryce Groff
4701987b05aSBryce Groff // init the child
4711987b05aSBryce Groff child->SetOffset(offset);
4721987b05aSBryce Groff child->SetSize(size);
4731987b05aSBryce Groff child->SetBlockSize(Partition()->BlockSize());
4741987b05aSBryce Groff //child->SetFlags(0);
4751987b05aSBryce Groff child->SetChildCookie(Partition());
4761987b05aSBryce Groff
4771987b05aSBryce Groff *_child = child;
4781987b05aSBryce Groff return B_OK;
4791987b05aSBryce Groff }
4801987b05aSBryce Groff
4811987b05aSBryce Groff
4821987b05aSBryce Groff status_t
DeleteChild(BMutablePartition * child)4831987b05aSBryce Groff ExtendedPartitionHandle::DeleteChild(BMutablePartition* child)
4841987b05aSBryce Groff {
4851987b05aSBryce Groff BMutablePartition* parent = child->Parent();
4861987b05aSBryce Groff status_t error = parent->DeleteChild(child);
4871987b05aSBryce Groff
4881987b05aSBryce Groff return error;
4891987b05aSBryce Groff }
490