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