xref: /haiku/src/add-ons/disk_systems/intel/ExtendedPartitionAddOn.cpp (revision 10d0523409a858bc1abb7437c991f2f0ad1e3fca)
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