From 0b6c74bbe3e509bae00b911698b19d4731ded935 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 10 Jun 2003 22:37:43 +0000 Subject: [PATCH] Implemented some more bits of KPartition. Added a very useful Open() method. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3463 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/disk_device_manager/KPartition.h | 24 ++-- .../core/disk_device_manager/KPartition.cpp | 129 ++++++++++++------ 2 files changed, 103 insertions(+), 50 deletions(-) diff --git a/headers/private/kernel/disk_device_manager/KPartition.h b/headers/private/kernel/disk_device_manager/KPartition.h index 0aa610f276..9d4f9e4eb8 100644 --- a/headers/private/kernel/disk_device_manager/KPartition.h +++ b/headers/private/kernel/disk_device_manager/KPartition.h @@ -6,12 +6,6 @@ #include "disk_device_manager.h" #include "List.h" -namespace BPrivate { -namespace DiskDevice { - -class KDiskDevice; -class KDiskSystem; - // partition flags // TODO: move to another header (must be accessible from userland API impl.) enum { @@ -24,17 +18,26 @@ enum { B_PARTITION_DESCENDANT_BUSY = 0x40, }; +namespace BPrivate { +namespace DiskDevice { + +class KDiskDevice; +class KDiskSystem; + class KPartition { +public: KPartition(partition_id id = -1); virtual ~KPartition(); // Reference counting. As long as there's at least one referrer, the // object won't be deleted. // manager must be locked - bool Register(); - bool Unregister(); + void Register(); + void Unregister(); int32 CountReferences() const; + status_t Open(int flags, int *fd); + void SetBusy(bool busy); bool IsBusy() const; // == jobs which may affect this partition are scheduled/in progress @@ -84,7 +87,7 @@ class KPartition { partition_data *PartitionData(); const partition_data *PartitionData() const; - void SetID(partition_id id); + virtual void SetID(partition_id id); partition_id ID() const; int32 ChangeCounter() const; @@ -139,6 +142,9 @@ class KPartition { void SetContentCookie(void *cookie); void *ContentCookie() const; +private: + void _UpdateChildIndices(int32 index); + protected: partition_data fPartitionData; List fChildren; diff --git a/src/kernel/core/disk_device_manager/KPartition.cpp b/src/kernel/core/disk_device_manager/KPartition.cpp index 514a34a23b..c118ef8cb4 100644 --- a/src/kernel/core/disk_device_manager/KPartition.cpp +++ b/src/kernel/core/disk_device_manager/KPartition.cpp @@ -1,38 +1,24 @@ // KPartition.cpp +#include +#include #include +#include #include +#include + //#include // TODO: Move the definitions needed in the kernel to a separate header. +#include "KDiskDevice.h" +#include "KDiskDeviceManager.h" +#include "KDiskDeviceUtils.h" #include "KPartition.h" using namespace std; -using BPrivate::DiskDevice::KDiskDevice; using BPrivate::DiskDevice::KDiskSystem; -// set_string -// simple helper -static -status_t -set_string(char *&location, const char *newValue) -{ - // unset old value - if (location) { - free(location); - location = NULL; - } - // set new value - status_t error = B_OK; - if (newValue) { - location = strdup(newValue); - if (!location) - error = B_NO_MEMORY; - } - return error; -} - // constructor KPartition::KPartition(partition_id id) : fPartitionData(), @@ -74,19 +60,17 @@ KPartition::~KPartition() } // Register -bool +void KPartition::Register() { fReferenceCount++; - return true; } // Unregister -bool +void KPartition::Unregister() { fReferenceCount--; - return true; } // CountReferences @@ -96,6 +80,24 @@ KPartition::CountReferences() const return fReferenceCount; } +// Open +status_t +KPartition::Open(int flags, int *fd) +{ + if (!fd) + return B_BAD_VALUE; + // get the path + char path[B_PATH_NAME_LENGTH]; + status_t error = GetPath(path); + if (error != B_OK) + return error; + // open the device + *fd = open(path, flags); + if (*fd < 0) + return errno; + return B_OK; +} + // SetBusy void KPartition::SetBusy(bool busy) @@ -343,8 +345,29 @@ KPartition::ChangeCounter() const status_t KPartition::GetPath(char *path) const { - // not implemented - return B_ERROR; + // For a KDiskDevice this version is never invoked, so the check for + // Parent() is correct. + if (!path || !Parent() || Index() < 0) + return B_BAD_VALUE; + // get the parent's path + status_t error = Parent()->GetPath(path); + if (error != B_OK) + return error; + // check length for safety + int32 len = strlen(path); + if (len >= B_PATH_NAME_LENGTH - 10) + return B_NAME_TOO_LONG; + if (Parent() == Device()) { + // Our parent is a device, so we replace `raw' by our index. + int32 leafLen = strlen("/raw"); + if (len <= leafLen || strcmp(path + len - leafLen, "/raw")) + return B_ERROR; + sprintf(path + len - leafLen + 1, "%ld", Index()); + } else { + // Our parent is a normal partition, no device: Append our index. + sprintf(path + len, "_%ld", Index()); + } + return error; } // SetVolumeID @@ -423,6 +446,7 @@ KPartition::Device() const void KPartition::SetParent(KPartition *parent) { + // Must be called in a {Add,Remove}Child() only! fParent = parent; } @@ -444,13 +468,22 @@ KPartition::AddChild(KPartition *partition, int32 index) if (index < 0 || index > count || !partition) return B_BAD_VALUE; // add partition -// TODO: Lock the disk device manager! - if (!fChildren.AddItem(partition, index)) - return B_NO_MEMORY; - fPartitionData.child_count++; - partition->SetParent(this); - partition->SetDevice(Device()); - return B_OK; + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + if (ManagerLocker locker = manager) { + if (!fChildren.AddItem(partition, index)) + return B_NO_MEMORY; + if (!manager->PartitionAdded(partition)) { + fChildren.RemoveItem(index); + return B_NO_MEMORY; + } + partition->SetIndex(index); + _UpdateChildIndices(index); + fPartitionData.child_count++; + partition->SetParent(this); + partition->SetDevice(Device()); + return B_OK; + } + return B_ERROR; } // RemoveChild @@ -459,12 +492,18 @@ KPartition::RemoveChild(int32 index) { KPartition *partition = NULL; if (index >= 0 && index < fPartitionData.child_count) { -// TODO: Lock the disk device manager! - partition = fChildren.ItemAt(index); - if (partition && fChildren.RemoveItem(index)) { - fPartitionData.child_count--; - partition->SetParent(NULL); - partition->SetDevice(NULL); + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + if (ManagerLocker locker = manager) { + partition = fChildren.ItemAt(index); + if (!partition || !manager->PartitionRemoved(partition)) + return NULL; + if (fChildren.RemoveItem(index)) { + _UpdateChildIndices(index + 1); + partition->SetIndex(-1); + fPartitionData.child_count--; + partition->SetParent(NULL); + partition->SetDevice(NULL); + } } } return partition; @@ -571,3 +610,11 @@ KPartition::ContentCookie() const return fPartitionData.content_cookie; } +// _UpdateChildIndices +void +KPartition::_UpdateChildIndices(int32 index) +{ + for (int32 i = index; KPartition *child = fChildren.ItemAt(i); i++) + child->SetIndex(index); +} +