1 /** \file ddm_userland_interface.cpp 2 * 3 * \brief Interface for userspace calls. 4 */ 5 6 #include <stdlib.h> 7 8 #include <AutoDeleter.h> 9 #include <ddm_userland_interface.h> 10 #include <KDiskDevice.h> 11 #include <KDiskDeviceJob.h> 12 #include <KDiskDeviceJobQueue.h> 13 #include <KDiskDeviceManager.h> 14 #include <KDiskDeviceUtils.h> 15 #include <KDiskSystem.h> 16 #include <KFileDiskDevice.h> 17 #include <KShadowPartition.h> 18 #include <syscall_args.h> 19 20 #include "ddm_operation_validation.h" 21 #include "KDiskDeviceJobGenerator.h" 22 #include "UserDataWriter.h" 23 24 using namespace BPrivate::DiskDevice; 25 26 // debugging 27 #define ERROR(x) 28 29 // ddm_strlcpy 30 /*! \brief Wrapper around user_strlcpy() that returns a status_t 31 indicating appropriate success or failure. 32 33 \param allowTruncation If \c true, does not return an error if 34 \a from is longer than \to. If \c false, returns \c B_NAME_TOO_LONG 35 if \a from is longer than \to. 36 */ 37 static 38 status_t 39 ddm_strlcpy(char *to, const char *from, size_t size, bool allowTruncation = false) { 40 int error = user_strlcpy(to, from, size); 41 error = (0 <= error && size_t(error) < size) ? B_OK 42 : (error < B_OK ? error : (allowTruncation ? B_OK : B_NAME_TOO_LONG)); 43 return status_t(error); 44 } 45 46 // move_descendants 47 static 48 void 49 move_descendants(KPartition *partition, off_t moveBy) 50 { 51 if (!partition) 52 return; 53 partition->SetOffset(partition->Offset() + moveBy); 54 // move children 55 for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) 56 move_descendants(child, moveBy); 57 } 58 59 // move_descendants_contents 60 static 61 status_t 62 move_descendants_contents(KPartition *partition) 63 { 64 if (!partition) 65 return B_BAD_VALUE; 66 // implicit content disk system changes 67 KDiskSystem *diskSystem = partition->DiskSystem(); 68 if (diskSystem || partition->AlgorithmData()) { 69 status_t error = diskSystem->ShadowPartitionChanged(partition, 70 B_PARTITION_RESIZE); 71 if (error != B_OK) 72 return error; 73 } 74 // move children's contents 75 for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) { 76 status_t error = move_descendants_contents(child); 77 if (error != B_OK) 78 return error; 79 } 80 return B_OK; 81 } 82 83 // _user_get_next_disk_device_id 84 partition_id 85 _user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize) 86 { 87 if (!_cookie) 88 return B_BAD_VALUE; 89 int32 cookie; 90 user_memcpy(&cookie, _cookie, sizeof(cookie)); 91 92 partition_id id = B_ENTRY_NOT_FOUND; 93 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 94 // get the next device 95 if (KDiskDevice *device = manager->RegisterNextDevice(&cookie)) { 96 PartitionRegistrar _(device, true); 97 id = device->ID(); 98 if (neededSize) { 99 if (DeviceReadLocker locker = device) { 100 // get the needed size 101 UserDataWriter writer; 102 device->WriteUserData(writer, false); 103 *neededSize = writer.AllocatedSize(); 104 } else { 105 id = B_ERROR; 106 } 107 } 108 } 109 user_memcpy(_cookie, &cookie, sizeof(cookie)); 110 return id; 111 } 112 113 // _user_find_disk_device 114 partition_id 115 _user_find_disk_device(const char *_filename, size_t *neededSize) 116 { 117 if (!_filename) 118 return B_BAD_VALUE; 119 120 char filename[B_PATH_NAME_LENGTH]; 121 status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH); 122 if (error) 123 return error; 124 125 partition_id id = B_ENTRY_NOT_FOUND; 126 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 127 // find the device 128 if (KDiskDevice *device = manager->RegisterDevice(filename)) { 129 PartitionRegistrar _(device, true); 130 id = device->ID(); 131 if (neededSize) { 132 if (DeviceReadLocker locker = device) { 133 // get the needed size 134 UserDataWriter writer; 135 device->WriteUserData(writer, false); 136 *neededSize = writer.AllocatedSize(); 137 } else 138 return B_ERROR; 139 } 140 } 141 return id; 142 } 143 144 // _user_find_partition 145 partition_id 146 _user_find_partition(const char *_filename, size_t *neededSize) 147 { 148 if (!_filename) 149 return B_BAD_VALUE; 150 151 char filename[B_PATH_NAME_LENGTH]; 152 status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH); 153 if (error) 154 return error; 155 156 partition_id id = B_ENTRY_NOT_FOUND; 157 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 158 // find the partition 159 if (KPartition *partition = manager->RegisterPartition(filename)) { 160 PartitionRegistrar _(partition, true); 161 id = partition->ID(); 162 if (neededSize) { 163 // get and lock the partition's device 164 KDiskDevice *device = manager->RegisterDevice(partition->ID()); 165 if (!device) 166 return B_ENTRY_NOT_FOUND; 167 PartitionRegistrar _2(device, true); 168 if (DeviceReadLocker locker = device) { 169 // get the needed size 170 UserDataWriter writer; 171 device->WriteUserData(writer, false); 172 *neededSize = writer.AllocatedSize(); 173 } else 174 return B_ERROR; 175 } 176 } 177 return id; 178 } 179 180 // _user_get_disk_device_data 181 /*! \brief Writes data describing the disk device identified by ID and all 182 its partitions into the supplied buffer. 183 184 The function passes the buffer size required to hold the data back 185 through the \a _neededSize parameter, if the device could be found at 186 least and no serious error occured. If fails with \c B_BUFFER_OVERFLOW, 187 if the supplied buffer is too small or a \c NULL buffer is supplied 188 (and \c bufferSize is 0). 189 190 The device is identified by \a id. If \a deviceOnly is \c true, then 191 it must be the ID of a disk device, otherwise the disk device is 192 chosen, on which the partition \a id refers to resides. 193 194 \param id The ID of an arbitrary partition on the disk device (including 195 the disk device itself), whose data shall be returned 196 (if \a deviceOnly is \c false), or the ID of the disk device 197 itself (if \a deviceOnly is true). 198 \param deviceOnly Specifies whether only IDs of disk devices (\c true), 199 or also IDs of partitions (\c false) are accepted for \a id. 200 \param shadow If \c true, the data of the shadow disk device is returned, 201 otherwise of the physical device. If there is no shadow device, 202 the parameter is ignored. 203 \param buffer The buffer into which the disk device data shall be written. 204 May be \c NULL. 205 \param bufferSize The size of \a buffer. 206 \param _neededSize Pointer to a variable into which the actually needed 207 buffer size is written. May be \c NULL. 208 \return 209 - \c B_OK: Everything went fine. The device was found and, if not \c NULL, 210 in \a _neededSize the actually needed buffer size is returned. And 211 \a buffer will contain the disk device data. 212 - \c B_BAD_VALUE: \c NULL \a buffer, but not 0 \a bufferSize. 213 - \c B_BUFFER_OVERFLOW: The supplied buffer was too small. \a _neededSize, 214 if not \c NULL, will contain the required buffer size. 215 - \c B_NO_MEMORY: Insufficient memory to complete the operation. 216 - \c B_ENTRY_NOT_FOUND: \a id is no valid disk device ID (if \a deviceOnly 217 is \c true) or not even a valid partition ID (if \a deviceOnly is 218 \c false). 219 - \c B_ERROR: An unexpected error occured. 220 - another error code... 221 */ 222 status_t 223 _user_get_disk_device_data(partition_id id, bool deviceOnly, bool shadow, 224 user_disk_device_data *buffer, size_t bufferSize, 225 size_t *_neededSize) 226 { 227 if (!buffer && bufferSize > 0) 228 return B_BAD_VALUE; 229 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 230 // get the device 231 if (KDiskDevice *device = manager->RegisterDevice(id, deviceOnly)) { 232 PartitionRegistrar _(device, true); 233 if (DeviceReadLocker locker = device) { 234 // do a dry run first to get the needed size 235 UserDataWriter writer; 236 device->WriteUserData(writer, shadow); 237 size_t neededSize = writer.AllocatedSize(); 238 if (_neededSize) { 239 status_t error = copy_ref_var_to_user(neededSize, _neededSize); 240 if (error != B_OK) 241 return error; 242 } 243 // if no buffer has been supplied or the buffer is too small, 244 // then we're done 245 if (!buffer || bufferSize < neededSize) 246 return B_BUFFER_OVERFLOW; 247 // otherwise allocate a kernel buffer 248 user_disk_device_data *kernelBuffer 249 = static_cast<user_disk_device_data*>(malloc(neededSize)); 250 if (!kernelBuffer) 251 return B_NO_MEMORY; 252 MemoryDeleter deleter(kernelBuffer); 253 // write the device data into the buffer 254 writer.SetTo(kernelBuffer, bufferSize); 255 device->WriteUserData(writer, shadow); 256 // sanity check 257 if (writer.AllocatedSize() != neededSize) { 258 ERROR(("Size of written disk device user data changed from " 259 "%lu to %lu while device was locked!\n")); 260 return B_ERROR; 261 } 262 // relocate 263 status_t error = writer.Relocate(buffer); 264 if (error != B_OK) 265 return error; 266 // copy out 267 if (buffer) 268 return user_memcpy(buffer, kernelBuffer, neededSize); 269 } else 270 return B_ERROR; 271 } 272 return B_ENTRY_NOT_FOUND; 273 } 274 275 // _user_get_partitionable_spaces 276 status_t 277 _user_get_partitionable_spaces(partition_id partitionID, int32 changeCounter, 278 partitionable_space_data *_buffer, 279 int32 count, int32 *_actualCount) 280 { 281 if (!_buffer && count > 0) 282 return B_BAD_VALUE; 283 // copy in 284 int32 bufferSize = count * sizeof(partitionable_space_data); 285 partitionable_space_data *buffer = count > 0 286 ? reinterpret_cast<partitionable_space_data*>(malloc(bufferSize)) 287 : NULL; 288 if (buffer) 289 user_memcpy(buffer, _buffer, bufferSize); 290 status_t error = B_OK; 291 // get the partition 292 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 293 KPartition *partition = manager->ReadLockPartition(partitionID); 294 error = partition ? B_OK : B_ENTRY_NOT_FOUND; 295 if (!error) { 296 PartitionRegistrar registrar1(partition, true); 297 PartitionRegistrar registrar2(partition->Device(), true); 298 DeviceReadLocker locker(partition->Device(), true); 299 error = check_shadow_partition(partition, changeCounter) ? B_OK : B_BAD_VALUE; 300 if (!error) { 301 // get the disk system 302 KDiskSystem *diskSystem = partition->DiskSystem(); 303 error = diskSystem ? B_OK : B_ENTRY_NOT_FOUND; 304 if (!error) { 305 // get the info 306 int32 actualCount; 307 error = diskSystem->GetPartitionableSpaces(partition, buffer, 308 count, &actualCount); 309 if (!error && _actualCount) 310 user_memcpy(_actualCount, &actualCount, sizeof(actualCount)); 311 } 312 } 313 } 314 // copy out 315 if (!error && buffer) 316 user_memcpy(_buffer, buffer, bufferSize); 317 free(buffer); 318 return error; 319 } 320 321 // _user_register_file_device 322 partition_id 323 _user_register_file_device(const char *_filename) 324 { 325 if (!_filename) 326 return B_BAD_VALUE; 327 char filename[B_PATH_NAME_LENGTH]; 328 status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH); 329 if (error) 330 return error; 331 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 332 if (ManagerLocker locker = manager) { 333 if (KFileDiskDevice *device = manager->FindFileDevice(filename)) 334 return device->ID(); 335 return manager->CreateFileDevice(filename); 336 } 337 return B_ERROR; 338 } 339 340 // _user_unregister_file_device 341 status_t 342 _user_unregister_file_device(partition_id deviceID, const char *_filename) 343 { 344 if (deviceID < 0 && !_filename) 345 return B_BAD_VALUE; 346 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 347 if (deviceID >= 0) { 348 return manager->DeleteFileDevice(deviceID); 349 } else { 350 char filename[B_PATH_NAME_LENGTH]; 351 status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH); 352 if (error) 353 return error; 354 return manager->DeleteFileDevice(filename); 355 } 356 } 357 358 // _user_get_disk_system_info 359 status_t 360 _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info) 361 { 362 if (!_info) 363 return B_BAD_VALUE; 364 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 365 if (ManagerLocker locker = manager) { 366 if (KDiskSystem *diskSystem = manager->FindDiskSystem(id)) { 367 DiskSystemLoader _(diskSystem, true); 368 user_disk_system_info info; 369 diskSystem->GetInfo(&info); 370 user_memcpy(_info, &info, sizeof(info)); 371 return B_OK; 372 } 373 } 374 return B_ENTRY_NOT_FOUND; 375 } 376 377 // _user_get_next_disk_system_info 378 status_t 379 _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info) 380 { 381 if (!_cookie || !_info) 382 return B_BAD_VALUE; 383 int32 cookie; 384 user_memcpy(&cookie, _cookie, sizeof(cookie)); 385 status_t result = B_ENTRY_NOT_FOUND; 386 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 387 if (ManagerLocker locker = manager) { 388 if (KDiskSystem *diskSystem = manager->NextDiskSystem(&cookie)) { 389 DiskSystemLoader _(diskSystem, true); 390 user_disk_system_info info; 391 diskSystem->GetInfo(&info); 392 user_memcpy(_info, &info, sizeof(info)); 393 result = B_OK; 394 } 395 } 396 user_memcpy(_cookie, &cookie, sizeof(cookie)); 397 return result; 398 } 399 400 // _user_find_disk_system 401 status_t 402 _user_find_disk_system(const char *_name, user_disk_system_info *_info) 403 { 404 if (!_name || !_info) 405 return B_BAD_VALUE; 406 char name[B_DISK_SYSTEM_NAME_LENGTH]; 407 status_t error = ddm_strlcpy(name, _name, B_DISK_SYSTEM_NAME_LENGTH); 408 if (error) 409 return error; 410 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 411 if (ManagerLocker locker = manager) { 412 if (KDiskSystem *diskSystem = manager->FindDiskSystem(name)) { 413 DiskSystemLoader _(diskSystem, true); 414 user_disk_system_info info; 415 diskSystem->GetInfo(&info); 416 user_memcpy(_info, &info, sizeof(info)); 417 return B_OK; 418 } 419 } 420 return B_ENTRY_NOT_FOUND; 421 } 422 423 // _user_supports_defragmenting_partition 424 bool 425 _user_supports_defragmenting_partition(partition_id partitionID, 426 int32 changeCounter, bool *_whileMounted) 427 { 428 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 429 // get the partition 430 KPartition *partition = manager->ReadLockPartition(partitionID); 431 if (!partition) 432 return false; 433 PartitionRegistrar registrar1(partition, true); 434 PartitionRegistrar registrar2(partition->Device(), true); 435 DeviceReadLocker locker(partition->Device(), true); 436 bool whileMounted; 437 bool result = validate_defragment_partition(partition, changeCounter, 438 &whileMounted) == B_OK; 439 if (result && _whileMounted) 440 user_memcpy(_whileMounted, &whileMounted, sizeof(whileMounted)); 441 return result; 442 } 443 444 // _user_supports_repairing_partition 445 bool 446 _user_supports_repairing_partition(partition_id partitionID, 447 int32 changeCounter, bool checkOnly, 448 bool *_whileMounted) 449 { 450 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 451 // get the partition 452 KPartition *partition = manager->ReadLockPartition(partitionID); 453 if (!partition) 454 return false; 455 PartitionRegistrar registrar1(partition, true); 456 PartitionRegistrar registrar2(partition->Device(), true); 457 DeviceReadLocker locker(partition->Device(), true); 458 bool whileMounted; 459 bool result = validate_repair_partition(partition, changeCounter, checkOnly, 460 &whileMounted) == B_OK; 461 if (result && _whileMounted) 462 user_memcpy(_whileMounted, &whileMounted, sizeof(whileMounted)); 463 return result; 464 } 465 466 // _user_supports_resizing_partition 467 bool 468 _user_supports_resizing_partition(partition_id partitionID, 469 int32 changeCounter, bool *_canResizeContents, 470 bool *_whileMounted) 471 { 472 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 473 474 // get the partition 475 KPartition *partition = manager->ReadLockPartition(partitionID); 476 if (!partition) 477 return false; 478 PartitionRegistrar registrar1(partition, true); 479 PartitionRegistrar registrar2(partition->Device(), true); 480 DeviceReadLocker locker(partition->Device(), true); 481 if (!check_shadow_partition(partition, changeCounter) 482 || !partition->Parent()) { 483 return false; 484 } 485 if (partition->Parent()->IsBusy() 486 || partition->Parent()->IsDescendantBusy()) { 487 return false; 488 } 489 490 // get the parent disk system 491 KDiskSystem *parentDiskSystem = partition->Parent()->DiskSystem(); 492 if (!parentDiskSystem) 493 return false; 494 bool result = parentDiskSystem->SupportsChildOperations(partition, 495 B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD); 496 if (!result) 497 return false; 498 499 // get the child disk system 500 KDiskSystem *childDiskSystem = partition->DiskSystem(); 501 if (_canResizeContents) { 502 bool canResizeContents = false; 503 bool whileMounted = false; 504 if (childDiskSystem) { 505 uint32 operations = childDiskSystem->GetSupportedOperations( 506 partition, B_DISK_SYSTEM_SUPPORTS_RESIZING 507 | B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED); 508 509 if (operations & B_DISK_SYSTEM_SUPPORTS_RESIZING) { 510 canResizeContents = true; 511 if (operations & B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED) 512 whileMounted = true; 513 } 514 } 515 516 user_memcpy(_canResizeContents, &canResizeContents, sizeof(canResizeContents)); 517 if (_whileMounted) 518 user_memcpy(_whileMounted, &whileMounted, sizeof(whileMounted)); 519 } 520 // TODO: Currently we report that we cannot resize the contents, if the 521 // partition's disk system is unknown. I found this more logical. It doesn't 522 // really matter, though, since the API user can check for this situation. 523 return result; 524 } 525 526 // _user_supports_moving_partition 527 bool 528 _user_supports_moving_partition(partition_id partitionID, int32 changeCounter, 529 partition_id *_unmovable, 530 partition_id *_needUnmounting, 531 size_t bufferSize) 532 { 533 if ((!_unmovable || !_needUnmounting) && bufferSize > 0) 534 return false; 535 partition_id *unmovable = NULL; 536 partition_id *needUnmounting = NULL; 537 if (bufferSize > 0) { 538 unmovable = static_cast<partition_id*>(malloc(bufferSize)); 539 needUnmounting = static_cast<partition_id*>(malloc(bufferSize)); 540 if (unmovable && needUnmounting) { 541 user_memcpy(unmovable, _unmovable, bufferSize); 542 user_memcpy(needUnmounting, _needUnmounting, bufferSize); 543 } else { 544 free(unmovable); 545 free(needUnmounting); 546 return false; 547 } 548 } 549 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 550 // get the partition 551 KPartition *partition = manager->ReadLockPartition(partitionID); 552 bool result = partition; 553 if (result) { 554 PartitionRegistrar registrar1(partition, true); 555 PartitionRegistrar registrar2(partition->Device(), true); 556 DeviceReadLocker locker(partition->Device(), true); 557 result = check_shadow_partition(partition, changeCounter) 558 && partition->Parent(); 559 if (result) { 560 result = !partition->Parent()->IsBusy() 561 && !partition->Parent()->IsDescendantBusy(); 562 } 563 if (result) { 564 // get the parent disk system 565 KDiskSystem *parentDiskSystem = partition->Parent()->DiskSystem(); 566 result = parentDiskSystem; 567 if (result) { 568 result = parentDiskSystem->SupportsChildOperations(partition, 569 B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD); 570 } 571 572 if (result) { 573 // check the movability of the descendants' contents 574 size_t unmovableSize = bufferSize; 575 size_t needUnmountingSize = bufferSize; 576 result = get_unmovable_descendants(partition, unmovable, 577 unmovableSize, needUnmounting, 578 needUnmountingSize); 579 } 580 } 581 } 582 if (result && bufferSize > 0) { 583 user_memcpy(_unmovable, unmovable, bufferSize); 584 user_memcpy(_needUnmounting, needUnmounting, bufferSize); 585 } 586 free(unmovable); 587 free(needUnmounting); 588 return result; 589 } 590 591 // _user_supports_setting_partition_name 592 bool 593 _user_supports_setting_partition_name(partition_id partitionID, 594 int32 changeCounter) 595 { 596 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 597 // get the partition 598 KPartition *partition = manager->ReadLockPartition(partitionID); 599 if (!partition) 600 return false; 601 PartitionRegistrar registrar1(partition, true); 602 PartitionRegistrar registrar2(partition->Device(), true); 603 DeviceReadLocker locker(partition->Device(), true); 604 if (!check_shadow_partition(partition, changeCounter) 605 || !partition->Parent()) { 606 return false; 607 } 608 if (partition->Parent()->IsBusy() 609 || partition->Parent()->IsDescendantBusy()) { 610 return false; 611 } 612 613 // get the disk system 614 KDiskSystem *diskSystem = partition->Parent()->DiskSystem(); 615 if (!diskSystem) 616 return false; 617 618 // get the info 619 return diskSystem->SupportsChildOperations(partition, 620 B_DISK_SYSTEM_SUPPORTS_SETTING_NAME); 621 } 622 623 // _user_supports_setting_partition_content_name 624 bool 625 _user_supports_setting_partition_content_name(partition_id partitionID, 626 int32 changeCounter, 627 bool *_whileMounted) 628 { 629 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 630 // get the partition 631 KPartition *partition = manager->ReadLockPartition(partitionID); 632 if (!partition) 633 return false; 634 PartitionRegistrar registrar1(partition, true); 635 PartitionRegistrar registrar2(partition->Device(), true); 636 DeviceReadLocker locker(partition->Device(), true); 637 if (!check_shadow_partition(partition, changeCounter)) 638 return false; 639 if (partition->IsBusy() || partition->IsDescendantBusy()) 640 return false; 641 // get the disk system 642 KDiskSystem *diskSystem = partition->DiskSystem(); 643 if (!diskSystem) 644 return false; 645 646 // get the info 647 uint32 operations = diskSystem->GetSupportedOperations(partition, 648 B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME 649 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME_WHILE_MOUNTED); 650 651 bool result = (operations & B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME); 652 if (result && _whileMounted) { 653 bool whileMounted = (operations 654 & B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME_WHILE_MOUNTED); 655 user_memcpy(_whileMounted, &whileMounted, sizeof(whileMounted)); 656 } 657 658 return result; 659 } 660 661 // _user_supports_setting_partition_type 662 bool 663 _user_supports_setting_partition_type(partition_id partitionID, 664 int32 changeCounter) 665 { 666 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 667 // get the partition 668 KPartition *partition = manager->ReadLockPartition(partitionID); 669 if (!partition) 670 return false; 671 PartitionRegistrar registrar1(partition, true); 672 PartitionRegistrar registrar2(partition->Device(), true); 673 DeviceReadLocker locker(partition->Device(), true); 674 if (!check_shadow_partition(partition, changeCounter) 675 || !partition->Parent()) { 676 return false; 677 } 678 if (partition->Parent()->IsBusy() 679 || partition->Parent()->IsDescendantBusy()) { 680 return false; 681 } 682 // get the disk system 683 KDiskSystem *diskSystem = partition->Parent()->DiskSystem(); 684 if (!diskSystem) 685 return false; 686 // get the info 687 return diskSystem->SupportsChildOperations(partition, 688 B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE); 689 } 690 691 // _user_supports_setting_partition_parameters 692 bool 693 _user_supports_setting_partition_parameters(partition_id partitionID, 694 int32 changeCounter) 695 { 696 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 697 // get the partition 698 KPartition *partition = manager->ReadLockPartition(partitionID); 699 if (!partition) 700 return false; 701 PartitionRegistrar registrar1(partition, true); 702 PartitionRegistrar registrar2(partition->Device(), true); 703 DeviceReadLocker locker(partition->Device(), true); 704 if (!check_shadow_partition(partition, changeCounter) 705 || !partition->Parent()) { 706 return false; 707 } 708 if (partition->Parent()->IsBusy() 709 || partition->Parent()->IsDescendantBusy()) { 710 return false; 711 } 712 // get the disk system 713 KDiskSystem *diskSystem = partition->Parent()->DiskSystem(); 714 if (!diskSystem) 715 return false; 716 // get the info 717 return diskSystem->SupportsChildOperations(partition, 718 B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS); 719 } 720 721 // _user_supports_setting_partition_content_parameters 722 bool 723 _user_supports_setting_partition_content_parameters(partition_id partitionID, 724 int32 changeCounter, 725 bool *_whileMounted) 726 { 727 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 728 // get the partition 729 KPartition *partition = manager->ReadLockPartition(partitionID); 730 if (!partition) 731 return false; 732 PartitionRegistrar registrar1(partition, true); 733 PartitionRegistrar registrar2(partition->Device(), true); 734 DeviceReadLocker locker(partition->Device(), true); 735 if (!check_shadow_partition(partition, changeCounter)) 736 return false; 737 if (partition->IsBusy() || partition->IsDescendantBusy()) 738 return false; 739 // get the disk system 740 KDiskSystem *diskSystem = partition->DiskSystem(); 741 if (!diskSystem) 742 return false; 743 // get the info 744 uint32 operations = diskSystem->GetSupportedOperations(partition, 745 B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS 746 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS_WHILE_MOUNTED); 747 bool result = (operations 748 & B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS); 749 if (result && _whileMounted) { 750 bool whileMounted = (operations 751 & B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS_WHILE_MOUNTED); 752 user_memcpy(_whileMounted, &whileMounted, sizeof(whileMounted)); 753 } 754 return result; 755 } 756 757 // _user_supports_initializing_partition 758 bool 759 _user_supports_initializing_partition(partition_id partitionID, 760 int32 changeCounter, 761 const char *_diskSystemName) 762 { 763 if (!_diskSystemName) 764 return false; 765 char diskSystemName[B_DISK_SYSTEM_NAME_LENGTH]; 766 status_t error = ddm_strlcpy(diskSystemName, _diskSystemName, B_DISK_SYSTEM_NAME_LENGTH); 767 if (error) 768 return error; 769 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 770 771 // get the partition 772 KPartition *partition = manager->ReadLockPartition(partitionID); 773 if (!partition) 774 return false; 775 PartitionRegistrar registrar1(partition, true); 776 PartitionRegistrar registrar2(partition->Device(), true); 777 DeviceReadLocker locker(partition->Device(), true); 778 if (!check_shadow_partition(partition, changeCounter)) 779 return false; 780 if (partition->IsBusy() || partition->IsDescendantBusy()) 781 return false; 782 783 // get the disk system 784 KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName); 785 if (!diskSystem) 786 return false; 787 DiskSystemLoader loader(diskSystem, true); 788 789 // get the info 790 if (!diskSystem->SupportsOperations(partition, 791 B_DISK_SYSTEM_SUPPORTS_INITIALIZING)) { 792 return false; 793 } 794 795 // get the parent partition's disk system 796 KPartition* parentPartition = partition->Parent(); 797 if (!parentPartition) 798 return true; 799 800 KDiskSystem* parentDiskSystem = parentPartition->DiskSystem(); 801 if (!parentDiskSystem) 802 return false; // something's fishy! 803 804 // ask the parent disk system 805 return parentDiskSystem->SupportsInitializingChild(partition, 806 diskSystemName); 807 } 808 809 // _user_supports_creating_child_partition 810 bool 811 _user_supports_creating_child_partition(partition_id partitionID, 812 int32 changeCounter) 813 { 814 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 815 // get the partition 816 KPartition *partition = manager->ReadLockPartition(partitionID); 817 if (!partition) 818 return false; 819 PartitionRegistrar registrar1(partition, true); 820 PartitionRegistrar registrar2(partition->Device(), true); 821 DeviceReadLocker locker(partition->Device(), true); 822 if (!check_shadow_partition(partition, changeCounter)) 823 return false; 824 if (partition->IsBusy() || partition->IsDescendantBusy()) 825 return false; 826 // get the disk system 827 KDiskSystem *diskSystem = partition->DiskSystem(); 828 if (!diskSystem) 829 return false; 830 // get the info 831 return diskSystem->SupportsOperations(partition, 832 B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD); 833 } 834 835 // _user_supports_deleting_child_partition 836 bool 837 _user_supports_deleting_child_partition(partition_id partitionID, 838 int32 changeCounter) 839 { 840 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 841 // get the partition 842 KPartition *partition = manager->ReadLockPartition(partitionID); 843 if (!partition) 844 return false; 845 PartitionRegistrar registrar1(partition, true); 846 PartitionRegistrar registrar2(partition->Device(), true); 847 DeviceReadLocker locker(partition->Device(), true); 848 return (validate_delete_child_partition(partition, changeCounter) == B_OK); 849 } 850 851 // _user_is_sub_disk_system_for 852 bool 853 _user_is_sub_disk_system_for(disk_system_id diskSystemID, 854 partition_id partitionID, int32 changeCounter) 855 { 856 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 857 // get the partition 858 KPartition *partition = manager->ReadLockPartition(partitionID); 859 if (!partition) 860 return false; 861 PartitionRegistrar registrar1(partition, true); 862 PartitionRegistrar registrar2(partition->Device(), true); 863 DeviceReadLocker locker(partition->Device(), true); 864 if (!check_shadow_partition(partition, changeCounter)) 865 return false; 866 // get the disk system 867 KDiskSystem *diskSystem = partition->DiskSystem(); 868 if (!diskSystem || diskSystem->ID() != diskSystemID) 869 return false; 870 // get the info 871 return diskSystem->IsSubSystemFor(partition); 872 } 873 874 // _user_validate_resize_partition 875 status_t 876 _user_validate_resize_partition(partition_id partitionID, int32 changeCounter, 877 off_t *_size) 878 { 879 if (!_size) 880 return B_BAD_VALUE; 881 off_t size; 882 user_memcpy(&size, _size, sizeof(size)); 883 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 884 // get the partition 885 KPartition *partition = manager->ReadLockPartition(partitionID); 886 if (!partition) 887 return B_ENTRY_NOT_FOUND; 888 PartitionRegistrar registrar1(partition, true); 889 PartitionRegistrar registrar2(partition->Device(), true); 890 DeviceReadLocker locker(partition->Device(), true); 891 off_t contentSize = 0; 892 bool result = validate_resize_partition(partition, changeCounter, &size, 893 &contentSize); 894 if (result) 895 user_memcpy(_size, &size, sizeof(size)); 896 return result; 897 } 898 899 // _user_validate_move_partition 900 status_t 901 _user_validate_move_partition(partition_id partitionID, int32 changeCounter, 902 off_t *_newOffset) 903 { 904 if (!_newOffset) 905 return B_BAD_VALUE; 906 off_t newOffset; 907 user_memcpy(&newOffset, _newOffset, sizeof(newOffset)); 908 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 909 // get the partition 910 KPartition *partition = manager->ReadLockPartition(partitionID); 911 if (!partition) 912 return B_ENTRY_NOT_FOUND; 913 PartitionRegistrar registrar1(partition, true); 914 PartitionRegistrar registrar2(partition->Device(), true); 915 DeviceReadLocker locker(partition->Device(), true); 916 status_t result = validate_move_partition(partition, changeCounter, &newOffset); 917 if (result) 918 user_memcpy(_newOffset, &newOffset, sizeof(newOffset)); 919 return result; 920 } 921 922 // _user_validate_set_partition_name 923 status_t 924 _user_validate_set_partition_name(partition_id partitionID, 925 int32 changeCounter, char *_name) 926 { 927 if (!_name) 928 return B_BAD_VALUE; 929 char name[B_DISK_DEVICE_NAME_LENGTH]; 930 status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH, true); 931 if (error) 932 return error; 933 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 934 // get the partition 935 KPartition *partition = manager->ReadLockPartition(partitionID); 936 if (!partition) 937 return B_ENTRY_NOT_FOUND; 938 PartitionRegistrar registrar1(partition, true); 939 PartitionRegistrar registrar2(partition->Device(), true); 940 DeviceReadLocker locker(partition->Device(), true); 941 error = validate_set_partition_name(partition, changeCounter, name); 942 if (!error) 943 error = ddm_strlcpy(_name, name, B_DISK_DEVICE_NAME_LENGTH); 944 return error; 945 } 946 947 // _user_validate_set_partition_content_name 948 status_t 949 _user_validate_set_partition_content_name(partition_id partitionID, 950 int32 changeCounter, char *_name) 951 { 952 if (!_name) 953 return B_BAD_VALUE; 954 char name[B_DISK_DEVICE_NAME_LENGTH]; 955 status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH, true); 956 if (error) 957 return error; 958 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 959 // get the partition 960 KPartition *partition = manager->ReadLockPartition(partitionID); 961 if (!partition) 962 return B_ENTRY_NOT_FOUND; 963 PartitionRegistrar registrar1(partition, true); 964 PartitionRegistrar registrar2(partition->Device(), true); 965 DeviceReadLocker locker(partition->Device(), true); 966 error = validate_set_partition_content_name(partition, changeCounter, name); 967 if (!error) 968 error = ddm_strlcpy(_name, name, B_DISK_DEVICE_NAME_LENGTH); 969 return error; 970 } 971 972 // _user_validate_set_partition_type 973 status_t 974 _user_validate_set_partition_type(partition_id partitionID, 975 int32 changeCounter, const char *_type) 976 { 977 if (!_type) 978 return B_BAD_VALUE; 979 char type[B_DISK_DEVICE_TYPE_LENGTH]; 980 status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); 981 if (error) 982 return error; 983 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 984 // get the partition 985 KPartition *partition = manager->ReadLockPartition(partitionID); 986 if (!partition) 987 return B_ENTRY_NOT_FOUND; 988 PartitionRegistrar registrar1(partition, true); 989 PartitionRegistrar registrar2(partition->Device(), true); 990 DeviceReadLocker locker(partition->Device(), true); 991 return validate_set_partition_type(partition, changeCounter, type); 992 } 993 994 // _user_validate_initialize_partition 995 status_t 996 _user_validate_initialize_partition(partition_id partitionID, 997 int32 changeCounter, 998 const char *_diskSystemName, char *_name, 999 const char *_parameters, 1000 size_t parametersSize) 1001 { 1002 if (!_diskSystemName || !_name || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 1003 return B_BAD_VALUE; 1004 char diskSystemName[B_DISK_SYSTEM_NAME_LENGTH]; 1005 char name[B_DISK_DEVICE_NAME_LENGTH]; 1006 char *parameters = NULL; 1007 status_t error = ddm_strlcpy(diskSystemName, _diskSystemName, B_DISK_SYSTEM_NAME_LENGTH); 1008 if (!error) 1009 error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH, true); 1010 if (error) 1011 return error; 1012 if (_parameters) { 1013 parameters = static_cast<char*>(malloc(parametersSize)); 1014 if (parameters) 1015 user_memcpy(parameters, _parameters, parametersSize); 1016 else 1017 return B_NO_MEMORY; 1018 } 1019 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1020 // get the partition 1021 KPartition *partition = manager->ReadLockPartition(partitionID); 1022 error = partition ? B_OK : B_ENTRY_NOT_FOUND; 1023 if (!error) { 1024 PartitionRegistrar registrar1(partition, true); 1025 PartitionRegistrar registrar2(partition->Device(), true); 1026 DeviceReadLocker locker(partition->Device(), true); 1027 error = validate_initialize_partition(partition, changeCounter, 1028 diskSystemName, name, parameters); 1029 } 1030 if (!error) 1031 error = ddm_strlcpy(_name, name, B_DISK_DEVICE_NAME_LENGTH); 1032 free(parameters); 1033 return error; 1034 } 1035 1036 // _user_validate_create_child_partition 1037 status_t 1038 _user_validate_create_child_partition(partition_id partitionID, 1039 int32 changeCounter, off_t *_offset, 1040 off_t *_size, const char *_type, 1041 const char *_parameters, 1042 size_t parametersSize) 1043 { 1044 if (!_offset || !_size || !_type 1045 || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 1046 { 1047 return B_BAD_VALUE; 1048 } 1049 off_t offset; 1050 off_t size; 1051 char type[B_DISK_DEVICE_TYPE_LENGTH]; 1052 char *parameters = NULL; 1053 user_memcpy(&offset, _offset, sizeof(offset)); 1054 user_memcpy(&size, _size, sizeof(size)); 1055 status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); 1056 if (error) 1057 return error; 1058 if (_parameters) { 1059 parameters = static_cast<char*>(malloc(parametersSize)); 1060 if (parameters) 1061 user_memcpy(parameters, _parameters, parametersSize); 1062 else 1063 return B_NO_MEMORY; 1064 } 1065 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1066 // get the partition 1067 KPartition *partition = manager->ReadLockPartition(partitionID); 1068 error = partition ? B_OK : B_ENTRY_NOT_FOUND; 1069 if (!error) { 1070 PartitionRegistrar registrar1(partition, true); 1071 PartitionRegistrar registrar2(partition->Device(), true); 1072 DeviceReadLocker locker(partition->Device(), true); 1073 error = validate_create_child_partition(partition, changeCounter, &offset, 1074 &size, type, parameters); 1075 } 1076 if (!error) { 1077 user_memcpy(_offset, &offset, sizeof(offset)); 1078 user_memcpy(_size, &size, sizeof(size)); 1079 } 1080 free(parameters); 1081 return error; 1082 } 1083 1084 // _user_get_next_supported_partition_type 1085 status_t 1086 _user_get_next_supported_partition_type(partition_id partitionID, 1087 int32 changeCounter, int32 *_cookie, 1088 char *_type) 1089 { 1090 if (!_cookie || !_type) 1091 return B_BAD_VALUE; 1092 int32 cookie; 1093 user_memcpy(&cookie, _cookie, sizeof(cookie)); 1094 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1095 // get the partition 1096 KPartition *partition = manager->ReadLockPartition(partitionID); 1097 status_t error = partition ? B_OK : B_ENTRY_NOT_FOUND; 1098 if (!error) { 1099 PartitionRegistrar registrar1(partition, true); 1100 PartitionRegistrar registrar2(partition->Device(), true); 1101 DeviceReadLocker locker(partition->Device(), true); 1102 error = check_shadow_partition(partition, changeCounter) ? B_OK : B_BAD_VALUE; 1103 if (!error) { 1104 // get the disk system 1105 KDiskSystem *diskSystem = partition->DiskSystem(); 1106 error = diskSystem ? B_OK : B_ENTRY_NOT_FOUND; 1107 if (!error) { 1108 // get the info 1109 char type[B_DISK_DEVICE_TYPE_LENGTH]; 1110 error = diskSystem->GetNextSupportedType(partition, &cookie, type); 1111 if (!error) { 1112 error = ddm_strlcpy(_type, type, B_DISK_DEVICE_TYPE_LENGTH); 1113 } 1114 } 1115 } 1116 } 1117 if (!error) 1118 user_memcpy(_cookie, &cookie, sizeof(cookie)); 1119 return error; 1120 } 1121 1122 // _user_get_partition_type_for_content_type 1123 status_t 1124 _user_get_partition_type_for_content_type(disk_system_id diskSystemID, 1125 const char *_contentType, char *_type) 1126 { 1127 if (!_contentType || !_type) 1128 return B_BAD_VALUE; 1129 char contentType[B_DISK_DEVICE_TYPE_LENGTH]; 1130 status_t error = ddm_strlcpy(contentType, _contentType, B_DISK_DEVICE_TYPE_LENGTH); 1131 if (error) 1132 return error; 1133 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1134 // get the disk system 1135 KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemID); 1136 if (!diskSystem) 1137 return false; 1138 DiskSystemLoader loader(diskSystem, true); 1139 // get the info 1140 char type[B_DISK_DEVICE_TYPE_LENGTH]; 1141 if (diskSystem->GetTypeForContentType(contentType, type)) { 1142 return ddm_strlcpy(_type, type, B_DISK_DEVICE_TYPE_LENGTH); 1143 } 1144 return B_ERROR; 1145 } 1146 1147 // _user_prepare_disk_device_modifications 1148 status_t 1149 _user_prepare_disk_device_modifications(partition_id deviceID) 1150 { 1151 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1152 // get the device 1153 if (KDiskDevice *device = manager->RegisterDevice(deviceID, true)) { 1154 PartitionRegistrar _(device, true); 1155 if (DeviceWriteLocker locker = device) { 1156 if (device->ShadowOwner() >= 0) 1157 return B_BUSY; 1158 // create shadow device 1159 return device->CreateShadowDevice(get_current_team()); 1160 } 1161 } 1162 return B_ENTRY_NOT_FOUND; 1163 } 1164 1165 // _user_commit_disk_device_modifications 1166 status_t 1167 _user_commit_disk_device_modifications(partition_id deviceID, port_id port, 1168 int32 token, bool completeProgress) 1169 { 1170 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1171 // get the device 1172 if (KDiskDevice *device = manager->RegisterDevice(deviceID, true)) { 1173 PartitionRegistrar _(device, true); 1174 if (DeviceWriteLocker locker = device) { 1175 if (device->ShadowOwner() != get_current_team()) 1176 return B_BAD_VALUE; 1177 // generate the jobs 1178 KDiskDeviceJobGenerator generator(manager->JobFactory(), device); 1179 status_t error = generator.GenerateJobs(); 1180 if (error != B_OK) 1181 return error; 1182 // add the jobs to the manager 1183 if (ManagerLocker locker2 = manager) { 1184 error = manager->AddJobQueue(generator.JobQueue()); 1185 if (error == B_OK) 1186 generator.DetachJobQueue(); 1187 else 1188 return error; 1189 } else 1190 return B_ERROR; 1191 // TODO: notification stuff 1192 return device->DeleteShadowDevice(); 1193 } 1194 } 1195 return B_ENTRY_NOT_FOUND; 1196 } 1197 1198 // _user_cancel_disk_device_modifications 1199 status_t 1200 _user_cancel_disk_device_modifications(partition_id deviceID) 1201 { 1202 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1203 // get the device 1204 if (KDiskDevice *device = manager->RegisterDevice(deviceID, true)) { 1205 PartitionRegistrar _(device, true); 1206 if (DeviceWriteLocker locker = device) { 1207 if (device->ShadowOwner() != get_current_team()) 1208 return B_BAD_VALUE; 1209 // delete shadow device 1210 return device->DeleteShadowDevice(); 1211 } 1212 } 1213 return B_ENTRY_NOT_FOUND; 1214 } 1215 1216 // _user_is_disk_device_modified 1217 bool 1218 _user_is_disk_device_modified(partition_id deviceID) 1219 { 1220 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1221 // get the device 1222 if (KDiskDevice *device = manager->RegisterDevice(deviceID, true)) { 1223 PartitionRegistrar _(device, true); 1224 if (DeviceReadLocker locker = device) { 1225 // check whether there's a shadow device and whether it's changed 1226 return (device->ShadowOwner() == get_current_team() 1227 && device->ShadowPartition() 1228 && device->ShadowPartition()->ChangeFlags() != 0); 1229 } 1230 } 1231 return B_ENTRY_NOT_FOUND; 1232 } 1233 1234 // _user_defragment_partition 1235 status_t 1236 _user_defragment_partition(partition_id partitionID, int32 changeCounter) 1237 { 1238 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1239 // get the partition 1240 KPartition *partition = manager->WriteLockPartition(partitionID); 1241 if (!partition) 1242 return B_ENTRY_NOT_FOUND; 1243 PartitionRegistrar registrar1(partition, true); 1244 PartitionRegistrar registrar2(partition->Device(), true); 1245 DeviceWriteLocker locker(partition->Device(), true); 1246 // check whether the disk system supports defragmenting 1247 status_t error = validate_defragment_partition(partition, changeCounter); 1248 if (error != B_OK) 1249 return error; 1250 // set the defragmenting flag 1251 partition->Changed(B_PARTITION_CHANGED_DEFRAGMENTATION); 1252 return B_OK; 1253 } 1254 1255 // _user_repair_partition 1256 status_t 1257 _user_repair_partition(partition_id partitionID, int32 changeCounter, 1258 bool checkOnly) 1259 { 1260 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1261 // get the partition 1262 KPartition *partition = manager->WriteLockPartition(partitionID); 1263 if (!partition) 1264 return B_ENTRY_NOT_FOUND; 1265 PartitionRegistrar registrar1(partition, true); 1266 PartitionRegistrar registrar2(partition->Device(), true); 1267 DeviceWriteLocker locker(partition->Device(), true); 1268 // check whether the disk system supports defragmenting 1269 status_t error = validate_repair_partition(partition, changeCounter, 1270 checkOnly); 1271 if (error != B_OK) 1272 return error; 1273 // set the respective flag 1274 if (checkOnly) 1275 partition->Changed(B_PARTITION_CHANGED_CHECK); 1276 else 1277 partition->Changed(B_PARTITION_CHANGED_REPAIR); 1278 return B_OK; 1279 } 1280 1281 // _user_resize_partition 1282 status_t 1283 _user_resize_partition(partition_id partitionID, int32 changeCounter, 1284 off_t size) 1285 { 1286 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1287 // get the partition 1288 KPartition *partition = manager->WriteLockPartition(partitionID); 1289 if (!partition) 1290 return B_ENTRY_NOT_FOUND; 1291 PartitionRegistrar registrar1(partition, true); 1292 PartitionRegistrar registrar2(partition->Device(), true); 1293 DeviceWriteLocker locker(partition->Device(), true); 1294 // check the size 1295 if (size == partition->Size()) 1296 return B_OK; 1297 off_t proposedSize = size; 1298 off_t contentSize = 0; 1299 status_t error = validate_resize_partition(partition, changeCounter, 1300 &proposedSize, &contentSize); 1301 if (error != B_OK) 1302 return error; 1303 if (proposedSize != size) 1304 return B_BAD_VALUE; 1305 // new size is fine -- resize the thing 1306 partition->SetSize(size); 1307 partition->Changed(B_PARTITION_CHANGED_SIZE); 1308 // implicit partitioning system changes 1309 error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( 1310 partition, B_PARTITION_RESIZE_CHILD); 1311 if (error != B_OK) 1312 return error; 1313 // implicit content disk system changes 1314 if (partition->DiskSystem()) { 1315 error = partition->DiskSystem()->ShadowPartitionChanged( 1316 partition, B_PARTITION_RESIZE); 1317 } 1318 return error; 1319 } 1320 1321 // _user_move_partition 1322 status_t 1323 _user_move_partition(partition_id partitionID, int32 changeCounter, 1324 off_t newOffset) 1325 { 1326 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1327 // get the partition 1328 KPartition *partition = manager->WriteLockPartition(partitionID); 1329 if (!partition) 1330 return B_ENTRY_NOT_FOUND; 1331 PartitionRegistrar registrar1(partition, true); 1332 PartitionRegistrar registrar2(partition->Device(), true); 1333 DeviceWriteLocker locker(partition->Device(), true); 1334 // check the new offset 1335 if (newOffset == partition->Offset()) 1336 return B_OK; 1337 off_t proposedOffset = newOffset; 1338 status_t error = validate_move_partition(partition, changeCounter, 1339 &proposedOffset, true); 1340 if (error != B_OK) 1341 return error; 1342 if (proposedOffset != newOffset) 1343 return B_BAD_VALUE; 1344 // new offset is fine -- move the thing 1345 off_t moveBy = newOffset - partition->Offset(); 1346 move_descendants(partition, moveBy); 1347 partition->Changed(B_PARTITION_CHANGED_OFFSET); 1348 // implicit partitioning system changes 1349 error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( 1350 partition, B_PARTITION_MOVE_CHILD); 1351 if (error != B_OK) 1352 return error; 1353 // implicit descendants' content disk system changes 1354 return move_descendants_contents(partition); 1355 } 1356 1357 // _user_set_partition_name 1358 status_t 1359 _user_set_partition_name(partition_id partitionID, int32 changeCounter, 1360 const char *_name) 1361 { 1362 if (!_name) 1363 return B_BAD_VALUE; 1364 char name[B_DISK_DEVICE_NAME_LENGTH]; 1365 status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); 1366 if (error) 1367 return error; 1368 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1369 // get the partition 1370 KPartition *partition = manager->WriteLockPartition(partitionID); 1371 if (!partition) 1372 return B_ENTRY_NOT_FOUND; 1373 PartitionRegistrar registrar1(partition, true); 1374 PartitionRegistrar registrar2(partition->Device(), true); 1375 DeviceWriteLocker locker(partition->Device(), true); 1376 // check name 1377 char proposedName[B_DISK_DEVICE_NAME_LENGTH]; 1378 strcpy(proposedName, name); 1379 error = validate_set_partition_name(partition, changeCounter, 1380 proposedName); 1381 if (error != B_OK) 1382 return error; 1383 if (strcmp(name, proposedName)) 1384 return B_BAD_VALUE; 1385 // set name 1386 error = partition->SetName(name); 1387 if (error != B_OK) 1388 return error; 1389 partition->Changed(B_PARTITION_CHANGED_NAME); 1390 // implicit partitioning system changes 1391 return partition->Parent()->DiskSystem()->ShadowPartitionChanged( 1392 partition, B_PARTITION_SET_NAME); 1393 } 1394 1395 // _user_set_partition_content_name 1396 status_t 1397 _user_set_partition_content_name(partition_id partitionID, int32 changeCounter, 1398 const char *_name) 1399 { 1400 if (!_name) 1401 return B_BAD_VALUE; 1402 char name[B_DISK_DEVICE_NAME_LENGTH]; 1403 status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); 1404 if (error) 1405 return error; 1406 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1407 // get the partition 1408 KPartition *partition = manager->WriteLockPartition(partitionID); 1409 if (!partition) 1410 return B_ENTRY_NOT_FOUND; 1411 PartitionRegistrar registrar1(partition, true); 1412 PartitionRegistrar registrar2(partition->Device(), true); 1413 DeviceWriteLocker locker(partition->Device(), true); 1414 // check name 1415 char proposedName[B_DISK_DEVICE_NAME_LENGTH]; 1416 strcpy(proposedName, name); 1417 error = validate_set_partition_content_name(partition, 1418 changeCounter, proposedName); 1419 if (error != B_OK) 1420 return error; 1421 if (strcmp(name, proposedName)) 1422 return B_BAD_VALUE; 1423 // set name 1424 error = partition->SetContentName(name); 1425 if (error != B_OK) 1426 return error; 1427 partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME); 1428 // implicit content disk system changes 1429 return partition->DiskSystem()->ShadowPartitionChanged( 1430 partition, B_PARTITION_SET_CONTENT_NAME); 1431 } 1432 1433 // _user_set_partition_type 1434 status_t 1435 _user_set_partition_type(partition_id partitionID, int32 changeCounter, 1436 const char *_type) 1437 { 1438 if (!_type) 1439 return B_BAD_VALUE; 1440 char type[B_DISK_DEVICE_TYPE_LENGTH]; 1441 status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); 1442 if (error) 1443 return error; 1444 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1445 // get the partition 1446 KPartition *partition = manager->WriteLockPartition(partitionID); 1447 if (!partition) 1448 return B_ENTRY_NOT_FOUND; 1449 PartitionRegistrar registrar1(partition, true); 1450 PartitionRegistrar registrar2(partition->Device(), true); 1451 DeviceWriteLocker locker(partition->Device(), true); 1452 // check type 1453 error = validate_set_partition_type(partition, changeCounter, 1454 type); 1455 if (error != B_OK) 1456 return error; 1457 // set type 1458 error = partition->SetType(type); 1459 if (error != B_OK) 1460 return error; 1461 partition->Changed(B_PARTITION_CHANGED_TYPE); 1462 // implicit partitioning system changes 1463 return partition->Parent()->DiskSystem()->ShadowPartitionChanged( 1464 partition, B_PARTITION_SET_TYPE); 1465 } 1466 1467 // _user_set_partition_parameters 1468 status_t 1469 _user_set_partition_parameters(partition_id partitionID, int32 changeCounter, 1470 const char *_parameters, size_t parametersSize) 1471 { 1472 if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 1473 return B_BAD_VALUE; 1474 char *parameters = NULL; 1475 if (_parameters) { 1476 parameters = static_cast<char*>(malloc(parametersSize)); 1477 if (parameters) 1478 user_memcpy(parameters, _parameters, parametersSize); 1479 else 1480 return B_NO_MEMORY; 1481 } 1482 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1483 // get the partition 1484 KPartition *partition = manager->WriteLockPartition(partitionID); 1485 status_t error = partition ? B_OK : B_ENTRY_NOT_FOUND; 1486 if (!error) { 1487 PartitionRegistrar registrar1(partition, true); 1488 PartitionRegistrar registrar2(partition->Device(), true); 1489 DeviceWriteLocker locker(partition->Device(), true); 1490 // check parameters 1491 error = validate_set_partition_parameters(partition, 1492 changeCounter, parameters); 1493 if (!error) { 1494 // set type 1495 error = partition->SetParameters(parameters); 1496 if (!error) { 1497 partition->Changed(B_PARTITION_CHANGED_PARAMETERS); 1498 // implicit partitioning system changes 1499 error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( 1500 partition, B_PARTITION_SET_PARAMETERS); 1501 } 1502 } 1503 } 1504 free(parameters); 1505 return error; 1506 } 1507 1508 // _user_set_partition_content_parameters 1509 status_t 1510 _user_set_partition_content_parameters(partition_id partitionID, 1511 int32 changeCounter, 1512 const char *_parameters, 1513 size_t parametersSize) 1514 { 1515 if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 1516 return B_BAD_VALUE; 1517 char *parameters = NULL; 1518 if (_parameters) { 1519 parameters = static_cast<char*>(malloc(parametersSize)); 1520 if (parameters) 1521 user_memcpy(parameters, _parameters, parametersSize); 1522 else 1523 return B_NO_MEMORY; 1524 } 1525 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1526 // get the partition 1527 KPartition *partition = manager->WriteLockPartition(partitionID); 1528 status_t error = partition ? B_OK : B_ENTRY_NOT_FOUND; 1529 if (!error) { 1530 PartitionRegistrar registrar1(partition, true); 1531 PartitionRegistrar registrar2(partition->Device(), true); 1532 DeviceWriteLocker locker(partition->Device(), true); 1533 // check parameters 1534 error = validate_set_partition_content_parameters(partition, 1535 changeCounter, parameters); 1536 if (!error) { 1537 // set name 1538 error = partition->SetContentParameters(parameters); 1539 if (!error) { 1540 partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); 1541 // implicit content disk system changes 1542 error = partition->DiskSystem()->ShadowPartitionChanged( 1543 partition, B_PARTITION_SET_CONTENT_PARAMETERS); 1544 } 1545 } 1546 } 1547 free(partition); 1548 return error; 1549 } 1550 1551 // _user_initialize_partition 1552 status_t 1553 _user_initialize_partition(partition_id partitionID, int32 changeCounter, 1554 const char *_diskSystemName, const char *_name, 1555 const char *_parameters, size_t parametersSize) 1556 { 1557 if (!_diskSystemName || !_name || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 1558 return B_BAD_VALUE; 1559 char diskSystemName[B_DISK_SYSTEM_NAME_LENGTH]; 1560 char name[B_DISK_DEVICE_NAME_LENGTH]; 1561 char *parameters = NULL; 1562 status_t error = ddm_strlcpy(diskSystemName, _diskSystemName, B_DISK_SYSTEM_NAME_LENGTH); 1563 if (!error) 1564 error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); 1565 if (error) 1566 return error; 1567 if (_parameters) { 1568 parameters = static_cast<char*>(malloc(parametersSize)); 1569 if (parameters) 1570 user_memcpy(parameters, _parameters, parametersSize); 1571 else 1572 return B_NO_MEMORY; 1573 } 1574 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1575 // get the partition 1576 KPartition *partition = manager->WriteLockPartition(partitionID); 1577 error = partition ? B_OK : B_ENTRY_NOT_FOUND; 1578 if (!error) { 1579 PartitionRegistrar registrar1(partition, true); 1580 PartitionRegistrar registrar2(partition->Device(), true); 1581 DeviceWriteLocker locker(partition->Device(), true); 1582 // get the disk system 1583 KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName); 1584 error = diskSystem ? B_OK : B_ENTRY_NOT_FOUND; 1585 if (!error) { 1586 DiskSystemLoader loader(diskSystem, true); 1587 // check parameters 1588 char proposedName[B_DISK_DEVICE_NAME_LENGTH]; 1589 strcpy(proposedName, name); 1590 error = validate_initialize_partition(partition, changeCounter, 1591 diskSystemName, proposedName, parameters); 1592 if (!error) { 1593 error = !strcmp(name, proposedName) ? B_OK : B_BAD_VALUE; 1594 } 1595 if (!error) { 1596 // unitialize the partition's contents and set the new parameters 1597 error = partition->UninitializeContents(true); 1598 } 1599 if (!error) { 1600 partition->SetDiskSystem(diskSystem); 1601 error = partition->SetContentName(name); 1602 } 1603 if (!error) { 1604 partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME); 1605 error = partition->SetContentParameters(parameters); 1606 } 1607 if (!error) { 1608 partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); 1609 partition->Changed(B_PARTITION_CHANGED_INITIALIZATION); 1610 // implicit content disk system changes 1611 error = partition->DiskSystem()->ShadowPartitionChanged( 1612 partition, B_PARTITION_INITIALIZE); 1613 } 1614 } 1615 } 1616 free(parameters); 1617 return error; 1618 } 1619 1620 // _user_uninitialize_partition 1621 status_t 1622 _user_uninitialize_partition(partition_id partitionID, int32 changeCounter) 1623 { 1624 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1625 // get the partition 1626 KPartition *partition = manager->WriteLockPartition(partitionID); 1627 if (!partition) 1628 return B_ENTRY_NOT_FOUND; 1629 PartitionRegistrar registrar1(partition, true); 1630 PartitionRegistrar registrar2(partition->Device(), true); 1631 DeviceWriteLocker locker(partition->Device(), true); 1632 // unitialize the partition's contents and set the new parameters 1633 return partition->UninitializeContents(true); 1634 } 1635 1636 // _user_create_child_partition 1637 status_t 1638 _user_create_child_partition(partition_id partitionID, int32 changeCounter, 1639 off_t offset, off_t size, const char *_type, 1640 const char *_parameters, size_t parametersSize, 1641 partition_id *_childID) 1642 { 1643 if (!_type || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 1644 return B_BAD_VALUE; 1645 char type[B_DISK_DEVICE_TYPE_LENGTH]; 1646 char *parameters = NULL; 1647 status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); 1648 if (error) 1649 return error; 1650 if (_parameters) { 1651 parameters = static_cast<char*>(malloc(parametersSize)); 1652 if (parameters) 1653 user_memcpy(parameters, _parameters, parametersSize); 1654 else 1655 return B_NO_MEMORY; 1656 } 1657 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1658 // get the partition 1659 KPartition *partition = manager->WriteLockPartition(partitionID); 1660 error = partition ? B_OK : B_ENTRY_NOT_FOUND; 1661 if (!error) { 1662 PartitionRegistrar registrar1(partition, true); 1663 PartitionRegistrar registrar2(partition->Device(), true); 1664 DeviceWriteLocker locker(partition->Device(), true); 1665 // check the parameters 1666 off_t proposedOffset = offset; 1667 off_t proposedSize = size; 1668 int32 index = 0; 1669 error = validate_create_child_partition(partition, changeCounter, 1670 &proposedOffset, &proposedSize, type, parameters, &index); 1671 if (!error) { 1672 error = (proposedOffset == offset && proposedSize == size) 1673 ? B_OK : B_BAD_VALUE; 1674 if (!error) { 1675 // create the child 1676 KPartition *child = NULL; 1677 error = partition->CreateChild(-1, index, &child); 1678 if (!error) { 1679 partition->Changed(B_PARTITION_CHANGED_CHILDREN); 1680 if (_childID) { 1681 partition_id childID = child->ID(); 1682 user_memcpy(_childID, &childID, sizeof(childID)); 1683 } 1684 // set the parameters 1685 child->SetOffset(offset); 1686 child->SetSize(offset); 1687 error = child->SetType(type); 1688 } 1689 if (!error) { 1690 error = partition->SetParameters(parameters); 1691 } 1692 if (!error) { 1693 // implicit partitioning system changes 1694 error = partition->DiskSystem()->ShadowPartitionChanged( 1695 partition, B_PARTITION_CREATE_CHILD); 1696 } 1697 } 1698 } 1699 } 1700 free(parameters); 1701 return error; 1702 } 1703 1704 // _user_delete_partition 1705 status_t 1706 _user_delete_partition(partition_id partitionID, int32 changeCounter) 1707 { 1708 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1709 // get the partition 1710 KPartition *partition = manager->WriteLockPartition(partitionID); 1711 if (!partition) 1712 return B_ENTRY_NOT_FOUND; 1713 PartitionRegistrar registrar1(partition, true); 1714 PartitionRegistrar registrar2(partition->Device(), true); 1715 DeviceWriteLocker locker(partition->Device(), true); 1716 // check whether delete the child is OK 1717 status_t error = validate_delete_child_partition(partition, changeCounter); 1718 if (error != B_OK) 1719 return error; 1720 // delete the child 1721 KPartition *parent = partition->Parent(); 1722 if (!parent->RemoveChild(partition)) 1723 return B_ERROR; 1724 parent->Changed(B_PARTITION_CHANGED_CHILDREN); 1725 return B_OK; 1726 } 1727 1728 // _user_get_next_disk_device_job_info 1729 status_t 1730 _user_get_next_disk_device_job_info(int32 *_cookie, 1731 user_disk_device_job_info *_info) 1732 { 1733 if (!_cookie || !_info) 1734 return B_BAD_VALUE; 1735 int32 cookie; 1736 user_disk_device_job_info info; 1737 user_memcpy(&cookie, _cookie, sizeof(cookie)); 1738 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1739 status_t error = B_ENTRY_NOT_FOUND; 1740 if (ManagerLocker locker = manager) { 1741 // get the next job and an info 1742 while (KDiskDeviceJob *job = manager->NextJob(&cookie)) { 1743 // return info only on job scheduled or in progress 1744 switch (job->Status()) { 1745 case B_DISK_DEVICE_JOB_SCHEDULED: 1746 case B_DISK_DEVICE_JOB_IN_PROGRESS: 1747 error = job->GetInfo(&info); 1748 break; 1749 case B_DISK_DEVICE_JOB_UNINITIALIZED: 1750 case B_DISK_DEVICE_JOB_SUCCEEDED: 1751 case B_DISK_DEVICE_JOB_FAILED: 1752 case B_DISK_DEVICE_JOB_CANCELED: 1753 break; 1754 } 1755 } 1756 } 1757 if (!error) { 1758 user_memcpy(_cookie, &cookie, sizeof(cookie)); 1759 user_memcpy(_info, &info, sizeof(info)); 1760 } 1761 return error; 1762 } 1763 1764 // _user_get_disk_device_job_info 1765 status_t 1766 _user_get_disk_device_job_info(disk_job_id id, user_disk_device_job_info *_info) 1767 { 1768 if (!_info) 1769 return B_BAD_VALUE; 1770 user_disk_device_job_info info; 1771 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1772 status_t error = B_ENTRY_NOT_FOUND; 1773 if (ManagerLocker locker = manager) { 1774 // find the job and get the info 1775 if (KDiskDeviceJob *job = manager->FindJob(id)) 1776 error = job->GetInfo(&info); 1777 } 1778 if (!error) 1779 user_memcpy(_info, &info, sizeof(info)); 1780 return error; 1781 } 1782 1783 // _user_get_disk_device_job_status 1784 status_t 1785 _user_get_disk_device_job_progress_info(disk_job_id id, 1786 disk_device_job_progress_info *_info) 1787 { 1788 if (!_info) 1789 return B_BAD_VALUE; 1790 disk_device_job_progress_info info; 1791 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1792 status_t error = B_ENTRY_NOT_FOUND; 1793 if (ManagerLocker locker = manager) { 1794 // find the job and get the info 1795 if (KDiskDeviceJob *job = manager->FindJob(id)) 1796 error = job->GetProgressInfo(&info); 1797 } 1798 if (!error) 1799 user_memcpy(_info, &info, sizeof(info)); 1800 return error; 1801 } 1802 1803 // _user_pause_disk_device_job 1804 status_t 1805 _user_pause_disk_device_job(disk_job_id id) 1806 { 1807 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1808 if (ManagerLocker locker = manager) { 1809 // get the job and the respective job queue 1810 if (KDiskDeviceJob *job = manager->FindJob(id)) { 1811 if (KDiskDeviceJobQueue *jobQueue = job->JobQueue()) { 1812 // only the active job in progress can be paused 1813 if (jobQueue->ActiveJob() != job) 1814 return B_BAD_VALUE; 1815 return jobQueue->Pause(); 1816 } 1817 } 1818 } 1819 return B_ENTRY_NOT_FOUND; 1820 } 1821 1822 // _user_cancel_disk_device_job 1823 status_t 1824 _user_cancel_disk_device_job(disk_job_id id, bool reverse) 1825 { 1826 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 1827 if (ManagerLocker locker = manager) { 1828 // get the job and the respective job queue 1829 if (KDiskDeviceJob *job = manager->FindJob(id)) { 1830 if (KDiskDeviceJobQueue *jobQueue = job->JobQueue()) { 1831 // only the active job in progress can be canceled 1832 if (jobQueue->ActiveJob() != job) 1833 return B_BAD_VALUE; 1834 return jobQueue->Cancel(reverse); 1835 } 1836 } 1837 } 1838 return B_ENTRY_NOT_FOUND; 1839 } 1840 1841