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