1/*
2 * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "PartitionDelegate.h"
7
8#include <stdio.h>
9
10#include <DiskSystemAddOn.h>
11#include <DiskSystemAddOnManager.h>
12
13//#define TRACE_PARTITION_DELEGATE
14#undef TRACE
15#ifdef TRACE_PARTITION_DELEGATE
16# define TRACE(x...) printf(x)
17#else
18# define TRACE(x...) do {} while (false)
19#endif
20
21
22// constructor
23BPartition::Delegate::Delegate(BPartition* partition)
24	:
25	fPartition(partition),
26	fMutablePartition(this),
27	fDiskSystem(NULL),
28	fPartitionHandle(NULL)
29{
30}
31
32
33// destructor
34BPartition::Delegate::~Delegate()
35{
36}
37
38
39// MutablePartition
40BMutablePartition*
41BPartition::Delegate::MutablePartition()
42{
43	return &fMutablePartition;
44}
45
46
47// MutablePartition
48const BMutablePartition*
49BPartition::Delegate::MutablePartition() const
50{
51	return &fMutablePartition;
52}
53
54
55// InitHierarchy
56status_t
57BPartition::Delegate::InitHierarchy(
58	const user_partition_data* partitionData, Delegate* parent)
59{
60	return fMutablePartition.Init(partitionData,
61		parent ? &parent->fMutablePartition : NULL);
62}
63
64
65// InitAfterHierarchy
66status_t
67BPartition::Delegate::InitAfterHierarchy()
68{
69	TRACE("%p->BPartition::Delegate::InitAfterHierarchy()\n", this);
70
71	if (!fMutablePartition.ContentType()) {
72		TRACE("  no content type\n");
73		return B_OK;
74	}
75
76	// init disk system and handle
77	DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default();
78	BDiskSystemAddOn* addOn = manager->GetAddOn(
79		fMutablePartition.ContentType());
80	if (!addOn) {
81		TRACE("  add-on for disk system \"%s\" not found\n",
82			fMutablePartition.ContentType());
83		return B_OK;
84	}
85
86	BPartitionHandle* handle;
87	status_t error = addOn->CreatePartitionHandle(&fMutablePartition, &handle);
88	if (error != B_OK) {
89		TRACE("  failed to create partition handle for partition %ld, disk "
90			"system: \"%s\": %s\n",
91			Partition()->ID(), addOn->Name(), strerror(error));
92		manager->PutAddOn(addOn);
93		return error;
94	}
95
96	// everything went fine -- keep the disk system add-on reference and the
97	// handle
98	fDiskSystem = addOn;
99	fPartitionHandle = handle;
100
101	return B_OK;
102}
103
104
105// PartitionData
106const user_partition_data*
107BPartition::Delegate::PartitionData() const
108{
109	return fMutablePartition.PartitionData();
110}
111
112
113// ChildAt
114BPartition::Delegate*
115BPartition::Delegate::ChildAt(int32 index) const
116{
117	BMutablePartition* child = fMutablePartition.ChildAt(index);
118	return child ? child->GetDelegate() : NULL;
119}
120
121
122// CountChildren
123int32
124BPartition::Delegate::CountChildren() const
125{
126	return fMutablePartition.CountChildren();
127}
128
129
130// IsModified
131bool
132BPartition::Delegate::IsModified() const
133{
134	return fMutablePartition.ChangeFlags() != 0;
135}
136
137
138// SupportedOperations
139uint32
140BPartition::Delegate::SupportedOperations(uint32 mask)
141{
142	if (!fPartitionHandle)
143		return 0;
144
145	return fPartitionHandle->SupportedOperations(mask);
146}
147
148
149// SupportedChildOperations
150uint32
151BPartition::Delegate::SupportedChildOperations(Delegate* child,
152	uint32 mask)
153{
154	if (!fPartitionHandle)
155		return 0;
156
157	return fPartitionHandle->SupportedChildOperations(child->MutablePartition(),
158		mask);
159}
160
161
162// Defragment
163status_t
164BPartition::Delegate::Defragment()
165{
166// TODO: Implement!
167	return B_BAD_VALUE;
168}
169
170
171// Repair
172status_t
173BPartition::Delegate::Repair(bool checkOnly)
174{
175	if (fPartitionHandle == NULL)
176		return B_NO_INIT;
177
178	return fPartitionHandle->Repair(checkOnly);
179}
180
181
182// ValidateResize
183status_t
184BPartition::Delegate::ValidateResize(off_t* size) const
185{
186	if (!fPartitionHandle)
187		return B_NO_INIT;
188
189	return fPartitionHandle->ValidateResize(size);
190}
191
192
193// ValidateResizeChild
194status_t
195BPartition::Delegate::ValidateResizeChild(Delegate* child, off_t* size) const
196{
197	if (!fPartitionHandle || !child)
198		return B_NO_INIT;
199
200	return fPartitionHandle->ValidateResizeChild(&child->fMutablePartition,
201		size);
202}
203
204
205// Resize
206status_t
207BPartition::Delegate::Resize(off_t size)
208{
209	if (!fPartitionHandle)
210		return B_NO_INIT;
211
212	return fPartitionHandle->Resize(size);
213}
214
215
216// ResizeChild
217status_t
218BPartition::Delegate::ResizeChild(Delegate* child, off_t size)
219{
220	if (!fPartitionHandle || !child)
221		return B_NO_INIT;
222
223	return fPartitionHandle->ResizeChild(&child->fMutablePartition, size);
224}
225
226
227// ValidateMove
228status_t
229BPartition::Delegate::ValidateMove(off_t* offset) const
230{
231	if (!fPartitionHandle)
232		return B_NO_INIT;
233
234	return fPartitionHandle->ValidateMove(offset);
235}
236
237
238// ValidateMoveChild
239status_t
240BPartition::Delegate::ValidateMoveChild(Delegate* child, off_t* offset) const
241{
242	if (!fPartitionHandle || !child)
243		return B_NO_INIT;
244
245	return fPartitionHandle->ValidateMoveChild(&child->fMutablePartition,
246		offset);
247}
248
249
250// Move
251status_t
252BPartition::Delegate::Move(off_t offset)
253{
254	if (!fPartitionHandle)
255		return B_NO_INIT;
256
257	return fPartitionHandle->Move(offset);
258}
259
260
261// MoveChild
262status_t
263BPartition::Delegate::MoveChild(Delegate* child, off_t offset)
264{
265	if (!fPartitionHandle || !child)
266		return B_NO_INIT;
267
268	return fPartitionHandle->MoveChild(&child->fMutablePartition, offset);
269}
270
271
272// ValidateSetContentName
273status_t
274BPartition::Delegate::ValidateSetContentName(BString* name) const
275{
276	if (!fPartitionHandle)
277		return B_NO_INIT;
278
279	return fPartitionHandle->ValidateSetContentName(name);
280}
281
282
283// ValidateSetName
284status_t
285BPartition::Delegate::ValidateSetName(Delegate* child, BString* name) const
286{
287	if (!fPartitionHandle || !child)
288		return B_NO_INIT;
289
290	return fPartitionHandle->ValidateSetName(&child->fMutablePartition, name);
291}
292
293
294// SetContentName
295status_t
296BPartition::Delegate::SetContentName(const char* name)
297{
298	if (!fPartitionHandle)
299		return B_NO_INIT;
300
301	return fPartitionHandle->SetContentName(name);
302}
303
304
305// SetName
306status_t
307BPartition::Delegate::SetName(Delegate* child, const char* name)
308{
309	if (!fPartitionHandle || !child)
310		return B_NO_INIT;
311
312	return fPartitionHandle->SetName(&child->fMutablePartition, name);
313}
314
315
316// ValidateSetType
317status_t
318BPartition::Delegate::ValidateSetType(Delegate* child, const char* type) const
319{
320	if (!fPartitionHandle || !child)
321		return B_NO_INIT;
322
323	return fPartitionHandle->ValidateSetType(&child->fMutablePartition, type);
324}
325
326
327// SetType
328status_t
329BPartition::Delegate::SetType(Delegate* child, const char* type)
330{
331	if (!fPartitionHandle || !child)
332		return B_NO_INIT;
333
334	return fPartitionHandle->SetType(&child->fMutablePartition, type);
335}
336
337
338// SetContentParameters
339status_t
340BPartition::Delegate::SetContentParameters(const char* parameters)
341{
342	if (!fPartitionHandle)
343		return B_NO_INIT;
344
345	return fPartitionHandle->SetContentParameters(parameters);
346}
347
348
349// SetParameters
350status_t
351BPartition::Delegate::SetParameters(Delegate* child, const char* parameters)
352{
353	if (!fPartitionHandle || !child)
354		return B_NO_INIT;
355
356	return fPartitionHandle->SetParameters(&child->fMutablePartition,
357		parameters);
358}
359
360
361// GetNextSupportedChildType
362status_t
363BPartition::Delegate::GetNextSupportedChildType(Delegate* child,
364	int32* cookie, BString* type) const
365{
366	TRACE("%p->BPartition::Delegate::GetNextSupportedChildType(child: %p, "
367		"cookie: %ld)\n", this, child, *cookie);
368
369	if (!fPartitionHandle) {
370		TRACE("  no partition handle!\n");
371		return B_NO_INIT;
372	}
373
374	return fPartitionHandle->GetNextSupportedType(
375		child ? &child->fMutablePartition : NULL, cookie, type);
376}
377
378
379// IsSubSystem
380bool
381BPartition::Delegate::IsSubSystem(Delegate* child,
382	const char* diskSystem) const
383{
384	// get the disk system add-on
385	DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default();
386	BDiskSystemAddOn* addOn = manager->GetAddOn(diskSystem);
387	if (!addOn)
388		return false;
389
390	bool result = addOn->IsSubSystemFor(&child->fMutablePartition);
391
392	// put the add-on
393	manager->PutAddOn(addOn);
394
395	return result;
396}
397
398
399// CanInitialize
400bool
401BPartition::Delegate::CanInitialize(const char* diskSystem) const
402{
403	// get the disk system add-on
404	DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default();
405	BDiskSystemAddOn* addOn = manager->GetAddOn(diskSystem);
406	if (!addOn)
407		return false;
408
409	bool result = addOn->CanInitialize(&fMutablePartition);
410
411	// put the add-on
412	manager->PutAddOn(addOn);
413
414	return result;
415}
416
417
418// ValidateInitialize
419status_t
420BPartition::Delegate::ValidateInitialize(const char* diskSystem,
421	BString* name, const char* parameters)
422{
423	// get the disk system add-on
424	DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default();
425	BDiskSystemAddOn* addOn = manager->GetAddOn(diskSystem);
426	if (!addOn)
427		return B_ENTRY_NOT_FOUND;
428
429	status_t result = addOn->ValidateInitialize(&fMutablePartition,
430		name, parameters);
431
432	// put the add-on
433	manager->PutAddOn(addOn);
434
435	return result;
436}
437
438
439// Initialize
440status_t
441BPartition::Delegate::Initialize(const char* diskSystem,
442	const char* name, const char* parameters)
443{
444	// get the disk system add-on
445	DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default();
446	BDiskSystemAddOn* addOn = manager->GetAddOn(diskSystem);
447	if (!addOn)
448		return B_ENTRY_NOT_FOUND;
449
450	BPartitionHandle* handle;
451	status_t result = addOn->Initialize(&fMutablePartition, name, parameters,
452		&handle);
453
454	// keep the add-on or put it on error
455	if (result == B_OK) {
456		// TODO: This won't suffice. If this partition had children, we have
457		// to delete them before the new disk system plays with it.
458		_FreeHandle();
459		fDiskSystem = addOn;
460		fPartitionHandle = handle;
461	} else {
462		manager->PutAddOn(addOn);
463	}
464
465	return result;
466}
467
468
469// Uninitialize
470status_t
471BPartition::Delegate::Uninitialize()
472{
473	if (fPartitionHandle) {
474		_FreeHandle();
475
476		fMutablePartition.UninitializeContents();
477	}
478
479	return B_OK;
480}
481
482
483// GetPartitioningInfo
484status_t
485BPartition::Delegate::GetPartitioningInfo(BPartitioningInfo* info)
486{
487	if (!fPartitionHandle)
488		return B_NO_INIT;
489
490	return fPartitionHandle->GetPartitioningInfo(info);
491}
492
493
494// GetParameterEditor
495status_t
496BPartition::Delegate::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,
497	BPartitionParameterEditor** editor) const
498{
499	if (!fPartitionHandle)
500		return B_NO_INIT;
501
502	return fPartitionHandle->GetParameterEditor(type, editor);
503}
504
505
506// ValidateCreateChild
507status_t
508BPartition::Delegate::ValidateCreateChild(off_t* start, off_t* size,
509	const char* type, BString* name, const char* parameters) const
510{
511	if (!fPartitionHandle)
512		return B_NO_INIT;
513
514	return fPartitionHandle->ValidateCreateChild(start, size, type, name,
515		parameters);
516}
517
518
519// CreateChild
520status_t
521BPartition::Delegate::CreateChild(off_t start, off_t size, const char* type,
522	const char* name, const char* parameters, BPartition** child)
523{
524	if (!fPartitionHandle)
525		return B_NO_INIT;
526
527	BMutablePartition* mutableChild;
528	status_t error = fPartitionHandle->CreateChild(start, size, type, name,
529		parameters, &mutableChild);
530	if (error != B_OK)
531		return error;
532
533	if (child)
534		*child = mutableChild->GetDelegate()->Partition();
535
536	return B_OK;
537}
538
539
540// DeleteChild
541status_t
542BPartition::Delegate::DeleteChild(Delegate* child)
543{
544	if (!fPartitionHandle || !child)
545		return B_NO_INIT;
546
547	return fPartitionHandle->DeleteChild(&child->fMutablePartition);
548}
549
550
551// _FreeHandle
552void
553BPartition::Delegate::_FreeHandle()
554{
555	if (fPartitionHandle) {
556		delete fPartitionHandle;
557		fPartitionHandle = NULL;
558
559		DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default();
560		manager->PutAddOn(fDiskSystem);
561		fDiskSystem = NULL;
562	}
563}
564