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 // TODO: Any further initialization required? 356 357 // add the child 358 BMutablePartition* child = delegate->MutablePartition(); 359 if (!fChildren.AddItem(child, index)) { 360 delete partition; 361 return B_NO_MEMORY; 362 } 363 child->fParent = this; 364 365 *_child = child; 366 367 Changed(B_PARTITION_CHANGED_CHILDREN); 368 return B_OK; 369 } 370 371 372 // CreateChild 373 status_t 374 BMutablePartition::CreateChild(int32 index, const char* type, const char* name, 375 const char* parameters, BMutablePartition** _child) 376 { 377 // create the child 378 BMutablePartition* child; 379 status_t error = CreateChild(index, &child); 380 if (error != B_OK) 381 return error; 382 383 // set the name, type, and parameters 384 error = SetType(type); 385 if (error == B_OK) 386 error = SetName(name); 387 if (error == B_OK) 388 error = SetParameters(parameters); 389 390 // cleanup on error 391 if (error != B_OK) { 392 DeleteChild(child); 393 return error; 394 } 395 396 *_child = child; 397 398 Changed(B_PARTITION_CHANGED_CHILDREN); 399 return B_OK; 400 } 401 402 403 // DeleteChild 404 status_t 405 BMutablePartition::DeleteChild(int32 index) 406 { 407 BMutablePartition* child = (BMutablePartition*)fChildren.RemoveItem(index); 408 if (!child) 409 return B_BAD_VALUE; 410 411 // This will delete not only all delegates in the child's hierarchy, but 412 // also the respective partitions themselves, if they are no longer 413 // referenced. 414 child->fDelegate->Partition()->_DeleteDelegates(); 415 416 Changed(B_PARTITION_CHANGED_CHILDREN); 417 return B_OK; 418 } 419 420 421 // DeleteChild 422 status_t 423 BMutablePartition::DeleteChild(BMutablePartition* child) 424 { 425 return DeleteChild(IndexOfChild(child)); 426 } 427 428 429 // DeleteAllChildren 430 void 431 BMutablePartition::DeleteAllChildren() 432 { 433 int32 count = CountChildren(); 434 for (int32 i = count - 1; i >= 0; i--) 435 DeleteChild(i); 436 } 437 438 439 // Parent 440 BMutablePartition* 441 BMutablePartition::Parent() const 442 { 443 return fParent; 444 } 445 446 447 // ChildAt 448 BMutablePartition* 449 BMutablePartition::ChildAt(int32 index) const 450 { 451 return (BMutablePartition*)fChildren.ItemAt(index); 452 } 453 454 455 // CountChildren 456 int32 457 BMutablePartition::CountChildren() const 458 { 459 return fChildren.CountItems(); 460 } 461 462 463 // IndexOfChild 464 int32 465 BMutablePartition::IndexOfChild(BMutablePartition* child) const 466 { 467 if (!child) 468 return -1; 469 return fChildren.IndexOf(child); 470 } 471 472 473 // SetChangeFlags 474 void 475 BMutablePartition::SetChangeFlags(uint32 flags) 476 { 477 fChangeFlags = flags; 478 } 479 480 481 // ChangeFlags 482 uint32 483 BMutablePartition::ChangeFlags() const 484 { 485 return fChangeFlags; 486 } 487 488 489 // Changed 490 void 491 BMutablePartition::Changed(uint32 flags, uint32 clearFlags) 492 { 493 fChangeFlags &= ~clearFlags; 494 fChangeFlags |= flags; 495 496 if (Parent()) 497 Parent()->Changed(B_PARTITION_CHANGED_DESCENDANTS); 498 } 499 500 501 // ChildCookie 502 void* 503 BMutablePartition::ChildCookie() const 504 { 505 return fChildCookie; 506 } 507 508 509 // SetChildCookie 510 void 511 BMutablePartition::SetChildCookie(void* cookie) 512 { 513 fChildCookie = cookie; 514 } 515 516 517 // constructor 518 BMutablePartition::BMutablePartition(BPartition::Delegate* delegate) 519 : fDelegate(delegate), 520 fData(NULL), 521 fParent(NULL), 522 fChangeFlags(0), 523 fChildCookie(NULL) 524 { 525 } 526 527 528 // Init 529 status_t 530 BMutablePartition::Init(const user_partition_data* partitionData, 531 BMutablePartition* parent) 532 { 533 fParent = parent; 534 535 // add to the parent's child list 536 if (fParent) { 537 if (!fParent->fChildren.AddItem(this)) 538 return B_NO_MEMORY; 539 } 540 541 // allocate data structure 542 fData = new(nothrow) user_partition_data; 543 if (!fData) 544 return B_NO_MEMORY; 545 546 memset(fData, 0, sizeof(user_partition_data)); 547 548 // copy the flat data 549 fData->id = partitionData->id; 550 fData->offset = partitionData->offset; 551 fData->size = partitionData->size; 552 fData->content_size = partitionData->content_size; 553 fData->block_size = partitionData->block_size; 554 fData->status = partitionData->status; 555 fData->flags = partitionData->flags; 556 fData->volume = partitionData->volume; 557 fData->index = partitionData->index; 558 fData->change_counter = partitionData->change_counter; 559 fData->disk_system = partitionData->disk_system; 560 561 // copy the strings 562 SET_STRING_RETURN_ON_ERROR(fData->name, partitionData->name); 563 SET_STRING_RETURN_ON_ERROR(fData->content_name, 564 partitionData->content_name); 565 SET_STRING_RETURN_ON_ERROR(fData->type, partitionData->type); 566 SET_STRING_RETURN_ON_ERROR(fData->content_type, 567 partitionData->content_type); 568 SET_STRING_RETURN_ON_ERROR(fData->parameters, partitionData->parameters); 569 SET_STRING_RETURN_ON_ERROR(fData->content_parameters, 570 partitionData->content_parameters); 571 572 return B_OK; 573 } 574 575 576 // destructor 577 BMutablePartition::~BMutablePartition() 578 { 579 if (fData) { 580 free(fData->name); 581 free(fData->content_name); 582 free(fData->type); 583 free(fData->content_type); 584 free(fData->parameters); 585 free(fData->content_parameters); 586 delete fData; 587 } 588 } 589 590 591 // PartitionData 592 const user_partition_data* 593 BMutablePartition::PartitionData() const 594 { 595 return fData; 596 } 597 598 599 // GetDelegate 600 BPartition::Delegate* 601 BMutablePartition::GetDelegate() const 602 { 603 return fDelegate; 604 } 605 606