xref: /haiku/src/kits/storage/disk_device/MutablePartition.cpp (revision ddac407426cd3b3d0b4589d7a161b300b3539a2a)
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