1 // KPartition.cpp 2 3 #include <errno.h> 4 #include <fcntl.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <unistd.h> 8 9 #include <KernelExport.h> 10 #include <Drivers.h> 11 #include <Errors.h> 12 #include <util/kernel_cpp.h> 13 14 #include <ddm_userland_interface.h> 15 #include <KDiskDevice.h> 16 #include <KDiskDeviceManager.h> 17 #include <KDiskDeviceUtils.h> 18 #include <KDiskSystem.h> 19 #include <KPartition.h> 20 #include <KPartitionListener.h> 21 #include <KPartitionVisitor.h> 22 #include <KPath.h> 23 #include <VectorSet.h> 24 25 #include "UserDataWriter.h" 26 27 using namespace std; 28 29 // debugging 30 //#define DBG(x) 31 #define DBG(x) x 32 #define OUT dprintf 33 34 // ListenerSet 35 struct KPartition::ListenerSet : VectorSet<KPartitionListener*> {}; 36 37 // constructor 38 KPartition::KPartition(partition_id id) 39 : fPartitionData(), 40 fChildren(), 41 fDevice(NULL), 42 fParent(NULL), 43 fDiskSystem(NULL), 44 fListeners(NULL), 45 fChangeFlags(0), 46 fChangeCounter(0), 47 fAlgorithmData(0), 48 fReferenceCount(0), 49 fObsolete(false) 50 { 51 fPartitionData.id = (id >= 0 ? id : _NextID()); 52 fPartitionData.offset = 0; 53 fPartitionData.size = 0; 54 fPartitionData.content_size = 0; 55 fPartitionData.block_size = 0; 56 fPartitionData.child_count = 0; 57 fPartitionData.index = -1; 58 fPartitionData.status = B_PARTITION_UNRECOGNIZED; 59 fPartitionData.flags = B_PARTITION_BUSY | B_PARTITION_DESCENDANT_BUSY; 60 fPartitionData.volume = -1; 61 fPartitionData.mount_cookie = NULL; 62 fPartitionData.name = NULL; 63 fPartitionData.content_name = NULL; 64 fPartitionData.type = NULL; 65 fPartitionData.content_type = NULL; 66 fPartitionData.parameters = NULL; 67 fPartitionData.content_parameters = NULL; 68 fPartitionData.cookie = NULL; 69 fPartitionData.content_cookie = NULL; 70 } 71 72 // destructor 73 KPartition::~KPartition() 74 { 75 delete fListeners; 76 SetDiskSystem(NULL); 77 free(fPartitionData.name); 78 free(fPartitionData.content_name); 79 free(fPartitionData.type); 80 free(fPartitionData.parameters); 81 free(fPartitionData.content_parameters); 82 } 83 84 // Register 85 void 86 KPartition::Register() 87 { 88 fReferenceCount++; 89 } 90 91 // Unregister 92 void 93 KPartition::Unregister() 94 { 95 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 96 ManagerLocker locker(manager); 97 fReferenceCount--; 98 if (IsObsolete() && fReferenceCount == 0) { 99 // let the manager delete object 100 manager->DeletePartition(this); 101 } 102 } 103 104 // CountReferences 105 int32 106 KPartition::CountReferences() const 107 { 108 return fReferenceCount; 109 } 110 111 // MarkObsolete 112 void 113 KPartition::MarkObsolete() 114 { 115 fObsolete = true; 116 } 117 118 // IsObsolete 119 bool 120 KPartition::IsObsolete() const 121 { 122 return fObsolete; 123 } 124 125 // PrepareForRemoval 126 bool 127 KPartition::PrepareForRemoval() 128 { 129 bool result = RemoveAllChildren(); 130 UnpublishDevice(); 131 if (ParentDiskSystem()) 132 ParentDiskSystem()->FreeCookie(this); 133 if (DiskSystem()) 134 DiskSystem()->FreeContentCookie(this); 135 return result; 136 } 137 138 // PrepareForDeletion 139 bool 140 KPartition::PrepareForDeletion() 141 { 142 return true; 143 } 144 145 // Open 146 status_t 147 KPartition::Open(int flags, int *fd) 148 { 149 return B_BAD_VALUE; 150 } 151 152 // PublishDevice 153 status_t 154 KPartition::PublishDevice() 155 { 156 // we're just a stupid base class, what do we know? 157 return B_ERROR; 158 } 159 160 // UnpublishDevice 161 status_t 162 KPartition::UnpublishDevice() 163 { 164 return B_ERROR; 165 } 166 167 // SetBusy 168 void 169 KPartition::SetBusy(bool busy) 170 { 171 if (busy) 172 SetFlags(B_PARTITION_BUSY); 173 else 174 ClearFlags(B_PARTITION_BUSY); 175 } 176 177 // IsBusy 178 bool 179 KPartition::IsBusy() const 180 { 181 return (fPartitionData.flags & B_PARTITION_BUSY); 182 } 183 184 // SetDescendantBusy 185 void 186 KPartition::SetDescendantBusy(bool busy) 187 { 188 if (busy) 189 SetFlags(B_PARTITION_DESCENDANT_BUSY); 190 else 191 ClearFlags(B_PARTITION_DESCENDANT_BUSY); 192 } 193 194 // IsDescendantBusy 195 bool 196 KPartition::IsDescendantBusy() const 197 { 198 return (fPartitionData.flags & B_PARTITION_DESCENDANT_BUSY); 199 } 200 201 // SetOffset 202 void 203 KPartition::SetOffset(off_t offset) 204 { 205 if (fPartitionData.offset != offset) { 206 fPartitionData.offset = offset; 207 FireOffsetChanged(offset); 208 } 209 } 210 211 // Offset 212 off_t 213 KPartition::Offset() const 214 { 215 return fPartitionData.offset; 216 } 217 218 // SetSize 219 void 220 KPartition::SetSize(off_t size) 221 { 222 if (fPartitionData.size != size) { 223 fPartitionData.size = size; 224 FireSizeChanged(size); 225 } 226 } 227 228 // Size 229 off_t 230 KPartition::Size() const 231 { 232 return fPartitionData.size; 233 } 234 235 // SetContentSize 236 void 237 KPartition::SetContentSize(off_t size) 238 { 239 if (fPartitionData.content_size != size) { 240 fPartitionData.content_size = size; 241 FireContentSizeChanged(size); 242 } 243 } 244 245 // ContentSize 246 off_t 247 KPartition::ContentSize() const 248 { 249 return fPartitionData.content_size; 250 } 251 252 // SetBlockSize 253 void 254 KPartition::SetBlockSize(uint32 blockSize) 255 { 256 if (fPartitionData.block_size != blockSize) { 257 fPartitionData.block_size = blockSize; 258 FireBlockSizeChanged(blockSize); 259 } 260 } 261 262 // BlockSize 263 uint32 264 KPartition::BlockSize() const 265 { 266 return fPartitionData.block_size; 267 } 268 269 // SetIndex 270 void 271 KPartition::SetIndex(int32 index) 272 { 273 if (fPartitionData.index != index) { 274 fPartitionData.index = index; 275 FireIndexChanged(index); 276 } 277 } 278 279 // Index 280 int32 281 KPartition::Index() const 282 { 283 return fPartitionData.index; 284 } 285 286 // SetStatus 287 void 288 KPartition::SetStatus(uint32 status) 289 { 290 if (fPartitionData.status != status) { 291 fPartitionData.status = status; 292 FireStatusChanged(status); 293 } 294 } 295 296 // Status 297 uint32 298 KPartition::Status() const 299 { 300 return fPartitionData.status; 301 } 302 303 // IsUninitialized 304 bool 305 KPartition::IsUninitialized() const 306 { 307 return (Status() == B_PARTITION_UNINITIALIZED); 308 } 309 310 // SetFlags 311 void 312 KPartition::SetFlags(uint32 flags) 313 { 314 if (fPartitionData.flags != flags) { 315 fPartitionData.flags = flags; 316 FireFlagsChanged(flags); 317 } 318 } 319 320 // AddFlags 321 void 322 KPartition::AddFlags(uint32 flags) 323 { 324 if (~fPartitionData.flags & flags) { 325 fPartitionData.flags |= flags; 326 FireFlagsChanged(fPartitionData.flags); 327 } 328 } 329 330 // ClearFlags 331 void 332 KPartition::ClearFlags(uint32 flags) 333 { 334 if (fPartitionData.flags & flags) { 335 fPartitionData.flags &= ~flags; 336 FireFlagsChanged(fPartitionData.flags); 337 } 338 } 339 340 // Flags 341 uint32 342 KPartition::Flags() const 343 { 344 return fPartitionData.flags; 345 } 346 347 // ContainsFileSystem 348 bool 349 KPartition::ContainsFileSystem() const 350 { 351 return (fPartitionData.flags & B_PARTITION_FILE_SYSTEM); 352 } 353 354 // ContainsPartitioningSystem 355 bool 356 KPartition::ContainsPartitioningSystem() const 357 { 358 return (fPartitionData.flags & B_PARTITION_PARTITIONING_SYSTEM); 359 } 360 361 // IsReadOnly 362 bool 363 KPartition::IsReadOnly() const 364 { 365 return (fPartitionData.flags & B_PARTITION_READ_ONLY); 366 } 367 368 // IsMounted 369 bool 370 KPartition::IsMounted() const 371 { 372 return (fPartitionData.flags & B_PARTITION_MOUNTED); 373 } 374 375 // IsDevice 376 bool 377 KPartition::IsDevice() const 378 { 379 return (fPartitionData.flags & B_PARTITION_IS_DEVICE); 380 } 381 382 // SetName 383 status_t 384 KPartition::SetName(const char *name) 385 { 386 status_t error = set_string(fPartitionData.name, name); 387 FireNameChanged(fPartitionData.name); 388 return error; 389 } 390 391 // Name 392 const char * 393 KPartition::Name() const 394 { 395 return fPartitionData.name; 396 } 397 398 // SetContentName 399 status_t 400 KPartition::SetContentName(const char *name) 401 { 402 status_t error = set_string(fPartitionData.content_name, name); 403 FireContentNameChanged(fPartitionData.content_name); 404 return error; 405 } 406 407 // ContentName 408 const char * 409 KPartition::ContentName() const 410 { 411 return fPartitionData.content_name; 412 } 413 414 // SetType 415 status_t 416 KPartition::SetType(const char *type) 417 { 418 status_t error = set_string(fPartitionData.type, type); 419 FireTypeChanged(fPartitionData.type); 420 return error; 421 } 422 423 // Type 424 const char * 425 KPartition::Type() const 426 { 427 return fPartitionData.type; 428 } 429 430 // ContentType 431 const char * 432 KPartition::ContentType() const 433 { 434 return fPartitionData.content_type; 435 } 436 437 // PartitionData 438 partition_data * 439 KPartition::PartitionData() 440 { 441 return &fPartitionData; 442 } 443 444 // PartitionData 445 const partition_data * 446 KPartition::PartitionData() const 447 { 448 return &fPartitionData; 449 } 450 451 // SetID 452 void 453 KPartition::SetID(partition_id id) 454 { 455 if (fPartitionData.id != id) { 456 fPartitionData.id = id; 457 FireIDChanged(id); 458 } 459 } 460 461 // ID 462 partition_id 463 KPartition::ID() const 464 { 465 return fPartitionData.id; 466 } 467 468 // GetPath 469 status_t 470 KPartition::GetPath(KPath *path) const 471 { 472 // For a KDiskDevice this version is never invoked, so the check for 473 // Parent() is correct. 474 if (!path || path->InitCheck() != B_OK || !Parent() || Index() < 0) 475 return B_BAD_VALUE; 476 // get the parent's path 477 status_t error = Parent()->GetPath(path); 478 if (error != B_OK) 479 return error; 480 if (Parent()->IsDevice()) { 481 // Our parent is a device, so we replace `raw' by our index. 482 const char *leaf = path->Leaf(); 483 if (!leaf || strcmp(leaf, "raw") != B_OK) 484 return B_ERROR; 485 #ifdef _KERNEL_MODE 486 char indexBuffer[12]; 487 snprintf(indexBuffer, sizeof(indexBuffer), "%ld", Index()); 488 #else 489 const char *prefix = "haiku_"; 490 char indexBuffer[strlen(prefix) + 12]; 491 snprintf(indexBuffer, sizeof(indexBuffer), "%s%ld", prefix, 492 Index()); 493 #endif 494 error = path->ReplaceLeaf(indexBuffer); 495 } else { 496 // Our parent is a normal partition, no device: Append our index. 497 char indexBuffer[13]; 498 snprintf(indexBuffer, sizeof(indexBuffer), "_%ld", Index()); 499 error = path->Append(indexBuffer, false); 500 } 501 return error; 502 } 503 504 // SetVolumeID 505 void 506 KPartition::SetVolumeID(dev_t volumeID) 507 { 508 if (fPartitionData.volume != volumeID) { 509 fPartitionData.volume = volumeID; 510 FireVolumeIDChanged(volumeID); 511 if (VolumeID() >= 0) 512 AddFlags(B_PARTITION_MOUNTED); 513 else 514 ClearFlags(B_PARTITION_MOUNTED); 515 } 516 } 517 518 // VolumeID 519 dev_t 520 KPartition::VolumeID() const 521 { 522 return fPartitionData.volume; 523 } 524 525 // SetMountCookie 526 void 527 KPartition::SetMountCookie(void *cookie) 528 { 529 if (fPartitionData.mount_cookie != cookie) { 530 fPartitionData.mount_cookie = cookie; 531 FireMountCookieChanged(cookie); 532 } 533 } 534 535 // MountCookie 536 void * 537 KPartition::MountCookie() const 538 { 539 return fPartitionData.mount_cookie; 540 } 541 542 // Mount 543 status_t 544 KPartition::Mount(uint32 mountFlags, const char *parameters) 545 { 546 // not implemented 547 return B_ERROR; 548 } 549 550 // Unmount 551 status_t 552 KPartition::Unmount() 553 { 554 // not implemented 555 return B_ERROR; 556 } 557 558 // SetParameters 559 status_t 560 KPartition::SetParameters(const char *parameters) 561 { 562 status_t error = set_string(fPartitionData.parameters, parameters); 563 FireParametersChanged(fPartitionData.parameters); 564 return error; 565 } 566 567 // Parameters 568 const char * 569 KPartition::Parameters() const 570 { 571 return fPartitionData.parameters; 572 } 573 574 // SetContentParameters 575 status_t 576 KPartition::SetContentParameters(const char *parameters) 577 { 578 status_t error = set_string(fPartitionData.content_parameters, parameters); 579 FireContentParametersChanged(fPartitionData.content_parameters); 580 return error; 581 } 582 583 // ContentParameters 584 const char * 585 KPartition::ContentParameters() const 586 { 587 return fPartitionData.content_parameters; 588 } 589 590 // SetDevice 591 void 592 KPartition::SetDevice(KDiskDevice *device) 593 { 594 fDevice = device; 595 if (fDevice && fDevice->IsReadOnlyMedia()) 596 AddFlags(B_PARTITION_READ_ONLY); 597 } 598 599 // Device 600 KDiskDevice * 601 KPartition::Device() const 602 { 603 return fDevice; 604 } 605 606 // SetParent 607 void 608 KPartition::SetParent(KPartition *parent) 609 { 610 // Must be called in a {Add,Remove}Child() only! 611 fParent = parent; 612 } 613 614 // Parent 615 KPartition * 616 KPartition::Parent() const 617 { 618 return fParent; 619 } 620 621 // AddChild 622 status_t 623 KPartition::AddChild(KPartition *partition, int32 index) 624 { 625 // check parameters 626 int32 count = fPartitionData.child_count; 627 if (index == -1) 628 index = count; 629 if (index < 0 || index > count || !partition) 630 return B_BAD_VALUE; 631 // add partition 632 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 633 if (ManagerLocker locker = manager) { 634 status_t error = fChildren.Insert(partition, index); 635 if (error != B_OK) 636 return error; 637 if (!manager->PartitionAdded(partition)) { 638 fChildren.Erase(index); 639 return B_NO_MEMORY; 640 } 641 partition->SetIndex(index); 642 _UpdateChildIndices(index); 643 fPartitionData.child_count++; 644 partition->SetParent(this); 645 partition->SetDevice(Device()); 646 // notify listeners 647 FireChildAdded(partition, index); 648 return B_OK; 649 } 650 return B_ERROR; 651 } 652 653 // RemoveChild 654 bool 655 KPartition::RemoveChild(int32 index) 656 { 657 if (index < 0 || index >= fPartitionData.child_count) 658 return false; 659 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 660 if (ManagerLocker locker = manager) { 661 KPartition *partition = fChildren.ElementAt(index); 662 PartitionRegistrar _(partition); 663 if (!partition || !manager->PartitionRemoved(partition) 664 || !fChildren.Erase(index)) { 665 return false; 666 } 667 _UpdateChildIndices(index + 1); 668 partition->SetIndex(-1); 669 fPartitionData.child_count--; 670 partition->SetParent(NULL); 671 partition->SetDevice(NULL); 672 // notify listeners 673 FireChildAdded(partition, index); 674 return true; 675 } 676 return false; 677 } 678 679 // RemoveChild 680 bool 681 KPartition::RemoveChild(KPartition *child) 682 { 683 if (child) { 684 int32 index = fChildren.IndexOf(child); 685 if (index >= 0) 686 return RemoveChild(index); 687 } 688 return false; 689 } 690 691 // RemoveAllChildren 692 bool 693 KPartition::RemoveAllChildren() 694 { 695 int32 count = CountChildren(); 696 for (int32 i = count - 1; i >= 0; i--) { 697 if (!RemoveChild(i)) 698 return false; 699 } 700 return true; 701 } 702 703 // ChildAt 704 KPartition * 705 KPartition::ChildAt(int32 index) const 706 { 707 return (index >= 0 && index < fChildren.Count() 708 ? fChildren.ElementAt(index) : NULL); 709 } 710 711 // CountChildren 712 int32 713 KPartition::CountChildren() const 714 { 715 return fPartitionData.child_count; 716 } 717 718 // CountDescendants 719 int32 720 KPartition::CountDescendants() const 721 { 722 int32 count = 1; 723 for (int32 i = 0; KPartition *child = ChildAt(i); i++) 724 count += child->CountDescendants(); 725 return count; 726 } 727 728 // VisitEachDescendant 729 KPartition * 730 KPartition::VisitEachDescendant(KPartitionVisitor *visitor) 731 { 732 if (!visitor) 733 return NULL; 734 if (visitor->VisitPre(this)) 735 return this; 736 for (int32 i = 0; KPartition *child = ChildAt(i); i++) { 737 if (KPartition *result = child->VisitEachDescendant(visitor)) 738 return result; 739 } 740 if (visitor->VisitPost(this)) 741 return this; 742 return NULL; 743 } 744 745 // CreateShadowPartition 746 status_t 747 KPartition::CreateShadowPartition() 748 { 749 // implemented by derived classes 750 return B_ERROR; 751 } 752 753 // UnsetShadowPartition 754 void 755 KPartition::UnsetShadowPartition(bool doDelete) 756 { 757 // implemented by derived classes 758 } 759 760 // SetDiskSystem 761 void 762 KPartition::SetDiskSystem(KDiskSystem *diskSystem) 763 { 764 // unload former disk system 765 if (fDiskSystem) { 766 fPartitionData.content_type = NULL; 767 fDiskSystem->Unload(); 768 fDiskSystem = NULL; 769 } 770 // set and load new one 771 fDiskSystem = diskSystem; 772 if (fDiskSystem) 773 fDiskSystem->Load(); // can't fail, since it's already loaded 774 // update concerned partition flags 775 if (fDiskSystem) { 776 fPartitionData.content_type = fDiskSystem->PrettyName(); 777 if (fDiskSystem->IsFileSystem()) 778 AddFlags(B_PARTITION_FILE_SYSTEM); 779 else 780 AddFlags(B_PARTITION_PARTITIONING_SYSTEM); 781 } 782 // notify listeners 783 FireDiskSystemChanged(fDiskSystem); 784 } 785 786 // DiskSystem 787 KDiskSystem * 788 KPartition::DiskSystem() const 789 { 790 return fDiskSystem; 791 } 792 793 // ParentDiskSystem 794 KDiskSystem * 795 KPartition::ParentDiskSystem() const 796 { 797 return (Parent() ? Parent()->DiskSystem() : NULL); 798 } 799 800 // SetCookie 801 void 802 KPartition::SetCookie(void *cookie) 803 { 804 if (fPartitionData.cookie != cookie) { 805 fPartitionData.cookie = cookie; 806 FireCookieChanged(cookie); 807 } 808 } 809 810 // Cookie 811 void * 812 KPartition::Cookie() const 813 { 814 return fPartitionData.cookie; 815 } 816 817 // SetContentCookie 818 void 819 KPartition::SetContentCookie(void *cookie) 820 { 821 if (fPartitionData.content_cookie != cookie) { 822 fPartitionData.content_cookie = cookie; 823 FireContentCookieChanged(cookie); 824 } 825 } 826 827 // ContentCookie 828 void * 829 KPartition::ContentCookie() const 830 { 831 return fPartitionData.content_cookie; 832 } 833 834 // AddListener 835 bool 836 KPartition::AddListener(KPartitionListener *listener) 837 { 838 if (!listener) 839 return false; 840 // lazy create listeners 841 if (!fListeners) { 842 fListeners = new(nothrow) ListenerSet; 843 if (!fListeners) 844 return false; 845 } 846 // add listener 847 return (fListeners->Insert(listener) == B_OK); 848 } 849 850 // RemoveListener 851 bool 852 KPartition::RemoveListener(KPartitionListener *listener) 853 { 854 if (!listener || !fListeners) 855 return false; 856 // remove listener and delete the set, if empty now 857 bool result = (fListeners->Remove(listener) > 0); 858 if (fListeners->IsEmpty()) { 859 delete fListeners; 860 fListeners = NULL; 861 } 862 return result; 863 } 864 865 // Changed 866 void 867 KPartition::Changed(uint32 flags, uint32 clearFlags) 868 { 869 fChangeFlags &= ~clearFlags; 870 fChangeFlags |= flags; 871 fChangeCounter++; 872 if (Parent()) 873 Parent()->Changed(B_PARTITION_CHANGED_DESCENDANTS); 874 } 875 876 // SetChangeFlags 877 void 878 KPartition::SetChangeFlags(uint32 flags) 879 { 880 fChangeFlags = flags; 881 } 882 883 // ChangeFlags 884 uint32 885 KPartition::ChangeFlags() const 886 { 887 return fChangeFlags; 888 } 889 890 // ChangeCounter 891 int32 892 KPartition::ChangeCounter() const 893 { 894 return fChangeCounter; 895 } 896 897 // UninitializeContents 898 status_t 899 KPartition::UninitializeContents(bool logChanges) 900 { 901 if (DiskSystem()) { 902 uint32 flags = B_PARTITION_CHANGED_INITIALIZATION 903 | B_PARTITION_CHANGED_CONTENT_TYPE 904 | B_PARTITION_CHANGED_STATUS 905 | B_PARTITION_CHANGED_FLAGS; 906 // children 907 if (CountChildren() > 0) { 908 if (!RemoveAllChildren()) 909 return B_ERROR; 910 flags |= B_PARTITION_CHANGED_CHILDREN; 911 } 912 // volume 913 if (VolumeID() >= 0) { 914 SetVolumeID(-1); 915 flags |= B_PARTITION_CHANGED_VOLUME; 916 } 917 // content name 918 if (ContentName()) { 919 SetContentName(NULL); 920 flags |= B_PARTITION_CHANGED_CONTENT_NAME; 921 } 922 // content parameters 923 if (ContentParameters()) { 924 SetContentParameters(NULL); 925 flags |= B_PARTITION_CHANGED_CONTENT_PARAMETERS; 926 } 927 // content size 928 if (ContentSize() > 0) { 929 SetContentSize(0); 930 flags |= B_PARTITION_CHANGED_CONTENT_SIZE; 931 } 932 // block size 933 if (Parent() && Parent()->BlockSize() != BlockSize()) { 934 SetBlockSize(Parent()->BlockSize()); 935 flags |= B_PARTITION_CHANGED_BLOCK_SIZE; 936 } 937 // disk system 938 DiskSystem()->FreeContentCookie(this); 939 SetDiskSystem(NULL); 940 // status 941 SetStatus(B_PARTITION_UNINITIALIZED); 942 // flags 943 ClearFlags(B_PARTITION_FILE_SYSTEM | B_PARTITION_PARTITIONING_SYSTEM); 944 if (!Device()->IsReadOnlyMedia()) 945 ClearFlags(B_PARTITION_READ_ONLY); 946 // log changes 947 if (logChanges) { 948 Changed(flags, B_PARTITION_CHANGED_DEFRAGMENTATION 949 | B_PARTITION_CHANGED_CHECK 950 | B_PARTITION_CHANGED_REPAIR); 951 } 952 } 953 return B_OK; 954 } 955 956 // SetAlgorithmData 957 void 958 KPartition::SetAlgorithmData(uint32 data) 959 { 960 fAlgorithmData = data; 961 } 962 963 // AlgorithmData 964 uint32 965 KPartition::AlgorithmData() const 966 { 967 return fAlgorithmData; 968 } 969 970 // WriteUserData 971 void 972 KPartition::WriteUserData(UserDataWriter &writer, user_partition_data *data) 973 { 974 // allocate 975 char *name = writer.PlaceString(Name()); 976 char *contentName = writer.PlaceString(ContentName()); 977 char *type = writer.PlaceString(Type()); 978 char *contentType = writer.PlaceString(ContentType()); 979 char *parameters = writer.PlaceString(Parameters()); 980 char *contentParameters = writer.PlaceString(ContentParameters()); 981 // fill in data 982 if (data) { 983 data->id = ID(); 984 data->shadow_id = -1; 985 data->offset = Offset(); 986 data->size = Size(); 987 data->content_size = ContentSize(); 988 data->block_size = BlockSize(); 989 data->status = Status(); 990 data->flags = Flags(); 991 data->volume = VolumeID(); 992 data->index = Index(); 993 data->change_counter = ChangeCounter(); 994 data->disk_system = (DiskSystem() ? DiskSystem()->ID() : -1); 995 data->name = name; 996 data->content_name = contentName; 997 data->type = type; 998 data->content_type = contentType; 999 data->parameters = parameters; 1000 data->content_parameters = contentParameters; 1001 data->child_count = CountChildren(); 1002 // make buffer relocatable 1003 writer.AddRelocationEntry(&data->name); 1004 writer.AddRelocationEntry(&data->content_name); 1005 writer.AddRelocationEntry(&data->type); 1006 writer.AddRelocationEntry(&data->content_type); 1007 writer.AddRelocationEntry(&data->parameters); 1008 writer.AddRelocationEntry(&data->content_parameters); 1009 } 1010 // children 1011 for (int32 i = 0; KPartition *child = ChildAt(i); i++) { 1012 user_partition_data *childData 1013 = writer.AllocatePartitionData(child->CountChildren()); 1014 if (data) { 1015 data->children[i] = childData; 1016 writer.AddRelocationEntry(&data->children[i]); 1017 } 1018 child->WriteUserData(writer, childData); 1019 } 1020 } 1021 1022 // Dump 1023 void 1024 KPartition::Dump(bool deep, int32 level) 1025 { 1026 if (level < 0 || level > 255) 1027 return; 1028 char prefix[256]; 1029 sprintf(prefix, "%*s%*s", (int)level, "", (int)level, ""); 1030 KPath path; 1031 GetPath(&path); 1032 if (level > 0) 1033 OUT("%spartition %ld: %s\n", prefix, ID(), path.Path()); 1034 OUT("%s offset: %lld\n", prefix, Offset()); 1035 OUT("%s size: %lld (%.2f MB)\n", prefix, Size(), Size() / (1024.0*1024)); 1036 OUT("%s content size: %lld\n", prefix, ContentSize()); 1037 OUT("%s block size: %lu\n", prefix, BlockSize()); 1038 OUT("%s child count: %ld\n", prefix, CountChildren()); 1039 OUT("%s index: %ld\n", prefix, Index()); 1040 OUT("%s status: %lu\n", prefix, Status()); 1041 OUT("%s flags: %lx\n", prefix, Flags()); 1042 OUT("%s volume: %ld\n", prefix, VolumeID()); 1043 OUT("%s disk system: %s\n", prefix, 1044 (DiskSystem() ? DiskSystem()->Name() : NULL)); 1045 OUT("%s name: %s\n", prefix, Name()); 1046 OUT("%s content name: %s\n", prefix, ContentName()); 1047 OUT("%s type: %s\n", prefix, Type()); 1048 OUT("%s content type: %s\n", prefix, ContentType()); 1049 OUT("%s params: %s\n", prefix, Parameters()); 1050 OUT("%s content params: %s\n", prefix, ContentParameters()); 1051 if (deep) { 1052 for (int32 i = 0; KPartition *child = ChildAt(i); i++) 1053 child->Dump(true, level + 1); 1054 } 1055 } 1056 1057 // FireOffsetChanged 1058 void 1059 KPartition::FireOffsetChanged(off_t offset) 1060 { 1061 if (fListeners) { 1062 for (ListenerSet::Iterator it = fListeners->Begin(); 1063 it != fListeners->End(); ++it) { 1064 (*it)->OffsetChanged(this, offset); 1065 } 1066 } 1067 } 1068 1069 // FireSizeChanged 1070 void 1071 KPartition::FireSizeChanged(off_t size) 1072 { 1073 if (fListeners) { 1074 for (ListenerSet::Iterator it = fListeners->Begin(); 1075 it != fListeners->End(); ++it) { 1076 (*it)->SizeChanged(this, size); 1077 } 1078 } 1079 } 1080 1081 // FireContentSizeChanged 1082 void 1083 KPartition::FireContentSizeChanged(off_t size) 1084 { 1085 if (fListeners) { 1086 for (ListenerSet::Iterator it = fListeners->Begin(); 1087 it != fListeners->End(); ++it) { 1088 (*it)->ContentSizeChanged(this, size); 1089 } 1090 } 1091 } 1092 1093 // FireBlockSizeChanged 1094 void 1095 KPartition::FireBlockSizeChanged(uint32 blockSize) 1096 { 1097 if (fListeners) { 1098 for (ListenerSet::Iterator it = fListeners->Begin(); 1099 it != fListeners->End(); ++it) { 1100 (*it)->BlockSizeChanged(this, blockSize); 1101 } 1102 } 1103 } 1104 1105 // FireIndexChanged 1106 void 1107 KPartition::FireIndexChanged(int32 index) 1108 { 1109 if (fListeners) { 1110 for (ListenerSet::Iterator it = fListeners->Begin(); 1111 it != fListeners->End(); ++it) { 1112 (*it)->IndexChanged(this, index); 1113 } 1114 } 1115 } 1116 1117 // FireStatusChanged 1118 void 1119 KPartition::FireStatusChanged(uint32 status) 1120 { 1121 if (fListeners) { 1122 for (ListenerSet::Iterator it = fListeners->Begin(); 1123 it != fListeners->End(); ++it) { 1124 (*it)->StatusChanged(this, status); 1125 } 1126 } 1127 } 1128 1129 // FireFlagsChanged 1130 void 1131 KPartition::FireFlagsChanged(uint32 flags) 1132 { 1133 if (fListeners) { 1134 for (ListenerSet::Iterator it = fListeners->Begin(); 1135 it != fListeners->End(); ++it) { 1136 (*it)->FlagsChanged(this, flags); 1137 } 1138 } 1139 } 1140 1141 // FireNameChanged 1142 void 1143 KPartition::FireNameChanged(const char *name) 1144 { 1145 if (fListeners) { 1146 for (ListenerSet::Iterator it = fListeners->Begin(); 1147 it != fListeners->End(); ++it) { 1148 (*it)->NameChanged(this, name); 1149 } 1150 } 1151 } 1152 1153 // FireContentNameChanged 1154 void 1155 KPartition::FireContentNameChanged(const char *name) 1156 { 1157 if (fListeners) { 1158 for (ListenerSet::Iterator it = fListeners->Begin(); 1159 it != fListeners->End(); ++it) { 1160 (*it)->ContentNameChanged(this, name); 1161 } 1162 } 1163 } 1164 1165 // FireTypeChanged 1166 void 1167 KPartition::FireTypeChanged(const char *type) 1168 { 1169 if (fListeners) { 1170 for (ListenerSet::Iterator it = fListeners->Begin(); 1171 it != fListeners->End(); ++it) { 1172 (*it)->TypeChanged(this, type); 1173 } 1174 } 1175 } 1176 1177 // FireIDChanged 1178 void 1179 KPartition::FireIDChanged(partition_id id) 1180 { 1181 if (fListeners) { 1182 for (ListenerSet::Iterator it = fListeners->Begin(); 1183 it != fListeners->End(); ++it) { 1184 (*it)->IDChanged(this, id); 1185 } 1186 } 1187 } 1188 1189 // FireVolumeIDChanged 1190 void 1191 KPartition::FireVolumeIDChanged(dev_t volumeID) 1192 { 1193 if (fListeners) { 1194 for (ListenerSet::Iterator it = fListeners->Begin(); 1195 it != fListeners->End(); ++it) { 1196 (*it)->VolumeIDChanged(this, volumeID); 1197 } 1198 } 1199 } 1200 1201 // FireMountCookieChanged 1202 void 1203 KPartition::FireMountCookieChanged(void *cookie) 1204 { 1205 if (fListeners) { 1206 for (ListenerSet::Iterator it = fListeners->Begin(); 1207 it != fListeners->End(); ++it) { 1208 (*it)->MountCookieChanged(this, cookie); 1209 } 1210 } 1211 } 1212 1213 // FireParametersChanged 1214 void 1215 KPartition::FireParametersChanged(const char *parameters) 1216 { 1217 if (fListeners) { 1218 for (ListenerSet::Iterator it = fListeners->Begin(); 1219 it != fListeners->End(); ++it) { 1220 (*it)->ParametersChanged(this, parameters); 1221 } 1222 } 1223 } 1224 1225 // FireContentParametersChanged 1226 void 1227 KPartition::FireContentParametersChanged(const char *parameters) 1228 { 1229 if (fListeners) { 1230 for (ListenerSet::Iterator it = fListeners->Begin(); 1231 it != fListeners->End(); ++it) { 1232 (*it)->ContentParametersChanged(this, parameters); 1233 } 1234 } 1235 } 1236 1237 // FireChildAdded 1238 void 1239 KPartition::FireChildAdded(KPartition *child, int32 index) 1240 { 1241 if (fListeners) { 1242 for (ListenerSet::Iterator it = fListeners->Begin(); 1243 it != fListeners->End(); ++it) { 1244 (*it)->ChildAdded(this, child, index); 1245 } 1246 } 1247 } 1248 1249 // FireChildRemoved 1250 void 1251 KPartition::FireChildRemoved(KPartition *child, int32 index) 1252 { 1253 if (fListeners) { 1254 for (ListenerSet::Iterator it = fListeners->Begin(); 1255 it != fListeners->End(); ++it) { 1256 (*it)->ChildRemoved(this, child, index); 1257 } 1258 } 1259 } 1260 1261 // FireDiskSystemChanged 1262 void 1263 KPartition::FireDiskSystemChanged(KDiskSystem *diskSystem) 1264 { 1265 if (fListeners) { 1266 for (ListenerSet::Iterator it = fListeners->Begin(); 1267 it != fListeners->End(); ++it) { 1268 (*it)->DiskSystemChanged(this, diskSystem); 1269 } 1270 } 1271 } 1272 1273 // FireCookieChanged 1274 void 1275 KPartition::FireCookieChanged(void *cookie) 1276 { 1277 if (fListeners) { 1278 for (ListenerSet::Iterator it = fListeners->Begin(); 1279 it != fListeners->End(); ++it) { 1280 (*it)->CookieChanged(this, cookie); 1281 } 1282 } 1283 } 1284 1285 // FireContentCookieChanged 1286 void 1287 KPartition::FireContentCookieChanged(void *cookie) 1288 { 1289 if (fListeners) { 1290 for (ListenerSet::Iterator it = fListeners->Begin(); 1291 it != fListeners->End(); ++it) { 1292 (*it)->ContentCookieChanged(this, cookie); 1293 } 1294 } 1295 } 1296 1297 // _UpdateChildIndices 1298 void 1299 KPartition::_UpdateChildIndices(int32 index) 1300 { 1301 for (int32 i = index; i < fChildren.Count(); i++) 1302 fChildren.ElementAt(i)->SetIndex(i); 1303 } 1304 1305 // _NextID 1306 int32 1307 KPartition::_NextID() 1308 { 1309 return atomic_add(&fNextID, 1); 1310 } 1311 1312 1313 // fNextID 1314 int32 KPartition::fNextID = 0; 1315 1316