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 21using std::nothrow; 22 23 24// UninitializeContents 25void 26BMutablePartition::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 43off_t 44BMutablePartition::Offset() const 45{ 46 return fData->offset; 47} 48 49 50// SetOffset 51void 52BMutablePartition::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 62off_t 63BMutablePartition::Size() const 64{ 65 return fData->size; 66} 67 68 69// SetSize 70void 71BMutablePartition::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 81off_t 82BMutablePartition::ContentSize() const 83{ 84 return fData->content_size; 85} 86 87 88// SetContentSize 89void 90BMutablePartition::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 100off_t 101BMutablePartition::BlockSize() const 102{ 103 return fData->block_size; 104} 105 106 107// SetBlockSize 108void 109BMutablePartition::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 119uint32 120BMutablePartition::Status() const 121{ 122 return fData->status; 123} 124 125 126// SetStatus 127void 128BMutablePartition::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 138uint32 139BMutablePartition::Flags() const 140{ 141 return fData->flags; 142} 143 144 145// SetFlags 146void 147BMutablePartition::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 157void 158BMutablePartition::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 168dev_t 169BMutablePartition::VolumeID() const 170{ 171 return fData->volume; 172} 173 174 175// SetVolumeID 176void 177BMutablePartition::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 187int32 188BMutablePartition::Index() const 189{ 190 return fData->index; 191} 192 193 194// Name 195const char* 196BMutablePartition::Name() const 197{ 198 return fData->name; 199} 200 201 202// SetName 203status_t 204BMutablePartition::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 218BString 219BMutablePartition::ContentName() const 220{ 221 return fData->content_name; 222} 223 224 225// SetContentName 226status_t 227BMutablePartition::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 241const char* 242BMutablePartition::Type() const 243{ 244 return fData->type; 245} 246 247 248// SetType 249status_t 250BMutablePartition::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 264const char* 265BMutablePartition::ContentType() const 266{ 267 return fData->content_type; 268} 269 270 271// SetContentType 272status_t 273BMutablePartition::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 288const char* 289BMutablePartition::Parameters() const 290{ 291 return fData->parameters; 292} 293 294 295// SetParameters 296status_t 297BMutablePartition::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 311const char* 312BMutablePartition::ContentParameters() const 313{ 314 return fData->content_parameters; 315} 316 317 318// SetContentParameters 319status_t 320BMutablePartition::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 334status_t 335BMutablePartition::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 386status_t 387BMutablePartition::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 417status_t 418BMutablePartition::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 435status_t 436BMutablePartition::DeleteChild(BMutablePartition* child) 437{ 438 return DeleteChild(IndexOfChild(child)); 439} 440 441 442// DeleteAllChildren 443void 444BMutablePartition::DeleteAllChildren() 445{ 446 int32 count = CountChildren(); 447 for (int32 i = count - 1; i >= 0; i--) 448 DeleteChild(i); 449} 450 451 452// Parent 453BMutablePartition* 454BMutablePartition::Parent() const 455{ 456 return fParent; 457} 458 459 460// ChildAt 461BMutablePartition* 462BMutablePartition::ChildAt(int32 index) const 463{ 464 return (BMutablePartition*)fChildren.ItemAt(index); 465} 466 467 468// CountChildren 469int32 470BMutablePartition::CountChildren() const 471{ 472 return fChildren.CountItems(); 473} 474 475 476// IndexOfChild 477int32 478BMutablePartition::IndexOfChild(BMutablePartition* child) const 479{ 480 if (!child) 481 return -1; 482 return fChildren.IndexOf(child); 483} 484 485 486// SetChangeFlags 487void 488BMutablePartition::SetChangeFlags(uint32 flags) 489{ 490 fChangeFlags = flags; 491} 492 493 494// ChangeFlags 495uint32 496BMutablePartition::ChangeFlags() const 497{ 498 return fChangeFlags; 499} 500 501 502// Changed 503void 504BMutablePartition::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 515void* 516BMutablePartition::ChildCookie() const 517{ 518 return fChildCookie; 519} 520 521 522// SetChildCookie 523void 524BMutablePartition::SetChildCookie(void* cookie) 525{ 526 fChildCookie = cookie; 527} 528 529 530// constructor 531BMutablePartition::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 542status_t 543BMutablePartition::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->physical_block_size = partitionData->physical_block_size; 568 fData->status = partitionData->status; 569 fData->flags = partitionData->flags; 570 fData->volume = partitionData->volume; 571 fData->index = partitionData->index; 572 fData->change_counter = partitionData->change_counter; 573 fData->disk_system = partitionData->disk_system; 574 575 // copy the strings 576 SET_STRING_RETURN_ON_ERROR(fData->name, partitionData->name); 577 SET_STRING_RETURN_ON_ERROR(fData->content_name, 578 partitionData->content_name); 579 SET_STRING_RETURN_ON_ERROR(fData->type, partitionData->type); 580 SET_STRING_RETURN_ON_ERROR(fData->content_type, 581 partitionData->content_type); 582 SET_STRING_RETURN_ON_ERROR(fData->parameters, partitionData->parameters); 583 SET_STRING_RETURN_ON_ERROR(fData->content_parameters, 584 partitionData->content_parameters); 585 586 return B_OK; 587} 588 589 590// destructor 591BMutablePartition::~BMutablePartition() 592{ 593 if (fData) { 594 free(fData->name); 595 free(fData->content_name); 596 free(fData->type); 597 free(fData->content_type); 598 free(fData->parameters); 599 free(fData->content_parameters); 600 delete fData; 601 } 602} 603 604 605// PartitionData 606const user_partition_data* 607BMutablePartition::PartitionData() const 608{ 609 return fData; 610} 611 612 613// GetDelegate 614BPartition::Delegate* 615BMutablePartition::GetDelegate() const 616{ 617 return fDelegate; 618} 619 620