1 // KPartitioningSystem.cpp 2 3 #include <fcntl.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 7 #include <ddm_modules.h> 8 #include <KDiskDevice.h> 9 #include <KDiskDeviceJob.h> 10 #include <KDiskDeviceManager.h> 11 #include <KDiskDeviceUtils.h> 12 #include <KPartition.h> 13 #include <KPartitioningSystem.h> 14 15 // constructor 16 KPartitioningSystem::KPartitioningSystem(const char *name) 17 : KDiskSystem(name), 18 fModule(NULL) 19 { 20 } 21 22 // destructor 23 KPartitioningSystem::~KPartitioningSystem() 24 { 25 } 26 27 // Init 28 status_t 29 KPartitioningSystem::Init() 30 { 31 status_t error = KDiskSystem::Init(); 32 if (error != B_OK) 33 return error; 34 error = Load(); 35 if (error != B_OK) 36 return error; 37 error = SetPrettyName(fModule->pretty_name); 38 SetFlags(fModule->flags & ~(uint32)B_DISK_SYSTEM_IS_FILE_SYSTEM); 39 Unload(); 40 return error; 41 } 42 43 // Identify 44 float 45 KPartitioningSystem::Identify(KPartition *partition, void **cookie) 46 { 47 if (!partition || !cookie || !fModule || !fModule->identify_partition) 48 return -1; 49 int fd = -1; 50 if (partition->Open(O_RDONLY, &fd) != B_OK) 51 return -1; 52 float result = fModule->identify_partition(fd, partition->PartitionData(), 53 cookie); 54 close(fd); 55 return result; 56 } 57 58 // Scan 59 status_t 60 KPartitioningSystem::Scan(KPartition *partition, void *cookie) 61 { 62 if (!partition || !fModule || !fModule->scan_partition) 63 return B_ERROR; 64 int fd = -1; 65 status_t result = partition->Open(O_RDONLY, &fd); 66 if (result != B_OK) 67 return result; 68 result = fModule->scan_partition(fd, partition->PartitionData(), cookie); 69 close(fd); 70 return result; 71 } 72 73 // FreeIdentifyCookie 74 void 75 KPartitioningSystem::FreeIdentifyCookie(KPartition *partition, void *cookie) 76 { 77 if (!partition || !fModule || !fModule->free_identify_partition_cookie) 78 return; 79 fModule->free_identify_partition_cookie(partition->PartitionData(), 80 cookie); 81 } 82 83 // FreeCookie 84 void 85 KPartitioningSystem::FreeCookie(KPartition *partition) 86 { 87 if (!partition || !fModule || !fModule->free_partition_cookie 88 || partition->ParentDiskSystem() != this) { 89 return; 90 } 91 fModule->free_partition_cookie(partition->PartitionData()); 92 partition->SetCookie(NULL); 93 } 94 95 // FreeContentCookie 96 void 97 KPartitioningSystem::FreeContentCookie(KPartition *partition) 98 { 99 if (!partition || !fModule || !fModule->free_partition_content_cookie 100 || partition->DiskSystem() != this) { 101 return; 102 } 103 fModule->free_partition_content_cookie(partition->PartitionData()); 104 partition->SetContentCookie(NULL); 105 } 106 107 // SupportsRepairing 108 bool 109 KPartitioningSystem::SupportsRepairing(KPartition *partition, bool checkOnly, 110 bool *whileMounted) 111 { 112 bool _whileMounted = false; 113 if (!whileMounted) 114 whileMounted = &_whileMounted; 115 if (!partition || partition->DiskSystem() != this || !fModule 116 || !fModule->supports_repairing) { 117 return (*whileMounted = false); 118 } 119 bool result = fModule->supports_repairing(partition->PartitionData(), 120 checkOnly); 121 *whileMounted = result; 122 return result; 123 } 124 125 // SupportsResizing 126 bool 127 KPartitioningSystem::SupportsResizing(KPartition *partition, 128 bool *whileMounted) 129 { 130 bool _whileMounted = false; 131 if (!whileMounted) 132 whileMounted = &_whileMounted; 133 if (!partition || partition->DiskSystem() != this || !fModule || 134 !fModule->supports_resizing) { 135 return (*whileMounted = false); 136 } 137 bool result = fModule->supports_resizing(partition->PartitionData()); 138 *whileMounted = result; 139 return result; 140 } 141 142 // SupportsResizingChild 143 bool 144 KPartitioningSystem::SupportsResizingChild(KPartition *child) 145 { 146 return (child && child->Parent() && child->ParentDiskSystem() == this 147 && fModule && fModule->supports_resizing_child 148 && fModule->supports_resizing_child( 149 child->Parent()->PartitionData(), 150 child->PartitionData())); 151 } 152 153 // SupportsMoving 154 bool 155 KPartitioningSystem::SupportsMoving(KPartition *partition, bool *isNoOp) 156 { 157 bool _isNoOp = false; 158 if (!isNoOp) 159 isNoOp = &_isNoOp; 160 if (!partition || partition->DiskSystem() != this || !fModule 161 || !fModule->supports_moving) { 162 return (*isNoOp = false); 163 } 164 return fModule->supports_moving(partition->PartitionData(), isNoOp); 165 } 166 167 // SupportsMovingChild 168 bool 169 KPartitioningSystem::SupportsMovingChild(KPartition *child) 170 { 171 return (child && child->Parent() && child->ParentDiskSystem() != this 172 && fModule && fModule->supports_moving_child 173 && fModule->supports_moving_child(child->Parent()->PartitionData(), 174 child->PartitionData())); 175 } 176 177 // SupportsSettingName 178 bool 179 KPartitioningSystem::SupportsSettingName(KPartition *partition) 180 { 181 return (partition && partition->ParentDiskSystem() == this 182 && fModule && fModule->supports_setting_name 183 && fModule->supports_setting_name(partition->PartitionData())); 184 } 185 186 // SupportsSettingContentName 187 bool 188 KPartitioningSystem::SupportsSettingContentName(KPartition *partition, 189 bool *whileMounted) 190 { 191 bool _whileMounted = false; 192 if (!whileMounted) 193 whileMounted = &_whileMounted; 194 if (!partition || partition->DiskSystem() != this || !fModule 195 || !fModule->supports_setting_content_name) { 196 return (*whileMounted = false); 197 } 198 bool result = fModule->supports_setting_content_name( 199 partition->PartitionData()); 200 *whileMounted = result; 201 return result; 202 } 203 204 // SupportsSettingType 205 bool 206 KPartitioningSystem::SupportsSettingType(KPartition *partition) 207 { 208 return (partition && partition->ParentDiskSystem() == this 209 && fModule && fModule->supports_setting_type 210 && fModule->supports_setting_type(partition->PartitionData())); 211 } 212 213 // SupportsSettingParameters 214 bool 215 KPartitioningSystem::SupportsSettingParameters(KPartition *partition) 216 { 217 return (partition && partition->ParentDiskSystem() == this 218 && fModule && fModule->supports_setting_parameters 219 && fModule->supports_setting_parameters( 220 partition->PartitionData())); 221 } 222 223 // SupportsSettingContentParameters 224 bool 225 KPartitioningSystem::SupportsSettingContentParameters(KPartition *partition, 226 bool *whileMounted) 227 { 228 bool _whileMounted = false; 229 if (!whileMounted) 230 whileMounted = &_whileMounted; 231 if (!partition || partition->DiskSystem() != this || !fModule 232 || !fModule->supports_setting_content_parameters) { 233 return (*whileMounted = false); 234 } 235 bool result = fModule->supports_setting_content_parameters( 236 partition->PartitionData()); 237 *whileMounted = result; 238 return result; 239 } 240 241 // SupportsInitializing 242 bool 243 KPartitioningSystem::SupportsInitializing(KPartition *partition) 244 { 245 return (partition && fModule && fModule->supports_initializing 246 && fModule->supports_initializing(partition->PartitionData())); 247 } 248 249 // SupportsInitializingChild 250 bool 251 KPartitioningSystem::SupportsInitializingChild(KPartition *child, 252 const char *diskSystem) 253 { 254 return (child && child->ParentDiskSystem() == this && diskSystem 255 && fModule && fModule->supports_initializing_child 256 && fModule->supports_initializing_child(child->PartitionData(), 257 diskSystem)); 258 } 259 260 // SupportsCreatingChild 261 bool 262 KPartitioningSystem::SupportsCreatingChild(KPartition *partition) 263 { 264 return (partition && partition->DiskSystem() == this 265 && fModule && fModule->supports_creating_child 266 && fModule->supports_creating_child(partition->PartitionData())); 267 } 268 269 // SupportsDeletingChild 270 bool 271 KPartitioningSystem::SupportsDeletingChild(KPartition *child) 272 { 273 return (child && child->Parent() && child->ParentDiskSystem() == this 274 && fModule && fModule->supports_deleting_child 275 && fModule->supports_deleting_child( 276 child->Parent()->PartitionData(), child->PartitionData())); 277 } 278 279 // IsSubSystemFor 280 bool 281 KPartitioningSystem::IsSubSystemFor(KPartition *partition) 282 { 283 return (partition && fModule && fModule->is_sub_system_for 284 && fModule->is_sub_system_for(partition->PartitionData())); 285 } 286 287 // ValidateResize 288 bool 289 KPartitioningSystem::ValidateResize(KPartition *partition, off_t *size) 290 { 291 return (partition && size && partition->DiskSystem() == this && fModule 292 && fModule->validate_resize 293 && fModule->validate_resize(partition->PartitionData(), size)); 294 } 295 296 // ValidateResizeChild 297 bool 298 KPartitioningSystem::ValidateResizeChild(KPartition *child, off_t *size) 299 { 300 return (child && size && child->Parent() 301 && child->ParentDiskSystem() == this && fModule 302 && fModule->validate_resize_child 303 && fModule->validate_resize_child(child->Parent()->PartitionData(), 304 child->PartitionData(), size)); 305 } 306 307 // ValidateMove 308 bool 309 KPartitioningSystem::ValidateMove(KPartition *partition, off_t *start) 310 { 311 return (partition && start && partition->DiskSystem() == this && fModule 312 && fModule->validate_move 313 && fModule->validate_move(partition->PartitionData(), start)); 314 } 315 316 // ValidateMoveChild 317 bool 318 KPartitioningSystem::ValidateMoveChild(KPartition *child, off_t *start) 319 { 320 return (child && start && child->Parent() 321 && child->ParentDiskSystem() == this && fModule 322 && fModule->validate_move_child 323 && fModule->validate_move_child(child->Parent()->PartitionData(), 324 child->PartitionData(), start)); 325 } 326 327 // ValidateSetName 328 bool 329 KPartitioningSystem::ValidateSetName(KPartition *partition, char *name) 330 { 331 return (partition && name && partition->Parent() 332 && partition->ParentDiskSystem() == this && fModule 333 && fModule->validate_set_name 334 && fModule->validate_set_name(partition->PartitionData(), name)); 335 } 336 337 // ValidateSetContentName 338 bool 339 KPartitioningSystem::ValidateSetContentName(KPartition *partition, char *name) 340 { 341 return (partition && name && partition->DiskSystem() == this 342 && fModule && fModule->validate_set_content_name 343 && fModule->validate_set_content_name(partition->PartitionData(), 344 name)); 345 } 346 347 // ValidateSetType 348 bool 349 KPartitioningSystem::ValidateSetType(KPartition *partition, const char *type) 350 { 351 return (partition && type && partition->ParentDiskSystem() == this 352 && fModule && fModule->validate_set_type 353 && fModule->validate_set_type(partition->PartitionData(), type)); 354 } 355 356 // ValidateSetParameters 357 bool 358 KPartitioningSystem::ValidateSetParameters(KPartition *partition, 359 const char *parameters) 360 { 361 return (partition && partition->ParentDiskSystem() == this 362 && fModule && fModule->validate_set_parameters 363 && fModule->validate_set_parameters(partition->PartitionData(), 364 parameters)); 365 } 366 367 // ValidateSetContentParameters 368 bool 369 KPartitioningSystem::ValidateSetContentParameters(KPartition *partition, 370 const char *parameters) 371 { 372 return (partition && partition->DiskSystem() == this && fModule 373 && fModule->validate_set_content_parameters 374 && fModule->validate_set_content_parameters( 375 partition->PartitionData(), parameters)); 376 } 377 378 // ValidateInitialize 379 bool 380 KPartitioningSystem::ValidateInitialize(KPartition *partition, char *name, 381 const char *parameters) 382 { 383 return (partition && name && fModule && fModule->validate_initialize 384 && fModule->validate_initialize(partition->PartitionData(), name, 385 parameters)); 386 } 387 388 // ValidateCreateChild 389 bool 390 KPartitioningSystem::ValidateCreateChild(KPartition *partition, off_t *start, 391 off_t *size, const char *type, 392 const char *parameters, int32 *index) 393 { 394 int32 _index = 0; 395 if (!index) 396 index = &_index; 397 return (partition && start && size && type 398 && partition->DiskSystem() == this && fModule 399 && fModule->validate_create_child 400 && fModule->validate_create_child(partition->PartitionData(), 401 start, size, type, parameters, 402 index)); 403 } 404 405 // CountPartitionableSpaces 406 int32 407 KPartitioningSystem::CountPartitionableSpaces(KPartition *partition) 408 { 409 if (!partition || partition->DiskSystem() != this || !fModule) 410 return 0; 411 if (!fModule->get_partitionable_spaces) { 412 // TODO: Fallback algorithm. 413 return 0; 414 } 415 int32 count = 0; 416 status_t error = fModule->get_partitionable_spaces( 417 partition->PartitionData(), NULL, 0, &count); 418 return (error == B_OK || error == B_BUFFER_OVERFLOW ? count : 0); 419 } 420 421 // GetPartitionableSpaces 422 status_t 423 KPartitioningSystem::GetPartitionableSpaces(KPartition *partition, 424 partitionable_space_data *buffer, 425 int32 count, int32 *actualCount) 426 { 427 if (!partition || partition->DiskSystem() != this || count > 0 && !buffer 428 || !actualCount || !fModule) { 429 return B_BAD_VALUE; 430 } 431 if (!fModule->get_partitionable_spaces) { 432 // TODO: Fallback algorithm. 433 return B_ENTRY_NOT_FOUND; 434 } 435 return fModule->get_partitionable_spaces(partition->PartitionData(), 436 buffer, count, actualCount); 437 } 438 439 // GetNextSupportedType 440 status_t 441 KPartitioningSystem::GetNextSupportedType(KPartition *partition, int32 *cookie, 442 char *type) 443 { 444 if (!partition || partition->DiskSystem() != this || !cookie || !type 445 || !fModule) { 446 return B_BAD_VALUE; 447 } 448 if (!fModule->get_next_supported_type) 449 return B_ENTRY_NOT_FOUND; 450 return fModule->get_next_supported_type(partition->PartitionData(), cookie, 451 type); 452 } 453 454 // GetTypeForContentType 455 status_t 456 KPartitioningSystem::GetTypeForContentType(const char *contentType, char *type) 457 { 458 if (!contentType || !type || !fModule) 459 return B_BAD_VALUE; 460 if (!fModule->get_type_for_content_type) 461 return B_ENTRY_NOT_FOUND; 462 return fModule->get_type_for_content_type(contentType, type); 463 } 464 465 // ShadowPartitionChanged 466 status_t 467 KPartitioningSystem::ShadowPartitionChanged(KPartition *partition, 468 uint32 operation) 469 { 470 if (!partition) 471 return B_BAD_VALUE; 472 if (!fModule) 473 return B_ERROR; 474 // If not implemented, we assume, that the partitioning system doesn't 475 // have to make any additional changes. 476 if (!fModule->shadow_changed) 477 return B_OK; 478 return fModule->shadow_changed(partition->PartitionData(), operation); 479 } 480 481 // Repair 482 status_t 483 KPartitioningSystem::Repair(KPartition *partition, bool checkOnly, 484 KDiskDeviceJob *job) 485 { 486 // to be implemented 487 return B_ERROR; 488 } 489 490 // Resize 491 status_t 492 KPartitioningSystem::Resize(KPartition *partition, off_t size, 493 KDiskDeviceJob *job) 494 { 495 // check parameters 496 if (!partition || !job || size < 0) 497 return B_BAD_VALUE; 498 if (!fModule->resize) 499 return B_ENTRY_NOT_FOUND; 500 // lock partition and open partition device 501 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 502 KPartition *_partition = manager->ReadLockPartition(partition->ID()); 503 if (!_partition) 504 return B_ERROR; 505 int fd = -1; 506 { 507 PartitionRegistrar registrar(_partition, true); 508 PartitionRegistrar deviceRegistrar(_partition->Device(), true); 509 DeviceReadLocker locker(_partition->Device(), true); 510 if (partition != _partition) 511 return B_ERROR; 512 status_t result = partition->Open(O_RDONLY, &fd); 513 if (result != B_OK) 514 return result; 515 } 516 // let the module do its job 517 status_t result = fModule->resize(fd, partition->ID(), size, job->ID()); 518 // cleanup and return 519 close(fd); 520 return result; 521 } 522 523 // ResizeChild 524 status_t 525 KPartitioningSystem::ResizeChild(KPartition *child, off_t size, 526 KDiskDeviceJob *job) 527 { 528 // check parameters 529 if (!child || !job || size < 0) 530 return B_BAD_VALUE; 531 if (!fModule->resize_child) 532 return B_ENTRY_NOT_FOUND; 533 // lock partition and open (parent) partition device 534 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 535 KPartition *_partition = manager->ReadLockPartition(child->ID()); 536 if (!_partition) 537 return B_ERROR; 538 int fd = -1; 539 { 540 PartitionRegistrar registrar(_partition, true); 541 PartitionRegistrar deviceRegistrar(_partition->Device(), true); 542 DeviceReadLocker locker(_partition->Device(), true); 543 if (child != _partition) 544 return B_ERROR; 545 if (!child->Parent()) 546 return B_BAD_VALUE; 547 status_t result = child->Parent()->Open(O_RDONLY, &fd); 548 if (result != B_OK) 549 return result; 550 } 551 // let the module do its job 552 status_t result = fModule->resize_child(fd, child->ID(), size, job->ID()); 553 // cleanup and return 554 close(fd); 555 return result; 556 } 557 558 // Move 559 status_t 560 KPartitioningSystem::Move(KPartition *partition, off_t offset, 561 KDiskDeviceJob *job) 562 { 563 // to be implemented 564 return B_ERROR; 565 } 566 567 // MoveChild 568 status_t 569 KPartitioningSystem::MoveChild(KPartition *child, off_t offset, 570 KDiskDeviceJob *job) 571 { 572 // to be implemented 573 return B_ERROR; 574 } 575 576 // SetName 577 status_t 578 KPartitioningSystem::SetName(KPartition *partition, char *name, 579 KDiskDeviceJob *job) 580 { 581 // to be implemented 582 return B_ERROR; 583 } 584 585 // SetContentName 586 status_t 587 KPartitioningSystem::SetContentName(KPartition *partition, char *name, 588 KDiskDeviceJob *job) 589 { 590 // to be implemented 591 return B_ERROR; 592 } 593 594 // SetType 595 status_t 596 KPartitioningSystem::SetType(KPartition *partition, char *type, 597 KDiskDeviceJob *job) 598 { 599 // to be implemented 600 return B_ERROR; 601 } 602 603 // SetParameters 604 status_t 605 KPartitioningSystem::SetParameters(KPartition *partition, 606 const char *parameters, KDiskDeviceJob *job) 607 { 608 // to be implemented 609 return B_ERROR; 610 } 611 612 // SetContentParameters 613 status_t 614 KPartitioningSystem::SetContentParameters(KPartition *partition, 615 const char *parameters, 616 KDiskDeviceJob *job) 617 { 618 // to be implemented 619 return B_ERROR; 620 } 621 622 // Initialize 623 status_t 624 KPartitioningSystem::Initialize(KPartition *partition, const char *name, 625 const char *parameters, KDiskDeviceJob *job) 626 { 627 // to be implemented 628 return B_ERROR; 629 } 630 631 // CreateChild 632 status_t 633 KPartitioningSystem::CreateChild(KPartition *partition, off_t offset, 634 off_t size, const char *type, 635 const char *parameters, KDiskDeviceJob *job, 636 KPartition **child, partition_id childID) 637 { 638 // to be implemented 639 return B_ERROR; 640 } 641 642 // DeleteChild 643 status_t 644 KPartitioningSystem::DeleteChild(KPartition *child, KDiskDeviceJob *job) 645 { 646 // to be implemented 647 return B_ERROR; 648 } 649 650 // LoadModule 651 status_t 652 KPartitioningSystem::LoadModule() 653 { 654 if (fModule) // shouldn't happen 655 return B_OK; 656 return get_module(Name(), (module_info**)&fModule); 657 } 658 659 // UnloadModule 660 void 661 KPartitioningSystem::UnloadModule() 662 { 663 if (fModule) { 664 put_module(fModule->module.name); 665 fModule = NULL; 666 } 667 } 668 669