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