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_defragment_partition 452 status_t 453 _user_defragment_partition(partition_id partitionID, int32* changeCounter) 454 { 455 #if 0 456 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 457 // get the partition 458 KPartition *partition = manager->WriteLockPartition(partitionID); 459 if (!partition) 460 return B_ENTRY_NOT_FOUND; 461 PartitionRegistrar registrar1(partition, true); 462 PartitionRegistrar registrar2(partition->Device(), true); 463 DeviceWriteLocker locker(partition->Device(), true); 464 // check whether the disk system supports defragmenting 465 status_t error = validate_defragment_partition(partition, changeCounter); 466 if (error != B_OK) 467 return error; 468 // set the defragmenting flag 469 partition->Changed(B_PARTITION_CHANGED_DEFRAGMENTATION); 470 return B_OK; 471 #endif 472 return B_BAD_VALUE; 473 } 474 475 476 // _user_repair_partition 477 status_t 478 _user_repair_partition(partition_id partitionID, int32* changeCounter, 479 bool checkOnly) 480 { 481 #if 0 482 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 483 // get the partition 484 KPartition *partition = manager->WriteLockPartition(partitionID); 485 if (!partition) 486 return B_ENTRY_NOT_FOUND; 487 PartitionRegistrar registrar1(partition, true); 488 PartitionRegistrar registrar2(partition->Device(), true); 489 DeviceWriteLocker locker(partition->Device(), true); 490 // check whether the disk system supports defragmenting 491 status_t error = validate_repair_partition(partition, changeCounter, 492 checkOnly); 493 if (error != B_OK) 494 return error; 495 // set the respective flag 496 if (checkOnly) 497 partition->Changed(B_PARTITION_CHANGED_CHECK); 498 else 499 partition->Changed(B_PARTITION_CHANGED_REPAIR); 500 return B_OK; 501 #endif 502 return B_BAD_VALUE; 503 } 504 505 506 // _user_resize_partition 507 status_t 508 _user_resize_partition(partition_id partitionID, int32* changeCounter, 509 partition_id childID, int32* childChangeCounter, off_t size, 510 off_t contentSize) 511 { 512 #if 0 513 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 514 // get the partition 515 KPartition *partition = manager->WriteLockPartition(partitionID); 516 if (!partition) 517 return B_ENTRY_NOT_FOUND; 518 PartitionRegistrar registrar1(partition, true); 519 PartitionRegistrar registrar2(partition->Device(), true); 520 DeviceWriteLocker locker(partition->Device(), true); 521 // check the size 522 if (size == partition->Size()) 523 return B_OK; 524 off_t proposedSize = size; 525 off_t contentSize = 0; 526 status_t error = validate_resize_partition(partition, changeCounter, 527 &proposedSize, &contentSize); 528 if (error != B_OK) 529 return error; 530 if (proposedSize != size) 531 return B_BAD_VALUE; 532 // new size is fine -- resize the thing 533 partition->SetSize(size); 534 partition->Changed(B_PARTITION_CHANGED_SIZE); 535 // implicit partitioning system changes 536 error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( 537 partition->Parent(), partition, B_PARTITION_RESIZE_CHILD); 538 if (error != B_OK) 539 return error; 540 // implicit content disk system changes 541 if (partition->DiskSystem()) { 542 error = partition->DiskSystem()->ShadowPartitionChanged( 543 partition, NULL, B_PARTITION_RESIZE); 544 } 545 return error; 546 #endif 547 return B_BAD_VALUE; 548 } 549 550 551 // _user_move_partition 552 status_t 553 _user_move_partition(partition_id partitionID, int32* changeCounter, 554 partition_id childID, int32* childChangeCounter, off_t newOffset, 555 partition_id* descendantIDs, int32* descendantChangeCounters, 556 int32 descendantCount) 557 { 558 #if 0 559 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 560 // get the partition 561 KPartition *partition = manager->WriteLockPartition(partitionID); 562 if (!partition) 563 return B_ENTRY_NOT_FOUND; 564 PartitionRegistrar registrar1(partition, true); 565 PartitionRegistrar registrar2(partition->Device(), true); 566 DeviceWriteLocker locker(partition->Device(), true); 567 // check the new offset 568 if (newOffset == partition->Offset()) 569 return B_OK; 570 off_t proposedOffset = newOffset; 571 status_t error = validate_move_partition(partition, changeCounter, 572 &proposedOffset, true); 573 if (error != B_OK) 574 return error; 575 if (proposedOffset != newOffset) 576 return B_BAD_VALUE; 577 // new offset is fine -- move the thing 578 off_t moveBy = newOffset - partition->Offset(); 579 move_descendants(partition, moveBy); 580 partition->Changed(B_PARTITION_CHANGED_OFFSET); 581 // implicit partitioning system changes 582 error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( 583 partition->Parent(), partition, B_PARTITION_MOVE_CHILD); 584 if (error != B_OK) 585 return error; 586 // implicit descendants' content disk system changes 587 return move_descendants_contents(partition); 588 #endif 589 return B_BAD_VALUE; 590 } 591 592 593 // _user_set_partition_name 594 status_t 595 _user_set_partition_name(partition_id partitionID, int32* changeCounter, 596 partition_id childID, int32* childChangeCounter, const char* name) 597 { 598 #if 0 599 if (!_name) 600 return B_BAD_VALUE; 601 char name[B_DISK_DEVICE_NAME_LENGTH]; 602 status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); 603 if (error) 604 return error; 605 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 606 // get the partition 607 KPartition *partition = manager->WriteLockPartition(partitionID); 608 if (!partition) 609 return B_ENTRY_NOT_FOUND; 610 PartitionRegistrar registrar1(partition, true); 611 PartitionRegistrar registrar2(partition->Device(), true); 612 DeviceWriteLocker locker(partition->Device(), true); 613 // check name 614 char proposedName[B_DISK_DEVICE_NAME_LENGTH]; 615 strcpy(proposedName, name); 616 error = validate_set_partition_name(partition, changeCounter, proposedName); 617 if (error != B_OK) 618 return error; 619 if (strcmp(name, proposedName)) 620 return B_BAD_VALUE; 621 // set name 622 error = partition->SetName(name); 623 if (error != B_OK) 624 return error; 625 partition->Changed(B_PARTITION_CHANGED_NAME); 626 // implicit partitioning system changes 627 return partition->Parent()->DiskSystem()->ShadowPartitionChanged( 628 partition->Parent(), partition, B_PARTITION_SET_NAME); 629 #endif 630 return B_BAD_VALUE; 631 } 632 633 634 // _user_set_partition_content_name 635 status_t 636 _user_set_partition_content_name(partition_id partitionID, int32* changeCounter, 637 const char* name) 638 { 639 #if 0 640 if (!_name) 641 return B_BAD_VALUE; 642 char name[B_DISK_DEVICE_NAME_LENGTH]; 643 status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); 644 if (error) 645 return error; 646 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 647 // get the partition 648 KPartition *partition = manager->WriteLockPartition(partitionID); 649 if (!partition) 650 return B_ENTRY_NOT_FOUND; 651 PartitionRegistrar registrar1(partition, true); 652 PartitionRegistrar registrar2(partition->Device(), true); 653 DeviceWriteLocker locker(partition->Device(), true); 654 // check name 655 char proposedName[B_DISK_DEVICE_NAME_LENGTH]; 656 strcpy(proposedName, name); 657 error = validate_set_partition_content_name(partition, 658 changeCounter, proposedName); 659 if (error != B_OK) 660 return error; 661 if (strcmp(name, proposedName)) 662 return B_BAD_VALUE; 663 // set name 664 error = partition->SetContentName(name); 665 if (error != B_OK) 666 return error; 667 partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME); 668 // implicit content disk system changes 669 return partition->DiskSystem()->ShadowPartitionChanged( 670 partition, NULL, B_PARTITION_SET_CONTENT_NAME); 671 #endif 672 return B_BAD_VALUE; 673 } 674 675 676 // _user_set_partition_type 677 status_t 678 _user_set_partition_type(partition_id partitionID, int32* changeCounter, 679 partition_id childID, int32* childChangeCounter, const char* type) 680 { 681 #if 0 682 if (!_type) 683 return B_BAD_VALUE; 684 char type[B_DISK_DEVICE_TYPE_LENGTH]; 685 status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); 686 if (error) 687 return error; 688 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 689 // get the partition 690 KPartition *partition = manager->WriteLockPartition(partitionID); 691 if (!partition) 692 return B_ENTRY_NOT_FOUND; 693 PartitionRegistrar registrar1(partition, true); 694 PartitionRegistrar registrar2(partition->Device(), true); 695 DeviceWriteLocker locker(partition->Device(), true); 696 // check type 697 error = validate_set_partition_type(partition, changeCounter, type); 698 if (error != B_OK) 699 return error; 700 // set type 701 error = partition->SetType(type); 702 if (error != B_OK) 703 return error; 704 partition->Changed(B_PARTITION_CHANGED_TYPE); 705 // implicit partitioning system changes 706 return partition->Parent()->DiskSystem()->ShadowPartitionChanged( 707 partition->Parent(), partition, B_PARTITION_SET_TYPE); 708 #endif 709 return B_BAD_VALUE; 710 } 711 712 713 // _user_set_partition_parameters 714 status_t 715 _user_set_partition_parameters(partition_id partitionID, int32* changeCounter, 716 partition_id childID, int32* childChangeCounter, const char* parameters, 717 size_t parametersSize) 718 { 719 #if 0 720 if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 721 return B_BAD_VALUE; 722 char *parameters = NULL; 723 if (_parameters) { 724 parameters = static_cast<char*>(malloc(parametersSize)); 725 if (parameters) 726 user_memcpy(parameters, _parameters, parametersSize); 727 else 728 return B_NO_MEMORY; 729 } 730 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 731 // get the partition 732 KPartition *partition = manager->WriteLockPartition(partitionID); 733 status_t error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; 734 if (!error) { 735 PartitionRegistrar registrar1(partition, true); 736 PartitionRegistrar registrar2(partition->Device(), true); 737 DeviceWriteLocker locker(partition->Device(), true); 738 // check parameters 739 error = validate_set_partition_parameters(partition, 740 changeCounter, parameters); 741 if (!error) { 742 // set type 743 error = partition->SetParameters(parameters); 744 if (!error) { 745 partition->Changed(B_PARTITION_CHANGED_PARAMETERS); 746 // implicit partitioning system changes 747 error = partition->Parent()->DiskSystem() 748 ->ShadowPartitionChanged(partition->Parent(), partition, 749 B_PARTITION_SET_PARAMETERS); 750 } 751 } 752 } 753 free(parameters); 754 return error; 755 #endif 756 return B_BAD_VALUE; 757 } 758 759 760 // _user_set_partition_content_parameters 761 status_t 762 _user_set_partition_content_parameters(partition_id partitionID, 763 int32* changeCounter, const char* parameters, size_t parametersSize) 764 { 765 #if 0 766 if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 767 return B_BAD_VALUE; 768 char *parameters = NULL; 769 if (_parameters) { 770 parameters = static_cast<char*>(malloc(parametersSize)); 771 if (parameters) 772 user_memcpy(parameters, _parameters, parametersSize); 773 else 774 return B_NO_MEMORY; 775 } 776 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 777 // get the partition 778 KPartition *partition = manager->WriteLockPartition(partitionID); 779 status_t error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; 780 if (!error) { 781 PartitionRegistrar registrar1(partition, true); 782 PartitionRegistrar registrar2(partition->Device(), true); 783 DeviceWriteLocker locker(partition->Device(), true); 784 // check parameters 785 error = validate_set_partition_content_parameters(partition, 786 changeCounter, parameters); 787 if (!error) { 788 // set name 789 error = partition->SetContentParameters(parameters); 790 if (!error) { 791 partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); 792 // implicit content disk system changes 793 error = partition->DiskSystem()->ShadowPartitionChanged( 794 partition, NULL, B_PARTITION_SET_CONTENT_PARAMETERS); 795 } 796 } 797 } 798 free(partition); 799 return error; 800 #endif 801 return B_BAD_VALUE; 802 } 803 804 805 // _user_initialize_partition 806 status_t 807 _user_initialize_partition(partition_id partitionID, int32* changeCounter, 808 const char* diskSystemName, const char* name, const char* parameters, 809 size_t parametersSize) 810 { 811 #if 0 812 if (!_diskSystemName || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 813 return B_BAD_VALUE; 814 815 // copy disk system name 816 char diskSystemName[B_DISK_SYSTEM_NAME_LENGTH]; 817 status_t error = ddm_strlcpy(diskSystemName, _diskSystemName, 818 B_DISK_SYSTEM_NAME_LENGTH); 819 820 // copy name 821 char name[B_DISK_DEVICE_NAME_LENGTH]; 822 if (!error && _name) 823 error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); 824 825 if (error) 826 return error; 827 828 // copy parameters 829 MemoryDeleter parameterDeleter; 830 char *parameters = NULL; 831 if (_parameters) { 832 parameters = static_cast<char*>(malloc(parametersSize)); 833 if (!parameters) 834 return B_NO_MEMORY; 835 parameterDeleter.SetTo(parameters); 836 837 if (user_memcpy(parameters, _parameters, parametersSize) != B_OK) 838 return B_BAD_ADDRESS; 839 } 840 841 // get the partition 842 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 843 KPartition *partition = manager->WriteLockPartition(partitionID); 844 if (!partition) 845 return B_ENTRY_NOT_FOUND; 846 847 PartitionRegistrar registrar1(partition, true); 848 PartitionRegistrar registrar2(partition->Device(), true); 849 DeviceWriteLocker locker(partition->Device(), true); 850 851 // get the disk system 852 KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName); 853 if (!diskSystem) 854 return B_ENTRY_NOT_FOUND; 855 DiskSystemLoader loader(diskSystem, true); 856 857 // check parameters 858 char proposedName[B_DISK_DEVICE_NAME_LENGTH]; 859 if (_name) 860 strcpy(proposedName, name); 861 862 error = validate_initialize_partition(partition, changeCounter, 863 diskSystemName, _name ? proposedName : NULL, parameters); 864 if (error != B_OK) 865 return error; 866 if (_name && strcmp(name, proposedName) != 0) 867 return B_BAD_VALUE; 868 869 // unitialize the partition's contents and set the new 870 // parameters 871 if ((error = partition->UninitializeContents(true)) != B_OK) 872 return error; 873 874 partition->SetDiskSystem(diskSystem); 875 876 if ((error = partition->SetContentName(_name ? name : NULL)) != B_OK) 877 return error; 878 partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME); 879 880 if ((error = partition->SetContentParameters(parameters)) != B_OK) 881 return error; 882 partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); 883 884 partition->Changed(B_PARTITION_CHANGED_INITIALIZATION); 885 886 // implicit content disk system changes 887 return partition->DiskSystem()->ShadowPartitionChanged( 888 partition, NULL, B_PARTITION_INITIALIZE); 889 #endif 890 return B_BAD_VALUE; 891 } 892 893 894 // _user_uninitialize_partition 895 status_t 896 _user_uninitialize_partition(partition_id partitionID, int32* changeCounter) 897 { 898 #if 0 899 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 900 // get the partition 901 KPartition *partition = manager->WriteLockPartition(partitionID); 902 if (!partition) 903 return B_ENTRY_NOT_FOUND; 904 PartitionRegistrar registrar1(partition, true); 905 PartitionRegistrar registrar2(partition->Device(), true); 906 DeviceWriteLocker locker(partition->Device(), true); 907 // unitialize the partition's contents and set the new parameters 908 return partition->UninitializeContents(true); 909 #endif 910 return B_BAD_VALUE; 911 } 912 913 914 // _user_create_child_partition 915 status_t 916 _user_create_child_partition(partition_id partitionID, int32* changeCounter, 917 off_t offset, off_t size, const char* type, const char* name, 918 const char* parameters, size_t parametersSize, partition_id* childID, 919 int32* childChangeCounter) 920 921 { 922 #if 0 923 if (!_type || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) 924 return B_BAD_VALUE; 925 char type[B_DISK_DEVICE_TYPE_LENGTH]; 926 char *parameters = NULL; 927 status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); 928 if (error) 929 return error; 930 if (_parameters) { 931 parameters = static_cast<char*>(malloc(parametersSize)); 932 if (parameters) 933 user_memcpy(parameters, _parameters, parametersSize); 934 else 935 return B_NO_MEMORY; 936 } 937 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 938 // get the partition 939 KPartition *partition = manager->WriteLockPartition(partitionID); 940 error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; 941 if (!error) { 942 PartitionRegistrar registrar1(partition, true); 943 PartitionRegistrar registrar2(partition->Device(), true); 944 DeviceWriteLocker locker(partition->Device(), true); 945 // check the parameters 946 off_t proposedOffset = offset; 947 off_t proposedSize = size; 948 int32 index = 0; 949 error = validate_create_child_partition(partition, changeCounter, 950 &proposedOffset, &proposedSize, type, parameters, &index); 951 if (!error) { 952 error = (proposedOffset == offset && proposedSize == size) 953 ? B_OK : B_BAD_VALUE; 954 if (!error) { 955 // create the child 956 KPartition *child = NULL; 957 error = partition->CreateChild(-1, index, &child); 958 if (!error) { 959 partition->Changed(B_PARTITION_CHANGED_CHILDREN); 960 if (_childID) { 961 partition_id childID = child->ID(); 962 user_memcpy(_childID, &childID, sizeof(childID)); 963 } 964 // set the parameters 965 child->SetOffset(offset); 966 child->SetSize(size); 967 error = child->SetType(type); 968 } 969 if (!error) { 970 error = child->SetParameters(parameters); 971 } 972 if (!error) { 973 // implicit partitioning system changes 974 error = partition->DiskSystem()->ShadowPartitionChanged( 975 partition, child, B_PARTITION_CREATE_CHILD); 976 } 977 } 978 } 979 } 980 free(parameters); 981 return error; 982 #endif 983 return B_BAD_VALUE; 984 } 985 986 987 // _user_delete_child_partition 988 status_t 989 _user_delete_child_partition(partition_id partitionID, int32* changeCounter, 990 partition_id childID, int32 childChangeCounter) 991 { 992 #if 0 993 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 994 // get the partition 995 KPartition *partition = manager->WriteLockPartition(partitionID); 996 if (!partition) 997 return B_ENTRY_NOT_FOUND; 998 PartitionRegistrar registrar1(partition, true); 999 PartitionRegistrar registrar2(partition->Device(), true); 1000 DeviceWriteLocker locker(partition->Device(), true); 1001 // check whether delete the child is OK 1002 status_t error = validate_delete_child_partition(partition, changeCounter); 1003 if (error != B_OK) 1004 return error; 1005 // delete the child 1006 KPartition *parent = partition->Parent(); 1007 if (!parent->RemoveChild(partition)) 1008 return B_ERROR; 1009 parent->Changed(B_PARTITION_CHANGED_CHILDREN); 1010 return B_OK; 1011 #endif 1012 return B_BAD_VALUE; 1013 } 1014