xref: /haiku/src/kits/storage/disk_device/MutablePartition.cpp (revision 99d027cd0238c1d86da86d7c3f4200509ccc61a6)
1 /*
2  * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <MutablePartition.h>
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <new>
12 
13 #include <Partition.h>
14 
15 #include <ddm_userland_interface_defs.h>
16 
17 #include "DiskDeviceUtils.h"
18 #include "PartitionDelegate.h"
19 
20 
21 using std::nothrow;
22 
23 
24 // UninitializeContents
25 void
26 BMutablePartition::UninitializeContents()
27 {
28 	DeleteAllChildren();
29 	SetVolumeID(-1);
30 	SetContentName(NULL);
31 	SetContentParameters(NULL);
32 	SetContentSize(0);
33 	SetBlockSize(Parent()->BlockSize());
34 	SetContentType(NULL);
35 	SetStatus(B_PARTITION_UNINITIALIZED);
36 	ClearFlags(B_PARTITION_FILE_SYSTEM | B_PARTITION_PARTITIONING_SYSTEM);
37 //	if (!Device()->IsReadOnlyMedia())
38 //		ClearFlags(B_PARTITION_READ_ONLY);
39 }
40 
41 
42 // Offset
43 off_t
44 BMutablePartition::Offset() const
45 {
46 	return fData->offset;
47 }
48 
49 
50 // SetOffset
51 void
52 BMutablePartition::SetOffset(off_t offset)
53 {
54 	if (fData->offset != offset) {
55 		fData->offset = offset;
56 		Changed(B_PARTITION_CHANGED_OFFSET);
57 	}
58 }
59 
60 
61 // Size
62 off_t
63 BMutablePartition::Size() const
64 {
65 	return fData->size;
66 }
67 
68 
69 // SetSize
70 void
71 BMutablePartition::SetSize(off_t size)
72 {
73 	if (fData->size != size) {
74 		fData->size = size;
75 		Changed(B_PARTITION_CHANGED_SIZE);
76 	}
77 }
78 
79 
80 // ContentSize
81 off_t
82 BMutablePartition::ContentSize() const
83 {
84 	return fData->content_size;
85 }
86 
87 
88 // SetContentSize
89 void
90 BMutablePartition::SetContentSize(off_t size)
91 {
92 	if (fData->content_size != size) {
93 		fData->content_size = size;
94 		Changed(B_PARTITION_CHANGED_CONTENT_SIZE);
95 	}
96 }
97 
98 
99 // BlockSize
100 off_t
101 BMutablePartition::BlockSize() const
102 {
103 	return fData->block_size;
104 }
105 
106 
107 // SetBlockSize
108 void
109 BMutablePartition::SetBlockSize(off_t blockSize)
110 {
111 	if (fData->block_size != blockSize) {
112 		fData->block_size = blockSize;
113 		Changed(B_PARTITION_CHANGED_BLOCK_SIZE);
114 	}
115 }
116 
117 
118 // Status
119 uint32
120 BMutablePartition::Status() const
121 {
122 	return fData->status;
123 }
124 
125 
126 // SetStatus
127 void
128 BMutablePartition::SetStatus(uint32 status)
129 {
130 	if (fData->status != status) {
131 		fData->status = status;
132 		Changed(B_PARTITION_CHANGED_STATUS);
133 	}
134 }
135 
136 
137 // Flags
138 uint32
139 BMutablePartition::Flags() const
140 {
141 	return fData->flags;
142 }
143 
144 
145 // SetFlags
146 void
147 BMutablePartition::SetFlags(uint32 flags)
148 {
149 	if (fData->flags != flags) {
150 		fData->flags = flags;
151 		Changed(B_PARTITION_CHANGED_FLAGS);
152 	}
153 }
154 
155 
156 // ClearFlags
157 void
158 BMutablePartition::ClearFlags(uint32 flags)
159 {
160 	if (flags & fData->flags) {
161 		fData->flags &= ~flags;
162 		Changed(B_PARTITION_CHANGED_FLAGS);
163 	}
164 }
165 
166 
167 // VolumeID
168 dev_t
169 BMutablePartition::VolumeID() const
170 {
171 	return fData->volume;
172 }
173 
174 
175 // SetVolumeID
176 void
177 BMutablePartition::SetVolumeID(dev_t volumeID)
178 {
179 	if (fData->volume != volumeID) {
180 		fData->volume = volumeID;
181 		Changed(B_PARTITION_CHANGED_VOLUME);
182 	}
183 }
184 
185 
186 // Index
187 int32
188 BMutablePartition::Index() const
189 {
190 	return fData->index;
191 }
192 
193 
194 // Name
195 const char*
196 BMutablePartition::Name() const
197 {
198 	return fData->name;
199 }
200 
201 
202 // SetName
203 status_t
204 BMutablePartition::SetName(const char* name)
205 {
206 	if (compare_string(name, fData->name) == 0)
207 		return B_OK;
208 
209 	if (set_string(fData->name, name) != B_OK)
210 		return B_NO_MEMORY;
211 
212 	Changed(B_PARTITION_CHANGED_NAME);
213 	return B_OK;
214 }
215 
216 
217 // ContentName
218 const char*
219 BMutablePartition::ContentName() const
220 {
221 	return fData->content_name;
222 }
223 
224 
225 // SetContentName
226 status_t
227 BMutablePartition::SetContentName(const char* name)
228 {
229 	if (compare_string(name, fData->content_name) == 0)
230 		return B_OK;
231 
232 	if (set_string(fData->content_name, name) != B_OK)
233 		return B_NO_MEMORY;
234 
235 	Changed(B_PARTITION_CHANGED_CONTENT_NAME);
236 	return B_OK;
237 }
238 
239 
240 // Type
241 const char*
242 BMutablePartition::Type() const
243 {
244 	return fData->type;
245 }
246 
247 
248 // SetType
249 status_t
250 BMutablePartition::SetType(const char* type)
251 {
252 	if (compare_string(type, fData->type) == 0)
253 		return B_OK;
254 
255 	if (set_string(fData->type, type) != B_OK)
256 		return B_NO_MEMORY;
257 
258 	Changed(B_PARTITION_CHANGED_TYPE);
259 	return B_OK;
260 }
261 
262 
263 // ContentType
264 const char*
265 BMutablePartition::ContentType() const
266 {
267 	return fData->content_type;
268 }
269 
270 
271 // SetContentType
272 status_t
273 BMutablePartition::SetContentType(const char* type)
274 {
275 	if (compare_string(type, fData->content_type) == 0)
276 		return B_OK;
277 
278 	if (set_string(fData->content_type, type) != B_OK)
279 		return B_NO_MEMORY;
280 
281 	Changed(B_PARTITION_CHANGED_CONTENT_TYPE
282 		| B_PARTITION_CHANGED_INITIALIZATION);
283 	return B_OK;
284 }
285 
286 
287 // Parameters
288 const char*
289 BMutablePartition::Parameters() const
290 {
291 	return fData->parameters;
292 }
293 
294 
295 // SetParameters
296 status_t
297 BMutablePartition::SetParameters(const char* parameters)
298 {
299 	if (compare_string(parameters, fData->parameters) == 0)
300 		return B_OK;
301 
302 	if (set_string(fData->parameters, parameters) != B_OK)
303 		return B_NO_MEMORY;
304 
305 	Changed(B_PARTITION_CHANGED_PARAMETERS);
306 	return B_OK;
307 }
308 
309 
310 // ContentParameters
311 const char*
312 BMutablePartition::ContentParameters() const
313 {
314 	return fData->content_parameters;
315 }
316 
317 
318 // SetContentParameters
319 status_t
320 BMutablePartition::SetContentParameters(const char* parameters)
321 {
322 	if (compare_string(parameters, fData->content_parameters) == 0)
323 		return B_OK;
324 
325 	if (set_string(fData->content_parameters, parameters) != B_OK)
326 		return B_NO_MEMORY;
327 
328 	Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS);
329 	return B_OK;
330 }
331 
332 
333 // CreateChild
334 status_t
335 BMutablePartition::CreateChild(int32 index, BMutablePartition** _child)
336 {
337 	if (index < 0)
338 		index = fChildren.CountItems();
339 	else if (index > fChildren.CountItems())
340 		return B_BAD_VALUE;
341 
342 	// create the BPartition
343 	BPartition* partition = new(nothrow) BPartition;
344 	if (!partition)
345 		return B_NO_MEMORY;
346 
347 	// create the delegate
348 	BPartition::Delegate* delegate
349 		= new(nothrow) BPartition::Delegate(partition);
350 	if (!delegate) {
351 		delete partition;
352 		return B_NO_MEMORY;
353 	}
354 	partition->fDelegate = delegate;
355 
356 	// add the child
357 	BMutablePartition* child = delegate->MutablePartition();
358 	if (!fChildren.AddItem(child, index)) {
359 		delete partition;
360 		return B_NO_MEMORY;
361 	}
362 	child->fParent = this;
363 	child->fData = new(nothrow) user_partition_data;
364 	if (!child->fData) {
365 		fChildren.RemoveItem(child);
366 		delete partition;
367 		return B_NO_MEMORY;
368 	}
369 
370 	memset(child->fData, 0, sizeof(user_partition_data));
371 
372 	child->fData->id = -1;
373 	child->fData->status = B_PARTITION_UNINITIALIZED;
374 	child->fData->volume = -1;
375 	child->fData->index = -1;
376 	child->fData->disk_system = -1;
377 
378 	*_child = child;
379 
380 	Changed(B_PARTITION_CHANGED_CHILDREN);
381 	return B_OK;
382 }
383 
384 
385 // CreateChild
386 status_t
387 BMutablePartition::CreateChild(int32 index, const char* type, const char* name,
388 	const char* parameters, BMutablePartition** _child)
389 {
390 	// create the child
391 	BMutablePartition* child;
392 	status_t error = CreateChild(index, &child);
393 	if (error != B_OK)
394 		return error;
395 
396 	// set the name, type, and parameters
397 	error = child->SetType(type);
398 	if (error == B_OK)
399 		error = child->SetName(name);
400 	if (error == B_OK)
401 		error = child->SetParameters(parameters);
402 
403 	// cleanup on error
404 	if (error != B_OK) {
405 		DeleteChild(child);
406 		return error;
407 	}
408 
409 	*_child = child;
410 
411 	Changed(B_PARTITION_CHANGED_CHILDREN);
412 	return B_OK;
413 }
414 
415 
416 // DeleteChild
417 status_t
418 BMutablePartition::DeleteChild(int32 index)
419 {
420 	BMutablePartition* child = (BMutablePartition*)fChildren.RemoveItem(index);
421 	if (!child)
422 		return B_BAD_VALUE;
423 
424 	// This will delete not only all delegates in the child's hierarchy, but
425 	// also the respective partitions themselves, if they are no longer
426 	// referenced.
427 	child->fDelegate->Partition()->_DeleteDelegates();
428 
429 	Changed(B_PARTITION_CHANGED_CHILDREN);
430 	return B_OK;
431 }
432 
433 
434 // DeleteChild
435 status_t
436 BMutablePartition::DeleteChild(BMutablePartition* child)
437 {
438 	return DeleteChild(IndexOfChild(child));
439 }
440 
441 
442 // DeleteAllChildren
443 void
444 BMutablePartition::DeleteAllChildren()
445 {
446 	int32 count = CountChildren();
447 	for (int32 i = count - 1; i >= 0; i--)
448 		DeleteChild(i);
449 }
450 
451 
452 // Parent
453 BMutablePartition*
454 BMutablePartition::Parent() const
455 {
456 	return fParent;
457 }
458 
459 
460 // ChildAt
461 BMutablePartition*
462 BMutablePartition::ChildAt(int32 index) const
463 {
464 	return (BMutablePartition*)fChildren.ItemAt(index);
465 }
466 
467 
468 // CountChildren
469 int32
470 BMutablePartition::CountChildren() const
471 {
472 	return fChildren.CountItems();
473 }
474 
475 
476 // IndexOfChild
477 int32
478 BMutablePartition::IndexOfChild(BMutablePartition* child) const
479 {
480 	if (!child)
481 		return -1;
482 	return fChildren.IndexOf(child);
483 }
484 
485 
486 // SetChangeFlags
487 void
488 BMutablePartition::SetChangeFlags(uint32 flags)
489 {
490 	fChangeFlags = flags;
491 }
492 
493 
494 // ChangeFlags
495 uint32
496 BMutablePartition::ChangeFlags() const
497 {
498 	return fChangeFlags;
499 }
500 
501 
502 // Changed
503 void
504 BMutablePartition::Changed(uint32 flags, uint32 clearFlags)
505 {
506 	fChangeFlags &= ~clearFlags;
507 	fChangeFlags |= flags;
508 
509 	if (Parent())
510 		Parent()->Changed(B_PARTITION_CHANGED_DESCENDANTS);
511 }
512 
513 
514 // ChildCookie
515 void*
516 BMutablePartition::ChildCookie() const
517 {
518 	return fChildCookie;
519 }
520 
521 
522 // SetChildCookie
523 void
524 BMutablePartition::SetChildCookie(void* cookie)
525 {
526 	fChildCookie = cookie;
527 }
528 
529 
530 // constructor
531 BMutablePartition::BMutablePartition(BPartition::Delegate* delegate)
532 	: fDelegate(delegate),
533 	  fData(NULL),
534 	  fParent(NULL),
535 	  fChangeFlags(0),
536 	  fChildCookie(NULL)
537 {
538 }
539 
540 
541 // Init
542 status_t
543 BMutablePartition::Init(const user_partition_data* partitionData,
544 	BMutablePartition* parent)
545 {
546 	fParent = parent;
547 
548 	// add to the parent's child list
549 	if (fParent) {
550 		if (!fParent->fChildren.AddItem(this))
551 			return B_NO_MEMORY;
552 	}
553 
554 	// allocate data structure
555 	fData = new(nothrow) user_partition_data;
556 	if (!fData)
557 		return B_NO_MEMORY;
558 
559 	memset(fData, 0, sizeof(user_partition_data));
560 
561 	// copy the flat data
562 	fData->id = partitionData->id;
563 	fData->offset = partitionData->offset;
564 	fData->size = partitionData->size;
565 	fData->content_size = partitionData->content_size;
566 	fData->block_size = partitionData->block_size;
567 	fData->status = partitionData->status;
568 	fData->flags = partitionData->flags;
569 	fData->volume = partitionData->volume;
570 	fData->index = partitionData->index;
571 	fData->change_counter = partitionData->change_counter;
572 	fData->disk_system = partitionData->disk_system;
573 
574 	// copy the strings
575 	SET_STRING_RETURN_ON_ERROR(fData->name, partitionData->name);
576 	SET_STRING_RETURN_ON_ERROR(fData->content_name,
577 		partitionData->content_name);
578 	SET_STRING_RETURN_ON_ERROR(fData->type, partitionData->type);
579 	SET_STRING_RETURN_ON_ERROR(fData->content_type,
580 		partitionData->content_type);
581 	SET_STRING_RETURN_ON_ERROR(fData->parameters, partitionData->parameters);
582 	SET_STRING_RETURN_ON_ERROR(fData->content_parameters,
583 		partitionData->content_parameters);
584 
585 	return B_OK;
586 }
587 
588 
589 // destructor
590 BMutablePartition::~BMutablePartition()
591 {
592 	if (fData) {
593 		free(fData->name);
594 		free(fData->content_name);
595 		free(fData->type);
596 		free(fData->content_type);
597 		free(fData->parameters);
598 		free(fData->content_parameters);
599 		delete fData;
600 	}
601 }
602 
603 
604 // PartitionData
605 const user_partition_data*
606 BMutablePartition::PartitionData() const
607 {
608 	return fData;
609 }
610 
611 
612 // GetDelegate
613 BPartition::Delegate*
614 BMutablePartition::GetDelegate() const
615 {
616 	return fDelegate;
617 }
618 
619