2 * Copyright 2009, Bryce Groff, bgroff@hawaii.edu.
3 * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de.
4 * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
6 * Distributed under the terms of the MIT License.
10 #include <KPartition.h>
18 #include <DiskDeviceRoster.h>
21 #include <fs_volume.h>
22 #include <KernelExport.h>
24 #include <ddm_userland_interface.h>
26 #include <KDiskDevice.h>
27 #include <KDiskDeviceManager.h>
28 #include <KDiskDeviceUtils.h>
29 #include <KDiskSystem.h>
30 #include <KPartitionListener.h>
31 #include <KPartitionVisitor.h>
33 #include <util/kernel_cpp.h>
34 #include <VectorSet.h>
37 #include "UserDataWriter.h"
49 struct KPartition::ListenerSet
: VectorSet
<KPartitionListener
*> {};
52 int32
KPartition::sNextID
= 0;
55 KPartition::KPartition(partition_id id
)
62 fDiskSystemPriority(-1),
71 fPartitionData
.id
= id
>= 0 ? id
: _NextID();
72 fPartitionData
.offset
= 0;
73 fPartitionData
.size
= 0;
74 fPartitionData
.content_size
= 0;
75 fPartitionData
.block_size
= 0;
76 fPartitionData
.child_count
= 0;
77 fPartitionData
.index
= -1;
78 fPartitionData
.status
= B_PARTITION_UNRECOGNIZED
;
79 fPartitionData
.flags
= B_PARTITION_BUSY
;
80 fPartitionData
.volume
= -1;
81 fPartitionData
.mount_cookie
= NULL
;
82 fPartitionData
.name
= NULL
;
83 fPartitionData
.content_name
= NULL
;
84 fPartitionData
.type
= NULL
;
85 fPartitionData
.content_type
= NULL
;
86 fPartitionData
.parameters
= NULL
;
87 fPartitionData
.content_parameters
= NULL
;
88 fPartitionData
.cookie
= NULL
;
89 fPartitionData
.content_cookie
= NULL
;
93 KPartition::~KPartition()
97 free(fPartitionData
.name
);
98 free(fPartitionData
.content_name
);
99 free(fPartitionData
.type
);
100 free(fPartitionData
.parameters
);
101 free(fPartitionData
.content_parameters
);
106 KPartition::Register()
113 KPartition::Unregister()
115 KDiskDeviceManager
* manager
= KDiskDeviceManager::Default();
116 ManagerLocker
locker(manager
);
118 if (IsObsolete() && fReferenceCount
== 0) {
119 // let the manager delete object
120 manager
->DeletePartition(this);
126 KPartition::CountReferences() const
128 return fReferenceCount
;
133 KPartition::MarkObsolete()
140 KPartition::IsObsolete() const
147 KPartition::PrepareForRemoval()
149 bool result
= RemoveAllChildren();
150 UninitializeContents();
152 if (ParentDiskSystem())
153 ParentDiskSystem()->FreeCookie(this);
155 DiskSystem()->FreeContentCookie(this);
161 KPartition::PrepareForDeletion()
168 KPartition::Open(int flags
, int* fd
)
175 status_t error
= GetPath(&path
);
180 *fd
= open(path
.Path(), flags
);
189 KPartition::PublishDevice()
194 // get the name to publish
195 char buffer
[B_FILE_NAME_LENGTH
];
196 status_t error
= GetFileName(buffer
, B_FILE_NAME_LENGTH
);
200 // prepare a partition_info
202 info
.offset
= Offset();
204 info
.logical_block_size
= BlockSize();
206 info
.partition
= ID();
207 if (strlcpy(info
.device
, Device()->Path(), sizeof(info
.device
))
208 >= sizeof(info
.device
)) {
209 return B_NAME_TOO_LONG
;
212 fPublishedName
= strdup(buffer
);
216 error
= devfs_publish_partition(buffer
, &info
);
218 dprintf("KPartition::PublishDevice(): Failed to publish partition "
219 "%" B_PRId32
": %s\n", ID(), strerror(error
));
220 free(fPublishedName
);
221 fPublishedName
= NULL
;
230 KPartition::UnpublishDevice()
237 status_t error
= GetPath(&path
);
239 dprintf("KPartition::UnpublishDevice(): Failed to get path for "
240 "partition %" B_PRId32
": %s\n", ID(), strerror(error
));
244 error
= devfs_unpublish_partition(path
.Path());
246 dprintf("KPartition::UnpublishDevice(): Failed to unpublish partition "
247 "%" B_PRId32
": %s\n", ID(), strerror(error
));
250 free(fPublishedName
);
251 fPublishedName
= NULL
;
258 KPartition::RepublishDevice()
263 char newNameBuffer
[B_FILE_NAME_LENGTH
];
264 status_t error
= GetFileName(newNameBuffer
, B_FILE_NAME_LENGTH
);
270 if (strcmp(fPublishedName
, newNameBuffer
) == 0)
273 for (int i
= 0; i
< CountChildren(); i
++)
274 ChildAt(i
)->RepublishDevice();
276 char* newName
= strdup(newNameBuffer
);
282 error
= devfs_rename_partition(Device()->Path(), fPublishedName
, newName
);
287 dprintf("KPartition::RepublishDevice(): Failed to republish partition "
288 "%" B_PRId32
": %s\n", ID(), strerror(error
));
292 free(fPublishedName
);
293 fPublishedName
= newName
;
300 KPartition::IsPublished() const
302 return fPublishedName
!= NULL
;
307 KPartition::SetBusy(bool busy
)
310 AddFlags(B_PARTITION_BUSY
);
312 ClearFlags(B_PARTITION_BUSY
);
317 KPartition::IsBusy() const
319 return (fPartitionData
.flags
& B_PARTITION_BUSY
) != 0;
324 KPartition::IsBusy(bool includeDescendants
)
326 if (!includeDescendants
)
329 struct IsBusyVisitor
: KPartitionVisitor
{
330 virtual bool VisitPre(KPartition
* partition
)
332 return partition
->IsBusy();
336 return VisitEachDescendant(&checkVisitor
) != NULL
;
341 KPartition::CheckAndMarkBusy(bool includeDescendants
)
343 if (IsBusy(includeDescendants
))
346 MarkBusy(includeDescendants
);
353 KPartition::MarkBusy(bool includeDescendants
)
355 if (includeDescendants
) {
356 struct MarkBusyVisitor
: KPartitionVisitor
{
357 virtual bool VisitPre(KPartition
* partition
)
359 partition
->AddFlags(B_PARTITION_BUSY
);
364 VisitEachDescendant(&markVisitor
);
371 KPartition::UnmarkBusy(bool includeDescendants
)
373 if (includeDescendants
) {
374 struct UnmarkBusyVisitor
: KPartitionVisitor
{
375 virtual bool VisitPre(KPartition
* partition
)
377 partition
->ClearFlags(B_PARTITION_BUSY
);
382 VisitEachDescendant(&visitor
);
389 KPartition::SetOffset(off_t offset
)
391 if (fPartitionData
.offset
!= offset
) {
392 fPartitionData
.offset
= offset
;
393 FireOffsetChanged(offset
);
399 KPartition::Offset() const
401 return fPartitionData
.offset
;
406 KPartition::SetSize(off_t size
)
408 if (fPartitionData
.size
!= size
) {
409 fPartitionData
.size
= size
;
410 FireSizeChanged(size
);
416 KPartition::Size() const
418 return fPartitionData
.size
;
423 KPartition::SetContentSize(off_t size
)
425 if (fPartitionData
.content_size
!= size
) {
426 fPartitionData
.content_size
= size
;
427 FireContentSizeChanged(size
);
433 KPartition::ContentSize() const
435 return fPartitionData
.content_size
;
440 KPartition::SetBlockSize(uint32 blockSize
)
442 if (fPartitionData
.block_size
!= blockSize
) {
443 fPartitionData
.block_size
= blockSize
;
444 FireBlockSizeChanged(blockSize
);
450 KPartition::BlockSize() const
452 return fPartitionData
.block_size
;
457 KPartition::SetIndex(int32 index
)
459 if (fPartitionData
.index
!= index
) {
460 fPartitionData
.index
= index
;
461 FireIndexChanged(index
);
467 KPartition::Index() const
469 return fPartitionData
.index
;
474 KPartition::SetStatus(uint32 status
)
476 if (fPartitionData
.status
!= status
) {
477 fPartitionData
.status
= status
;
478 FireStatusChanged(status
);
484 KPartition::Status() const
486 return fPartitionData
.status
;
491 KPartition::IsUninitialized() const
493 return Status() == B_PARTITION_UNINITIALIZED
;
498 KPartition::SetFlags(uint32 flags
)
500 if (fPartitionData
.flags
!= flags
) {
501 fPartitionData
.flags
= flags
;
502 FireFlagsChanged(flags
);
508 KPartition::AddFlags(uint32 flags
)
510 if (~fPartitionData
.flags
& flags
) {
511 fPartitionData
.flags
|= flags
;
512 FireFlagsChanged(fPartitionData
.flags
);
518 KPartition::ClearFlags(uint32 flags
)
520 if (fPartitionData
.flags
& flags
) {
521 fPartitionData
.flags
&= ~flags
;
522 FireFlagsChanged(fPartitionData
.flags
);
528 KPartition::Flags() const
530 return fPartitionData
.flags
;
535 KPartition::ContainsFileSystem() const
537 return (fPartitionData
.flags
& B_PARTITION_FILE_SYSTEM
) != 0;
542 KPartition::ContainsPartitioningSystem() const
544 return (fPartitionData
.flags
& B_PARTITION_PARTITIONING_SYSTEM
) != 0;
549 KPartition::IsReadOnly() const
551 return (fPartitionData
.flags
& B_PARTITION_READ_ONLY
) != 0;
556 KPartition::IsMounted() const
558 return (fPartitionData
.flags
& B_PARTITION_MOUNTED
) != 0;
563 KPartition::IsChildMounted()
565 struct IsMountedVisitor
: KPartitionVisitor
{
566 virtual bool VisitPre(KPartition
* partition
)
568 return partition
->IsMounted();
572 return VisitEachDescendant(&checkVisitor
) != NULL
;
577 KPartition::IsDevice() const
579 return (fPartitionData
.flags
& B_PARTITION_IS_DEVICE
) != 0;
584 KPartition::SetName(const char* name
)
586 status_t error
= set_string(fPartitionData
.name
, name
);
587 FireNameChanged(fPartitionData
.name
);
593 KPartition::Name() const
595 return fPartitionData
.name
;
600 KPartition::SetContentName(const char* name
)
602 status_t error
= set_string(fPartitionData
.content_name
, name
);
603 FireContentNameChanged(fPartitionData
.content_name
);
609 KPartition::ContentName() const
611 return fPartitionData
.content_name
;
616 KPartition::SetType(const char* type
)
618 status_t error
= set_string(fPartitionData
.type
, type
);
619 FireTypeChanged(fPartitionData
.type
);
625 KPartition::Type() const
627 return fPartitionData
.type
;
632 KPartition::ContentType() const
634 return fPartitionData
.content_type
;
639 KPartition::PartitionData()
641 return &fPartitionData
;
645 const partition_data
*
646 KPartition::PartitionData() const
648 return &fPartitionData
;
653 KPartition::SetID(partition_id id
)
655 if (fPartitionData
.id
!= id
) {
656 fPartitionData
.id
= id
;
663 KPartition::ID() const
665 return fPartitionData
.id
;
670 KPartition::GetFileName(char* buffer
, size_t size
) const
672 // If the parent is the device, the name is the index of the partition.
673 if (Parent() == NULL
|| Parent()->IsDevice()) {
674 if (snprintf(buffer
, size
, "%" B_PRId32
, Index()) >= (int)size
)
675 return B_NAME_TOO_LONG
;
679 // The partition has a non-device parent, so we append the index to the
680 // parent partition's name.
681 status_t error
= Parent()->GetFileName(buffer
, size
);
685 size_t len
= strlen(buffer
);
686 if (snprintf(buffer
+ len
, size
- len
, "_%" B_PRId32
, Index()) >= int(size
- len
))
687 return B_NAME_TOO_LONG
;
693 KPartition::GetPath(KPath
* path
) const
695 // For a KDiskDevice this version is never invoked, so the check for
696 // Parent() is correct.
697 if (!path
|| path
->InitCheck() != B_OK
|| !Parent() || Index() < 0)
700 // init the path with the device path
701 status_t error
= path
->SetPath(Device()->Path());
705 // replace the leaf name with the partition's file name
706 char name
[B_FILE_NAME_LENGTH
];
707 error
= GetFileName(name
, sizeof(name
));
709 error
= path
->ReplaceLeaf(name
);
716 KPartition::SetVolumeID(dev_t volumeID
)
718 if (fPartitionData
.volume
== volumeID
)
721 fPartitionData
.volume
= volumeID
;
722 FireVolumeIDChanged(volumeID
);
724 AddFlags(B_PARTITION_MOUNTED
);
726 ClearFlags(B_PARTITION_MOUNTED
);
728 KDiskDeviceManager
* manager
= KDiskDeviceManager::Default();
730 char messageBuffer
[512];
732 message
.SetTo(messageBuffer
, sizeof(messageBuffer
), B_DEVICE_UPDATE
);
733 message
.AddInt32("event", volumeID
>= 0
734 ? B_DEVICE_PARTITION_MOUNTED
: B_DEVICE_PARTITION_UNMOUNTED
);
735 message
.AddInt32("id", ID());
737 message
.AddInt32("volume", volumeID
);
739 manager
->Notify(message
, B_DEVICE_REQUEST_MOUNTING
);
744 KPartition::VolumeID() const
746 return fPartitionData
.volume
;
751 KPartition::SetMountCookie(void* cookie
)
753 if (fPartitionData
.mount_cookie
!= cookie
) {
754 fPartitionData
.mount_cookie
= cookie
;
755 FireMountCookieChanged(cookie
);
761 KPartition::MountCookie() const
763 return fPartitionData
.mount_cookie
;
768 KPartition::Mount(uint32 mountFlags
, const char* parameters
)
776 KPartition::Unmount()
784 KPartition::SetParameters(const char* parameters
)
786 status_t error
= set_string(fPartitionData
.parameters
, parameters
);
787 FireParametersChanged(fPartitionData
.parameters
);
793 KPartition::Parameters() const
795 return fPartitionData
.parameters
;
800 KPartition::SetContentParameters(const char* parameters
)
802 status_t error
= set_string(fPartitionData
.content_parameters
, parameters
);
803 FireContentParametersChanged(fPartitionData
.content_parameters
);
809 KPartition::ContentParameters() const
811 return fPartitionData
.content_parameters
;
816 KPartition::SetDevice(KDiskDevice
* device
)
819 if (fDevice
!= NULL
&& fDevice
->IsReadOnlyMedia())
820 AddFlags(B_PARTITION_READ_ONLY
);
825 KPartition::Device() const
832 KPartition::SetParent(KPartition
* parent
)
834 // Must be called in a {Add,Remove}Child() only!
840 KPartition::Parent() const
847 KPartition::AddChild(KPartition
* partition
, int32 index
)
850 int32 count
= fPartitionData
.child_count
;
853 if (index
< 0 || index
> count
|| !partition
)
857 KDiskDeviceManager
* manager
= KDiskDeviceManager::Default();
858 if (ManagerLocker locker
= manager
) {
859 status_t error
= fChildren
.Insert(partition
, index
);
862 if (!manager
->PartitionAdded(partition
)) {
863 fChildren
.Erase(index
);
866 // update siblings index's
867 partition
->SetIndex(index
);
868 _UpdateChildIndices(count
, index
);
869 fPartitionData
.child_count
++;
871 partition
->SetParent(this);
872 partition
->SetDevice(Device());
875 partition
->PublishDevice();
878 FireChildAdded(partition
, index
);
886 KPartition::CreateChild(partition_id id
, int32 index
, off_t offset
, off_t size
,
890 int32 count
= fPartitionData
.child_count
;
893 if (index
< 0 || index
> count
)
896 // create and add partition
897 KPartition
* child
= new(std::nothrow
) KPartition(id
);
901 child
->SetOffset(offset
);
902 child
->SetSize(size
);
904 status_t error
= AddChild(child
, index
);
906 // cleanup / set result
917 KPartition::RemoveChild(int32 index
)
919 if (index
< 0 || index
>= fPartitionData
.child_count
)
922 KDiskDeviceManager
* manager
= KDiskDeviceManager::Default();
923 if (ManagerLocker locker
= manager
) {
924 KPartition
* partition
= fChildren
.ElementAt(index
);
925 PartitionRegistrar
_(partition
);
926 if (!partition
|| !manager
->PartitionRemoved(partition
)
927 || !fChildren
.Erase(index
)) {
930 _UpdateChildIndices(index
, fChildren
.Count());
931 partition
->SetIndex(-1);
932 fPartitionData
.child_count
--;
933 partition
->SetParent(NULL
);
934 partition
->SetDevice(NULL
);
936 FireChildRemoved(partition
, index
);
944 KPartition::RemoveChild(KPartition
* child
)
947 int32 index
= fChildren
.IndexOf(child
);
949 return RemoveChild(index
);
956 KPartition::RemoveAllChildren()
958 int32 count
= CountChildren();
959 for (int32 i
= count
- 1; i
>= 0; i
--) {
968 KPartition::ChildAt(int32 index
) const
970 return index
>= 0 && index
< fChildren
.Count()
971 ? fChildren
.ElementAt(index
) : NULL
;
976 KPartition::CountChildren() const
978 return fPartitionData
.child_count
;
983 KPartition::CountDescendants() const
986 for (int32 i
= 0; KPartition
* child
= ChildAt(i
); i
++)
987 count
+= child
->CountDescendants();
993 KPartition::VisitEachDescendant(KPartitionVisitor
* visitor
)
997 if (visitor
->VisitPre(this))
999 for (int32 i
= 0; KPartition
* child
= ChildAt(i
); i
++) {
1000 if (KPartition
* result
= child
->VisitEachDescendant(visitor
))
1003 if (visitor
->VisitPost(this))
1010 KPartition::SetDiskSystem(KDiskSystem
* diskSystem
, float priority
)
1012 // unload former disk system
1014 fPartitionData
.content_type
= NULL
;
1015 fDiskSystem
->Unload();
1017 fDiskSystemPriority
= -1;
1019 // set and load new one
1020 fDiskSystem
= diskSystem
;
1022 fDiskSystem
->Load();
1023 // can't fail, since it's already loaded
1025 // update concerned partition flags
1027 fPartitionData
.content_type
= fDiskSystem
->PrettyName();
1028 fDiskSystemPriority
= priority
;
1029 if (fDiskSystem
->IsFileSystem())
1030 AddFlags(B_PARTITION_FILE_SYSTEM
);
1032 AddFlags(B_PARTITION_PARTITIONING_SYSTEM
);
1035 FireDiskSystemChanged(fDiskSystem
);
1037 KDiskDeviceManager
* manager
= KDiskDeviceManager::Default();
1039 char messageBuffer
[512];
1041 message
.SetTo(messageBuffer
, sizeof(messageBuffer
), B_DEVICE_UPDATE
);
1042 message
.AddInt32("event", B_DEVICE_PARTITION_INITIALIZED
);
1043 message
.AddInt32("id", ID());
1045 manager
->Notify(message
, B_DEVICE_REQUEST_PARTITION
);
1050 KPartition::DiskSystem() const
1057 KPartition::DiskSystemPriority() const
1059 return fDiskSystemPriority
;
1064 KPartition::ParentDiskSystem() const
1066 return Parent() ? Parent()->DiskSystem() : NULL
;
1071 KPartition::SetCookie(void* cookie
)
1073 if (fPartitionData
.cookie
!= cookie
) {
1074 fPartitionData
.cookie
= cookie
;
1075 FireCookieChanged(cookie
);
1081 KPartition::Cookie() const
1083 return fPartitionData
.cookie
;
1088 KPartition::SetContentCookie(void* cookie
)
1090 if (fPartitionData
.content_cookie
!= cookie
) {
1091 fPartitionData
.content_cookie
= cookie
;
1092 FireContentCookieChanged(cookie
);
1098 KPartition::ContentCookie() const
1100 return fPartitionData
.content_cookie
;
1105 KPartition::AddListener(KPartitionListener
* listener
)
1109 // lazy create listeners
1111 fListeners
= new(nothrow
) ListenerSet
;
1116 return fListeners
->Insert(listener
) == B_OK
;
1121 KPartition::RemoveListener(KPartitionListener
* listener
)
1123 if (!listener
|| !fListeners
)
1125 // remove listener and delete the set, if empty now
1126 bool result
= (fListeners
->Remove(listener
) > 0);
1127 if (fListeners
->IsEmpty()) {
1136 KPartition::Changed(uint32 flags
, uint32 clearFlags
)
1138 fChangeFlags
&= ~clearFlags
;
1139 fChangeFlags
|= flags
;
1142 Parent()->Changed(B_PARTITION_CHANGED_DESCENDANTS
);
1147 KPartition::SetChangeFlags(uint32 flags
)
1149 fChangeFlags
= flags
;
1154 KPartition::ChangeFlags() const
1156 return fChangeFlags
;
1161 KPartition::ChangeCounter() const
1163 return fChangeCounter
;
1168 KPartition::UninitializeContents(bool logChanges
)
1171 uint32 flags
= B_PARTITION_CHANGED_INITIALIZATION
1172 | B_PARTITION_CHANGED_CONTENT_TYPE
1173 | B_PARTITION_CHANGED_STATUS
1174 | B_PARTITION_CHANGED_FLAGS
;
1177 if (CountChildren() > 0) {
1178 if (!RemoveAllChildren())
1180 flags
|= B_PARTITION_CHANGED_CHILDREN
;
1184 if (VolumeID() >= 0) {
1185 status_t error
= vfs_unmount(VolumeID(),
1186 B_FORCE_UNMOUNT
| B_UNMOUNT_BUSY_PARTITION
);
1187 if (error
!= B_OK
) {
1188 dprintf("KPartition::UninitializeContents(): Failed to unmount "
1189 "device %" B_PRIdDEV
": %s\n", VolumeID(), strerror(error
));
1193 flags
|= B_PARTITION_CHANGED_VOLUME
;
1197 if (ContentName()) {
1198 SetContentName(NULL
);
1199 flags
|= B_PARTITION_CHANGED_CONTENT_NAME
;
1202 // content parameters
1203 if (ContentParameters()) {
1204 SetContentParameters(NULL
);
1205 flags
|= B_PARTITION_CHANGED_CONTENT_PARAMETERS
;
1209 if (ContentSize() > 0) {
1211 flags
|= B_PARTITION_CHANGED_CONTENT_SIZE
;
1215 if (Parent() && Parent()->BlockSize() != BlockSize()) {
1216 SetBlockSize(Parent()->BlockSize());
1217 flags
|= B_PARTITION_CHANGED_BLOCK_SIZE
;
1221 DiskSystem()->FreeContentCookie(this);
1222 SetDiskSystem(NULL
);
1225 SetStatus(B_PARTITION_UNINITIALIZED
);
1228 ClearFlags(B_PARTITION_FILE_SYSTEM
| B_PARTITION_PARTITIONING_SYSTEM
);
1229 if (!Device()->IsReadOnlyMedia())
1230 ClearFlags(B_PARTITION_READ_ONLY
);
1234 Changed(flags
, B_PARTITION_CHANGED_DEFRAGMENTATION
1235 | B_PARTITION_CHANGED_CHECK
| B_PARTITION_CHANGED_REPAIR
);
1244 KPartition::SetAlgorithmData(uint32 data
)
1246 fAlgorithmData
= data
;
1251 KPartition::AlgorithmData() const
1253 return fAlgorithmData
;
1258 KPartition::WriteUserData(UserDataWriter
& writer
, user_partition_data
* data
)
1261 char* name
= writer
.PlaceString(Name());
1262 char* contentName
= writer
.PlaceString(ContentName());
1263 char* type
= writer
.PlaceString(Type());
1264 char* contentType
= writer
.PlaceString(ContentType());
1265 char* parameters
= writer
.PlaceString(Parameters());
1266 char* contentParameters
= writer
.PlaceString(ContentParameters());
1270 data
->offset
= Offset();
1271 data
->size
= Size();
1272 data
->content_size
= ContentSize();
1273 data
->block_size
= BlockSize();
1274 data
->status
= Status();
1275 data
->flags
= Flags();
1276 data
->volume
= VolumeID();
1277 data
->index
= Index();
1278 data
->change_counter
= ChangeCounter();
1279 data
->disk_system
= (DiskSystem() ? DiskSystem()->ID() : -1);
1281 data
->content_name
= contentName
;
1283 data
->content_type
= contentType
;
1284 data
->parameters
= parameters
;
1285 data
->content_parameters
= contentParameters
;
1286 data
->child_count
= CountChildren();
1287 // make buffer relocatable
1288 writer
.AddRelocationEntry(&data
->name
);
1289 writer
.AddRelocationEntry(&data
->content_name
);
1290 writer
.AddRelocationEntry(&data
->type
);
1291 writer
.AddRelocationEntry(&data
->content_type
);
1292 writer
.AddRelocationEntry(&data
->parameters
);
1293 writer
.AddRelocationEntry(&data
->content_parameters
);
1296 for (int32 i
= 0; KPartition
* child
= ChildAt(i
); i
++) {
1297 user_partition_data
* childData
1298 = writer
.AllocatePartitionData(child
->CountChildren());
1300 data
->children
[i
] = childData
;
1301 writer
.AddRelocationEntry(&data
->children
[i
]);
1303 child
->WriteUserData(writer
, childData
);
1309 KPartition::Dump(bool deep
, int32 level
)
1311 if (level
< 0 || level
> 255)
1315 sprintf(prefix
, "%*s%*s", (int)level
, "", (int)level
, "");
1319 OUT("%spartition %" B_PRId32
": %s\n", prefix
, ID(), path
.Path());
1320 OUT("%s offset: %" B_PRIdOFF
"\n", prefix
, Offset());
1321 OUT("%s size: %" B_PRIdOFF
" (%.2f MB)\n", prefix
, Size(),
1322 Size() / (1024.0*1024));
1323 OUT("%s content size: %" B_PRIdOFF
"\n", prefix
, ContentSize());
1324 OUT("%s block size: %" B_PRIu32
"\n", prefix
, BlockSize());
1325 OUT("%s child count: %" B_PRId32
"\n", prefix
, CountChildren());
1326 OUT("%s index: %" B_PRId32
"\n", prefix
, Index());
1327 OUT("%s status: %" B_PRIu32
"\n", prefix
, Status());
1328 OUT("%s flags: %" B_PRIx32
"\n", prefix
, Flags());
1329 OUT("%s volume: %" B_PRIdDEV
"\n", prefix
, VolumeID());
1330 OUT("%s disk system: %s\n", prefix
,
1331 (DiskSystem() ? DiskSystem()->Name() : NULL
));
1332 OUT("%s name: %s\n", prefix
, Name());
1333 OUT("%s content name: %s\n", prefix
, ContentName());
1334 OUT("%s type: %s\n", prefix
, Type());
1335 OUT("%s content type: %s\n", prefix
, ContentType());
1336 OUT("%s params: %s\n", prefix
, Parameters());
1337 OUT("%s content params: %s\n", prefix
, ContentParameters());
1339 for (int32 i
= 0; KPartition
* child
= ChildAt(i
); i
++)
1340 child
->Dump(true, level
+ 1);
1346 KPartition::FireOffsetChanged(off_t offset
)
1349 for (ListenerSet::Iterator it
= fListeners
->Begin();
1350 it
!= fListeners
->End(); ++it
) {
1351 (*it
)->OffsetChanged(this, offset
);
1358 KPartition::FireSizeChanged(off_t size
)
1361 for (ListenerSet::Iterator it
= fListeners
->Begin();
1362 it
!= fListeners
->End(); ++it
) {
1363 (*it
)->SizeChanged(this, size
);
1370 KPartition::FireContentSizeChanged(off_t size
)
1373 for (ListenerSet::Iterator it
= fListeners
->Begin();
1374 it
!= fListeners
->End(); ++it
) {
1375 (*it
)->ContentSizeChanged(this, size
);
1382 KPartition::FireBlockSizeChanged(uint32 blockSize
)
1385 for (ListenerSet::Iterator it
= fListeners
->Begin();
1386 it
!= fListeners
->End(); ++it
) {
1387 (*it
)->BlockSizeChanged(this, blockSize
);
1394 KPartition::FireIndexChanged(int32 index
)
1397 for (ListenerSet::Iterator it
= fListeners
->Begin();
1398 it
!= fListeners
->End(); ++it
) {
1399 (*it
)->IndexChanged(this, index
);
1406 KPartition::FireStatusChanged(uint32 status
)
1409 for (ListenerSet::Iterator it
= fListeners
->Begin();
1410 it
!= fListeners
->End(); ++it
) {
1411 (*it
)->StatusChanged(this, status
);
1418 KPartition::FireFlagsChanged(uint32 flags
)
1421 for (ListenerSet::Iterator it
= fListeners
->Begin();
1422 it
!= fListeners
->End(); ++it
) {
1423 (*it
)->FlagsChanged(this, flags
);
1430 KPartition::FireNameChanged(const char* name
)
1433 for (ListenerSet::Iterator it
= fListeners
->Begin();
1434 it
!= fListeners
->End(); ++it
) {
1435 (*it
)->NameChanged(this, name
);
1442 KPartition::FireContentNameChanged(const char* name
)
1445 for (ListenerSet::Iterator it
= fListeners
->Begin();
1446 it
!= fListeners
->End(); ++it
) {
1447 (*it
)->ContentNameChanged(this, name
);
1454 KPartition::FireTypeChanged(const char* type
)
1457 for (ListenerSet::Iterator it
= fListeners
->Begin();
1458 it
!= fListeners
->End(); ++it
) {
1459 (*it
)->TypeChanged(this, type
);
1466 KPartition::FireIDChanged(partition_id id
)
1469 for (ListenerSet::Iterator it
= fListeners
->Begin();
1470 it
!= fListeners
->End(); ++it
) {
1471 (*it
)->IDChanged(this, id
);
1478 KPartition::FireVolumeIDChanged(dev_t volumeID
)
1481 for (ListenerSet::Iterator it
= fListeners
->Begin();
1482 it
!= fListeners
->End(); ++it
) {
1483 (*it
)->VolumeIDChanged(this, volumeID
);
1490 KPartition::FireMountCookieChanged(void* cookie
)
1493 for (ListenerSet::Iterator it
= fListeners
->Begin();
1494 it
!= fListeners
->End(); ++it
) {
1495 (*it
)->MountCookieChanged(this, cookie
);
1502 KPartition::FireParametersChanged(const char* parameters
)
1505 for (ListenerSet::Iterator it
= fListeners
->Begin();
1506 it
!= fListeners
->End(); ++it
) {
1507 (*it
)->ParametersChanged(this, parameters
);
1514 KPartition::FireContentParametersChanged(const char* parameters
)
1517 for (ListenerSet::Iterator it
= fListeners
->Begin();
1518 it
!= fListeners
->End(); ++it
) {
1519 (*it
)->ContentParametersChanged(this, parameters
);
1526 KPartition::FireChildAdded(KPartition
* child
, int32 index
)
1529 for (ListenerSet::Iterator it
= fListeners
->Begin();
1530 it
!= fListeners
->End(); ++it
) {
1531 (*it
)->ChildAdded(this, child
, index
);
1538 KPartition::FireChildRemoved(KPartition
* child
, int32 index
)
1541 for (ListenerSet::Iterator it
= fListeners
->Begin();
1542 it
!= fListeners
->End(); ++it
) {
1543 (*it
)->ChildRemoved(this, child
, index
);
1550 KPartition::FireDiskSystemChanged(KDiskSystem
* diskSystem
)
1553 for (ListenerSet::Iterator it
= fListeners
->Begin();
1554 it
!= fListeners
->End(); ++it
) {
1555 (*it
)->DiskSystemChanged(this, diskSystem
);
1562 KPartition::FireCookieChanged(void* cookie
)
1565 for (ListenerSet::Iterator it
= fListeners
->Begin();
1566 it
!= fListeners
->End(); ++it
) {
1567 (*it
)->CookieChanged(this, cookie
);
1574 KPartition::FireContentCookieChanged(void* cookie
)
1577 for (ListenerSet::Iterator it
= fListeners
->Begin();
1578 it
!= fListeners
->End(); ++it
) {
1579 (*it
)->ContentCookieChanged(this, cookie
);
1586 KPartition::_UpdateChildIndices(int32 start
, int32 end
)
1589 for (int32 i
= start
; i
< end
; i
++) {
1590 fChildren
.ElementAt(i
)->SetIndex(i
);
1591 fChildren
.ElementAt(i
)->RepublishDevice();
1594 for (int32 i
= start
; i
> end
; i
--) {
1595 fChildren
.ElementAt(i
)->SetIndex(i
);
1596 fChildren
.ElementAt(i
)->RepublishDevice();
1603 KPartition::_NextID()
1605 return atomic_add(&sNextID
, 1);