2003-01-31 22:06:20 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// This software is part of the OpenBeOS distribution and is covered
|
|
|
|
|
// by the OpenBeOS license.
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
2003-02-16 18:07:23 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
2003-02-08 00:42:14 +00:00
|
|
|
#include <new.h>
|
2003-02-16 18:07:23 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
2003-02-08 00:42:14 +00:00
|
|
|
|
2003-01-31 22:06:20 +00:00
|
|
|
#include <DiskDevice.h>
|
2003-02-08 23:34:47 +00:00
|
|
|
#include <DiskDevicePrivate.h>
|
2003-02-16 18:07:23 +00:00
|
|
|
#include <Drivers.h>
|
2003-02-08 00:42:14 +00:00
|
|
|
#include <Message.h>
|
|
|
|
|
#include <Partition.h>
|
2003-02-16 18:07:23 +00:00
|
|
|
#include <RegistrarDefs.h>
|
2003-02-08 00:42:14 +00:00
|
|
|
#include <Session.h>
|
2003-01-31 22:06:20 +00:00
|
|
|
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \class BDiskDevice
|
|
|
|
|
\brief A BDiskDevice object represents a storage device.
|
|
|
|
|
*/
|
|
|
|
|
|
2003-01-31 22:06:20 +00:00
|
|
|
// constructor
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Creates an uninitialized BDiskDevice object.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
BDiskDevice::BDiskDevice()
|
2003-02-08 00:42:14 +00:00
|
|
|
: fSessions(10, true),
|
|
|
|
|
fUniqueID(-1),
|
|
|
|
|
fChangeCounter(0),
|
|
|
|
|
fMediaStatus(B_ERROR),
|
|
|
|
|
fSize(0),
|
|
|
|
|
fBlockSize(0),
|
|
|
|
|
fType(0),
|
|
|
|
|
fReadOnly(false),
|
|
|
|
|
fRemovable(false)//,
|
|
|
|
|
// fIsFloppy(false)
|
2003-01-31 22:06:20 +00:00
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
fPath[0] = '\0';
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// destructor
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Frees all resources associated with this object.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
BDiskDevice::~BDiskDevice()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-08 00:42:14 +00:00
|
|
|
// Unset
|
|
|
|
|
void
|
|
|
|
|
BDiskDevice::Unset()
|
|
|
|
|
{
|
|
|
|
|
fSessions.MakeEmpty();
|
|
|
|
|
fUniqueID = -1;
|
|
|
|
|
fChangeCounter = 0;
|
|
|
|
|
fMediaStatus = B_ERROR;
|
|
|
|
|
fSize = 0;
|
|
|
|
|
fBlockSize = 0;
|
|
|
|
|
fType = 0;
|
|
|
|
|
fReadOnly = false;
|
|
|
|
|
fRemovable = false;
|
|
|
|
|
// fIsFloppy = false;
|
|
|
|
|
fPath[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-01 18:13:13 +00:00
|
|
|
// Size
|
|
|
|
|
/*! \brief Returns the size of the device.
|
|
|
|
|
\return The size of the device in bytes.
|
|
|
|
|
*/
|
|
|
|
|
off_t
|
|
|
|
|
BDiskDevice::Size() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fSize;
|
2003-02-01 18:13:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BlockSize
|
|
|
|
|
/*! \brief Returns the block size of the device.
|
|
|
|
|
\return The block size of the device in bytes.
|
|
|
|
|
*/
|
|
|
|
|
int32
|
|
|
|
|
BDiskDevice::BlockSize() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fBlockSize;
|
2003-02-01 18:13:13 +00:00
|
|
|
}
|
|
|
|
|
|
2003-01-31 22:06:20 +00:00
|
|
|
// CountSessions
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns the number of sessions on this device.
|
|
|
|
|
\return The number of sessions on this device.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
int32
|
|
|
|
|
BDiskDevice::CountSessions() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fSessions.CountItems();
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SessionAt
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns a contained session by index.
|
|
|
|
|
\param index The index of the session to be returned.
|
|
|
|
|
\return The session with the requested index, or \c NULL, if \a index
|
|
|
|
|
is out of range.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
BSession *
|
|
|
|
|
BDiskDevice::SessionAt(int32 index) const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fSessions.ItemAt(index);
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CountPartitions
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns the number of partitions on this device.
|
|
|
|
|
\return The number of partitions on this device.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
int32
|
|
|
|
|
BDiskDevice::CountPartitions() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
int32 count = 0;
|
|
|
|
|
for (int32 i = 0; BSession *session = SessionAt(i); i++)
|
|
|
|
|
count += session->CountPartitions();
|
|
|
|
|
return count;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-08 00:42:14 +00:00
|
|
|
// Path
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns the path to the device.
|
|
|
|
|
\return The path to the device.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
const char *
|
2003-02-08 00:42:14 +00:00
|
|
|
BDiskDevice::Path() const
|
2003-01-31 22:06:20 +00:00
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return (fPath[0] != '\0' ? fPath : NULL);
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-16 18:07:23 +00:00
|
|
|
// skip_string_component
|
|
|
|
|
static
|
|
|
|
|
const char *
|
|
|
|
|
skip_string_component(const char *str, const char *component)
|
|
|
|
|
{
|
|
|
|
|
const char *remainder = NULL;
|
|
|
|
|
if (str && component) {
|
|
|
|
|
size_t len = strlen(component);
|
|
|
|
|
if (!strncmp(str, component, len))
|
|
|
|
|
remainder = str + len;
|
|
|
|
|
}
|
|
|
|
|
return remainder;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-31 22:06:20 +00:00
|
|
|
// GetName
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns a human readable name for the device.
|
|
|
|
|
|
|
|
|
|
The method tries to interpret the device path, which it can do only for
|
|
|
|
|
floppy, IDE and SCSI devices, for others the device path is returned.
|
|
|
|
|
|
|
|
|
|
\param name Pointer to a pre-allocated BString to be set to the device
|
|
|
|
|
name.
|
|
|
|
|
\param includeBusID \c true, if the bus ID shall be included in the name
|
2003-02-16 18:07:23 +00:00
|
|
|
to be returned (of interest for SCSI devices).
|
2003-02-01 18:13:13 +00:00
|
|
|
\param includeLUN \c true, if the LUN shall be included in the name
|
2003-02-16 18:07:23 +00:00
|
|
|
to be returned (of interest for SCSI devices).
|
|
|
|
|
\return
|
|
|
|
|
- \c B_OK: Everything went fine.
|
|
|
|
|
- \c B_BAD_VALUE: \c NULL \a name.
|
|
|
|
|
- \c B_NO_INIT: The device is not properly initialized.
|
2003-02-01 18:13:13 +00:00
|
|
|
*/
|
2003-02-16 18:07:23 +00:00
|
|
|
status_t
|
2003-01-31 22:06:20 +00:00
|
|
|
BDiskDevice::GetName(BString *name, bool includeBusID, bool includeLUN) const
|
|
|
|
|
{
|
2003-02-16 18:07:23 +00:00
|
|
|
// check params and initialization
|
|
|
|
|
status_t error = (name ? B_OK : B_BAD_VALUE);
|
|
|
|
|
const char *path = Path();
|
|
|
|
|
if (error == B_OK && !path)
|
|
|
|
|
error = B_BAD_VALUE;
|
|
|
|
|
// analyze the device path
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
bool recognized = false;
|
|
|
|
|
const char *prefix = "/dev/disk/";
|
|
|
|
|
size_t prefixLen = strlen(prefix);
|
|
|
|
|
if (!strncmp(path, prefix, prefixLen)) {
|
|
|
|
|
path = path + prefixLen;
|
|
|
|
|
// check first component
|
|
|
|
|
const char *tail = NULL;
|
|
|
|
|
// floppy
|
|
|
|
|
if (skip_string_component(path, "floppy/")) {
|
|
|
|
|
name->SetTo("floppy");
|
|
|
|
|
recognized = true;
|
|
|
|
|
// ide
|
|
|
|
|
} else if ((tail = skip_string_component(path, "ide/"))) {
|
|
|
|
|
int controller = 0;
|
|
|
|
|
bool master = false;
|
|
|
|
|
const char *_tail = tail;
|
|
|
|
|
if ((((tail = skip_string_component(_tail, "atapi/")))
|
|
|
|
|
|| ((tail = skip_string_component(_tail, "ata/"))))
|
|
|
|
|
&& isdigit(*tail)) {
|
|
|
|
|
controller = atoi(tail);
|
|
|
|
|
master = false;
|
|
|
|
|
if ((tail = strchr(tail, '/'))) {
|
|
|
|
|
tail++;
|
|
|
|
|
if (skip_string_component(tail, "master/")) {
|
|
|
|
|
master = true;
|
|
|
|
|
recognized = true;
|
|
|
|
|
} else if (skip_string_component(tail, "slave/"))
|
|
|
|
|
recognized = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (recognized) {
|
|
|
|
|
name->SetTo("IDE ");
|
|
|
|
|
*name << (master ? "master" : "slave") << " bus:"
|
|
|
|
|
<< controller;
|
|
|
|
|
}
|
|
|
|
|
// scsi
|
|
|
|
|
} else if ((tail = skip_string_component(path, "scsi/"))) {
|
|
|
|
|
int bus = 0;
|
|
|
|
|
int id = 0;
|
|
|
|
|
int lun = 0;
|
|
|
|
|
if (sscanf(tail, "%d/%d/%d/raw", &bus, &id, &lun) == 3) {
|
|
|
|
|
recognized = true;
|
|
|
|
|
name->SetTo("SCSI");
|
|
|
|
|
if (includeBusID)
|
|
|
|
|
*name << " bus:" << bus;
|
|
|
|
|
*name << " id:" << id;
|
|
|
|
|
if (includeLUN)
|
|
|
|
|
*name << " lun:" << lun;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!recognized)
|
|
|
|
|
name->SetTo(path);
|
|
|
|
|
}
|
|
|
|
|
return error;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetName
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns a human readable name for the device.
|
|
|
|
|
|
|
|
|
|
The method tries to interpret the device path, which it can do only for
|
|
|
|
|
floppy, IDE and SCSI devices, for others the device path is returned.
|
|
|
|
|
|
|
|
|
|
\param name Pointer to a pre-allocated char buffer into which the device
|
|
|
|
|
name shall be copied.
|
|
|
|
|
\param includeBusID \c true, if the bus ID shall be included in the name
|
2003-02-16 18:07:23 +00:00
|
|
|
to be returned (of interest for SCSI devices).
|
2003-02-01 18:13:13 +00:00
|
|
|
\param includeLUN \c true, if the LUN shall be included in the name
|
2003-02-16 18:07:23 +00:00
|
|
|
to be returned (of interest for SCSI devices).
|
|
|
|
|
- \c B_OK: Everything went fine.
|
|
|
|
|
- \c B_BAD_VALUE: \c NULL \a name.
|
|
|
|
|
- \c B_NO_INIT: The device is not properly initialized.
|
2003-02-01 18:13:13 +00:00
|
|
|
*/
|
2003-02-16 18:07:23 +00:00
|
|
|
status_t
|
2003-01-31 22:06:20 +00:00
|
|
|
BDiskDevice::GetName(char *name, bool includeBusID, bool includeLUN) const
|
|
|
|
|
{
|
2003-02-16 18:07:23 +00:00
|
|
|
status_t error = (name ? B_OK : B_BAD_VALUE);
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
BString _name;
|
|
|
|
|
error = GetName(&_name, includeBusID, includeLUN);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
strcpy(name, _name.String());
|
|
|
|
|
}
|
|
|
|
|
return error;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsReadOnly
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns whether the device is read-only.
|
|
|
|
|
\return \c true, if the device is read-only, \c false otherwise.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
bool
|
|
|
|
|
BDiskDevice::IsReadOnly() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fReadOnly;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsRemovable
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns whether the device media are removable.
|
|
|
|
|
\return \c true, if the device media are removable, \c false otherwise.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
bool
|
|
|
|
|
BDiskDevice::IsRemovable() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fRemovable;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// HasMedia
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns whether the device contains a media.
|
|
|
|
|
\return \c true, if the device contains a media, \c false otherwise.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
bool
|
|
|
|
|
BDiskDevice::HasMedia() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return (fMediaStatus == B_OK);
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsFloppy
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns whether the device is a floppy device.
|
|
|
|
|
\return \c true, if the device is a floppy device, \c false otherwise.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
bool
|
|
|
|
|
BDiskDevice::IsFloppy() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return !strcmp(fPath, "/dev/disk/floppy/raw");
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns the type of the device.
|
|
|
|
|
|
|
|
|
|
The type may be one of the following (note, that not all types make sense
|
|
|
|
|
for storage device, but they are listed anyway):
|
|
|
|
|
- \c B_DISK: Hard disks, floppy disks, etc.
|
|
|
|
|
- \c B_TAPE: Tape drives.
|
|
|
|
|
- \c B_PRINTER: Printers.
|
|
|
|
|
- \c B_CPU: CPU devices.
|
|
|
|
|
- \c B_WORM: Write-once, read-many devives.
|
|
|
|
|
- \c B_CD: CD ROMs.
|
|
|
|
|
- \c B_SCANNER: Scanners.
|
|
|
|
|
- \c B_OPTICAL: Optical devices.
|
|
|
|
|
- \c B_JUKEBOX: Jukeboxes.
|
|
|
|
|
- \c B_NETWORK: Network devices.
|
|
|
|
|
\return The type of the device.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
uint8
|
|
|
|
|
BDiskDevice::Type() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fType;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UniqueID
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Returns a unique identifier for this device.
|
|
|
|
|
|
|
|
|
|
The ID is not persistent, i.e. in general won't be the same after
|
|
|
|
|
rebooting.
|
|
|
|
|
|
|
|
|
|
\see BDiskDeviceRoster::GetDeviceWithID().
|
|
|
|
|
|
|
|
|
|
\return A unique identifier for this device.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
int32
|
|
|
|
|
BDiskDevice::UniqueID() const
|
|
|
|
|
{
|
2003-02-08 00:42:14 +00:00
|
|
|
return fUniqueID;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Eject
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Eject the device's media.
|
|
|
|
|
|
|
|
|
|
The device media must, of course, be removable, and the device must
|
|
|
|
|
support ejecting the media.
|
|
|
|
|
|
2003-02-16 18:07:23 +00:00
|
|
|
\param update If \c true, Update() is invoked after successful ejection.
|
|
|
|
|
\return
|
|
|
|
|
- \c B_OK: Everything went fine.
|
|
|
|
|
- \c B_NO_INIT: The device is not properly initialized.
|
|
|
|
|
- \c B_BAD_VALUE: The device media is not removable.
|
|
|
|
|
- other error codes
|
2003-02-01 18:13:13 +00:00
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
status_t
|
2003-02-16 18:07:23 +00:00
|
|
|
BDiskDevice::Eject(bool update)
|
2003-01-31 22:06:20 +00:00
|
|
|
{
|
2003-02-16 18:07:23 +00:00
|
|
|
// get path
|
|
|
|
|
const char *path = Path();
|
|
|
|
|
status_t error = (path ? B_OK : B_NO_INIT);
|
|
|
|
|
// check whether the device media is removable
|
|
|
|
|
if (error == B_OK && !IsRemovable())
|
|
|
|
|
error = B_BAD_VALUE;
|
|
|
|
|
// open, eject and close the device
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
int fd = open(path, O_RDONLY);
|
|
|
|
|
if (fd < 0 || ioctl(fd, B_EJECT_DEVICE) != 0)
|
|
|
|
|
error = errno;
|
|
|
|
|
if (fd >= 0)
|
|
|
|
|
close(fd);
|
|
|
|
|
}
|
|
|
|
|
if (error == B_OK && update)
|
|
|
|
|
error = Update();
|
|
|
|
|
return error;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LowLevelFormat
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Low level formats the device.
|
|
|
|
|
\return \c B_OK, if everything went fine, another error code otherwise.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
status_t
|
|
|
|
|
BDiskDevice::LowLevelFormat()
|
|
|
|
|
{
|
|
|
|
|
return B_ERROR; // not implemented
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Updates the object to reflect the latest changes to the device.
|
|
|
|
|
|
|
|
|
|
Note, that subobjects (BSessions, BPartitions) may be deleted during this
|
|
|
|
|
operation. It is also possible, that the device doesn't exist anymore --
|
|
|
|
|
e.g. if it is hot-pluggable. Then an error is returned and the object is
|
|
|
|
|
uninitialized.
|
|
|
|
|
|
2003-02-16 18:07:23 +00:00
|
|
|
\param updated Pointer to a bool variable which shall be set to \c true,
|
|
|
|
|
if the object needed to be updated and to \c false otherwise.
|
|
|
|
|
May be \c NULL. Is not touched, if the method fails.
|
2003-02-01 18:13:13 +00:00
|
|
|
\return \c B_OK, if the update went fine, another error code otherwise.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
status_t
|
2003-02-16 18:07:23 +00:00
|
|
|
BDiskDevice::Update(bool *updated)
|
2003-01-31 22:06:20 +00:00
|
|
|
{
|
2003-02-16 18:07:23 +00:00
|
|
|
// get a messenger for the disk device manager
|
|
|
|
|
// TODO: Cache the messenger? Maybe add a global variable?
|
|
|
|
|
BMessenger manager;
|
|
|
|
|
status_t error = get_disk_device_messenger(&manager);
|
|
|
|
|
// compose request message
|
|
|
|
|
BMessage request(B_REG_UPDATE_DISK_DEVICE);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = request.AddInt32("device_id", fUniqueID);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = request.AddInt32("change_counter", fChangeCounter);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = request.AddInt32("update_policy", B_REG_DEVICE_UPDATE_CHANGED);
|
|
|
|
|
// send request
|
|
|
|
|
BMessage reply;
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = manager.SendMessage(&request, &reply);
|
|
|
|
|
// analyze reply
|
|
|
|
|
bool upToDate = true;
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
// result
|
|
|
|
|
status_t result = B_OK;
|
|
|
|
|
error = reply.FindInt32("result", &result);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = result;
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = reply.FindBool("up_to_date", &upToDate);
|
|
|
|
|
}
|
|
|
|
|
// get the archived device, if not up to date
|
|
|
|
|
if (error == B_OK && !upToDate) {
|
|
|
|
|
BMessage archive;
|
|
|
|
|
error = reply.FindMessage("device", &archive);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = _Update(&archive);
|
|
|
|
|
}
|
|
|
|
|
// set result / cleanup on error
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
if (updated)
|
|
|
|
|
*updated = !upToDate;
|
|
|
|
|
} else
|
|
|
|
|
Unset();
|
|
|
|
|
return error;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VisitEachSession
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Iterates through the device's sessions.
|
|
|
|
|
|
|
|
|
|
The supplied visitor's Visit(BSession*) is invoked for each session.
|
|
|
|
|
If Visit() returns \c true, the iteration is terminated and the BSession
|
|
|
|
|
object just visited is returned.
|
|
|
|
|
|
|
|
|
|
\param visitor The visitor.
|
|
|
|
|
\return The BSession object at which the iteration was terminated, or
|
|
|
|
|
\c NULL, if the iteration has not been terminated.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
BSession *
|
|
|
|
|
BDiskDevice::VisitEachSession(BDiskDeviceVisitor *visitor)
|
|
|
|
|
{
|
2003-02-08 23:34:47 +00:00
|
|
|
if (visitor) {
|
|
|
|
|
for (int32 i = 0; BSession *session = SessionAt(i); i++) {
|
|
|
|
|
if (visitor->Visit(session))
|
|
|
|
|
return session;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VisitEachPartition
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Iterates through the device's partitions.
|
|
|
|
|
|
|
|
|
|
The supplied visitor's Visit(BPartition*) is invoked for each partition.
|
|
|
|
|
If Visit() returns \c true, the iteration is terminated and the BPartition
|
|
|
|
|
object just visited is returned.
|
|
|
|
|
|
|
|
|
|
\param visitor The visitor.
|
|
|
|
|
\return The BPartition object at which the iteration was terminated, or
|
|
|
|
|
\c NULL, if the iteration has not been terminated.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
BPartition *
|
|
|
|
|
BDiskDevice::VisitEachPartition(BDiskDeviceVisitor *visitor)
|
|
|
|
|
{
|
2003-02-08 23:34:47 +00:00
|
|
|
if (visitor) {
|
|
|
|
|
for (int32 i = 0; BSession *session = SessionAt(i); i++) {
|
|
|
|
|
if (BPartition *partition = session->VisitEachPartition(visitor))
|
|
|
|
|
return partition;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Traverse
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Pre-order traverses the tree of the spanned by the BDiskDevice and
|
|
|
|
|
its subobjects.
|
|
|
|
|
|
|
|
|
|
The supplied visitor's Visit() is invoked for the device object itself,
|
|
|
|
|
for each session and for each partition.
|
|
|
|
|
If Visit() returns \c true, the iteration is terminated and this method
|
|
|
|
|
returns \c true as well.
|
|
|
|
|
|
|
|
|
|
\param visitor The visitor.
|
|
|
|
|
\return \c true, if the iteration was terminated, \c false otherwise.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
bool
|
|
|
|
|
BDiskDevice::Traverse(BDiskDeviceVisitor *visitor)
|
|
|
|
|
{
|
2003-02-08 23:34:47 +00:00
|
|
|
if (visitor) {
|
|
|
|
|
// visit the device itself
|
|
|
|
|
if (visitor->Visit(this))
|
|
|
|
|
return true;
|
|
|
|
|
for (int32 i = 0; BSession *session = SessionAt(i); i++) {
|
|
|
|
|
// visit the session
|
|
|
|
|
if (visitor->Visit(session))
|
|
|
|
|
return true;
|
|
|
|
|
// visit all partitions on the session
|
|
|
|
|
if (session->VisitEachPartition(visitor))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SessionWithID
|
|
|
|
|
/*! \brief Returns the session on the device, that has a certain ID.
|
|
|
|
|
\param id The ID of the session to be returned.
|
|
|
|
|
\return The session with ID \a id, or \c NULL, if a session with that
|
|
|
|
|
ID does not exist on this device.
|
|
|
|
|
*/
|
|
|
|
|
BSession *
|
|
|
|
|
BDiskDevice::SessionWithID(int32 id)
|
|
|
|
|
{
|
|
|
|
|
IDFinderVisitor visitor(id);
|
|
|
|
|
return VisitEachSession(&visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PartitionWithID
|
|
|
|
|
/*! \brief Returns the partition on the device, that has a certain ID.
|
|
|
|
|
\param id The ID of the partition to be returned.
|
|
|
|
|
\return The partition with ID \a id, or \c NULL, if a partition with that
|
|
|
|
|
ID does not exist on this device.
|
|
|
|
|
*/
|
|
|
|
|
BPartition *
|
|
|
|
|
BDiskDevice::PartitionWithID(int32 id)
|
|
|
|
|
{
|
|
|
|
|
IDFinderVisitor visitor(id);
|
|
|
|
|
return VisitEachPartition(&visitor);
|
2003-01-31 22:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// copy constructor
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Privatized copy constructor to avoid usage.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
BDiskDevice::BDiskDevice(const BDiskDevice &)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =
|
2003-02-01 18:13:13 +00:00
|
|
|
/*! \brief Privatized assignment operator to avoid usage.
|
|
|
|
|
*/
|
2003-01-31 22:06:20 +00:00
|
|
|
BDiskDevice &
|
|
|
|
|
BDiskDevice::operator=(const BDiskDevice &)
|
|
|
|
|
{
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-08 00:42:14 +00:00
|
|
|
// find_string
|
|
|
|
|
static
|
|
|
|
|
status_t
|
|
|
|
|
find_string(BMessage *message, const char *name, char *buffer)
|
|
|
|
|
{
|
|
|
|
|
const char *str;
|
|
|
|
|
status_t error = message->FindString(name, &str);
|
2003-02-08 23:34:47 +00:00
|
|
|
if (error == B_OK)
|
2003-02-08 00:42:14 +00:00
|
|
|
strcpy(buffer, str);
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _Unarchive
|
|
|
|
|
status_t
|
|
|
|
|
BDiskDevice::_Unarchive(BMessage *archive)
|
|
|
|
|
{
|
2003-02-08 23:34:47 +00:00
|
|
|
//printf("BDiskDevice::_Unarchive()\n");
|
|
|
|
|
//archive->PrintToStream();
|
2003-02-08 00:42:14 +00:00
|
|
|
Unset();
|
|
|
|
|
status_t error = (archive ? B_OK : B_BAD_VALUE);
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
// ID and change counter
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("id", &fUniqueID);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("change_counter", &fChangeCounter);
|
|
|
|
|
// geometry
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt64("size", &fSize);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("block_size", &fBlockSize);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt8("type", (int8*)&fType);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindBool("removable", &fRemovable);
|
|
|
|
|
if (error == B_OK)
|
2003-02-08 23:34:47 +00:00
|
|
|
error = archive->FindBool("read_only", &fReadOnly);
|
2003-02-08 00:42:14 +00:00
|
|
|
// other data
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = find_string(archive, "path", fPath);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("media_status", &fMediaStatus);
|
|
|
|
|
// sessions
|
|
|
|
|
type_code fieldType;
|
|
|
|
|
int32 count = 0;
|
2003-02-08 23:34:47 +00:00
|
|
|
if (error == B_OK) {
|
|
|
|
|
if (archive->GetInfo("sessions", &fieldType, &count) != B_OK)
|
|
|
|
|
count = 0;
|
|
|
|
|
}
|
2003-02-08 00:42:14 +00:00
|
|
|
for (int32 i = 0; error == B_OK && i < count; i++) {
|
|
|
|
|
// get the archived session
|
|
|
|
|
BMessage sessionArchive;
|
|
|
|
|
error = archive->FindMessage("sessions", i, &sessionArchive);
|
|
|
|
|
// allocate a session object
|
|
|
|
|
BSession *session = NULL;
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
session = new(nothrow) BSession;
|
|
|
|
|
if (!session)
|
|
|
|
|
error = B_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
// unarchive the session
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = session->_Unarchive(&sessionArchive);
|
|
|
|
|
// add the session
|
|
|
|
|
if (error == B_OK && !_AddSession(session))
|
|
|
|
|
error = B_NO_MEMORY;
|
|
|
|
|
// cleanup on error
|
|
|
|
|
if (error != B_OK && session)
|
|
|
|
|
delete session;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// cleanup on error
|
|
|
|
|
if (error != B_OK)
|
|
|
|
|
Unset();
|
2003-02-08 23:34:47 +00:00
|
|
|
//printf("BDiskDevice::_Unarchive() done: %s\n", strerror(error));
|
2003-02-08 00:42:14 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-16 18:07:23 +00:00
|
|
|
// _Update
|
|
|
|
|
status_t
|
|
|
|
|
BDiskDevice::_Update(BMessage *archive)
|
|
|
|
|
{
|
|
|
|
|
status_t error = (archive ? B_OK : B_BAD_VALUE);
|
|
|
|
|
bool upToDate = false;
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
// ID and change counter
|
|
|
|
|
int32 id;
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("id", &id);
|
|
|
|
|
if (error == B_OK && id != fUniqueID)
|
|
|
|
|
error = B_ERROR;
|
|
|
|
|
int32 changeCounter;
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("change_counter", &changeCounter);
|
|
|
|
|
upToDate = (fChangeCounter == changeCounter);
|
|
|
|
|
fChangeCounter = changeCounter;
|
|
|
|
|
}
|
|
|
|
|
if (error == B_OK && !upToDate) {
|
|
|
|
|
// geometry
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt64("size", &fSize);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("block_size", &fBlockSize);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt8("type", (int8*)&fType);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindBool("removable", &fRemovable);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindBool("read_only", &fReadOnly);
|
|
|
|
|
// other data
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = find_string(archive, "path", fPath);
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = archive->FindInt32("media_status", &fMediaStatus);
|
|
|
|
|
// sessions
|
|
|
|
|
// copy old session list and empty it
|
|
|
|
|
BObjectList<BSession> sessions;
|
|
|
|
|
for (int32 i = 0; BSession *session = fSessions.ItemAt(i); i++)
|
|
|
|
|
sessions.AddItem(session);
|
|
|
|
|
for (int32 i = fSessions.CountItems() - 1; i >= 0; i--)
|
|
|
|
|
fSessions.RemoveItemAt(i);
|
|
|
|
|
// get the session count
|
|
|
|
|
type_code fieldType;
|
|
|
|
|
int32 count = 0;
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
if (archive->GetInfo("sessions", &fieldType, &count) != B_OK)
|
|
|
|
|
count = 0;
|
|
|
|
|
}
|
|
|
|
|
for (int32 i = 0; error == B_OK && i < count; i++) {
|
|
|
|
|
// get the archived session
|
|
|
|
|
BMessage sessionArchive;
|
|
|
|
|
error = archive->FindMessage("sessions", i, &sessionArchive);
|
|
|
|
|
// check, whether we do already know that session
|
|
|
|
|
int32 sessionID;
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = sessionArchive.FindInt32("id", &sessionID);
|
|
|
|
|
BSession *session = NULL;
|
|
|
|
|
for (int32 k = 0; k < sessions.CountItems(); k++) {
|
|
|
|
|
BSession *oldSession = sessions.ItemAt(i);
|
|
|
|
|
if (oldSession->UniqueID() == sessionID) {
|
|
|
|
|
session = oldSession;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (error == B_OK) {
|
|
|
|
|
if (session) {
|
|
|
|
|
// the session is known: just update it
|
|
|
|
|
error = session->_Update(&sessionArchive);
|
|
|
|
|
} else {
|
|
|
|
|
// the session is unknown
|
|
|
|
|
// allocate a session object
|
|
|
|
|
session = new(nothrow) BSession;
|
|
|
|
|
if (!session)
|
|
|
|
|
error = B_NO_MEMORY;
|
|
|
|
|
// unarchive the session
|
|
|
|
|
if (error == B_OK)
|
|
|
|
|
error = session->_Unarchive(&sessionArchive);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// add the session
|
|
|
|
|
if (error == B_OK && !_AddSession(session))
|
|
|
|
|
error = B_NO_MEMORY;
|
|
|
|
|
// cleanup on error
|
|
|
|
|
if (error != B_OK && session)
|
|
|
|
|
delete session;
|
|
|
|
|
}
|
|
|
|
|
// delete all obsolete sessions
|
|
|
|
|
for (int32 i = sessions.CountItems() - 1; i >= 0; i--)
|
|
|
|
|
delete sessions.RemoveItemAt(i);
|
|
|
|
|
}
|
|
|
|
|
// cleanup on error
|
|
|
|
|
if (error != B_OK)
|
|
|
|
|
Unset();
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-08 00:42:14 +00:00
|
|
|
// _AddSession
|
|
|
|
|
bool
|
|
|
|
|
BDiskDevice::_AddSession(BSession *session)
|
|
|
|
|
{
|
|
|
|
|
bool result = fSessions.AddItem(session);
|
|
|
|
|
if (result)
|
|
|
|
|
session->_SetDevice(this);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|