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
This commit is contained in:
Ingo Weinhold 2003-06-10 22:37:43 +00:00
parent af4c45d5d8
commit 0b6c74bbe3
2 changed files with 103 additions and 50 deletions

View File

@ -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<KPartition*> fChildren;

View File

@ -1,38 +1,24 @@
// KPartition.cpp
#include <errno.h>
#include <fcntl.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <Errors.h>
//#include <Partition.h>
// 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);
}