Fixed/rewrote the implementation. Added doxygen style documentation.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2207 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2002-12-09 12:49:44 +00:00
parent 21881ce58c
commit 0813d0d4b8
2 changed files with 527 additions and 610 deletions
+362 -481
View File
@@ -6,615 +6,496 @@
// //
// Description: BVolume class // Description: BVolume class
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/*!
\file Volume.h
BVolume implementation.
*/
#include <Volume.h>
#include <Directory.h>
#include <Bitmap.h>
#include <Node.h>
#include <errno.h> #include <errno.h>
#include <Bitmap.h>
#include <Directory.h>
#include <fs_info.h> #include <fs_info.h>
#include <kernel_interface.h> #include <kernel_interface.h>
#include <Node.h>
#include <Volume.h>
#ifdef USE_OPENBEOS_NAMESPACE #ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS { namespace OpenBeOS {
#endif #endif
// ---------------------------------------------------------------------- /*!
// BVolume (public) \class BVolume
// ---------------------------------------------------------------------- \brief Represents a disk volume
// Default constructor: does nothing and sets InitCheck() to B_NO_INIT.
BVolume::BVolume(void) Provides an interface for querying information about a volume.
{
Unset();
}
The class is a simple wrapper for a \c dev_t and the function
fs_stat_dev. The only exception is the method is SetName(), which
sets the name of the volume.
// ---------------------------------------------------------------------- \author Vincent Dominguez
// BVolume (public) \author <a href='mailto:[email protected]'>Ingo Weinhold</a>
// ----------------------------------------------------------------------
// Device constructor: sets the BVolume to point to the volume
// represented by the argument. See the SetTo() function for
// status codes.
BVolume::BVolume( \version 0.0.0
dev_t dev) */
{
#if !_PR3_COMPATIBLE_
// Initialize reserved class variables to "safe" values:
_reserved[0] = 0L;
_reserved[1] = 0L;
_reserved[2] = 0L;
_reserved[3] = 0L;
_reserved[4] = 0L;
_reserved[5] = 0L;
_reserved[6] = 0L;
_reserved[7] = 0L;
// Place this in a separate initialization method at
// a later time.
#endif
SetTo(dev); /*! \var dev_t BVolume::fDevice
} \brief The volume's device ID.
*/
/*! \var dev_t BVolume::fCStatus
\brief The object's initialization status.
*/
// ---------------------------------------------------------------------- // constructor
// BVolume (public) /*! \brief Creates an uninitialized BVolume.
// ----------------------------------------------------------------------
// Copy constructor: sets the object to point to the same device as
// does the argument.
BVolume::BVolume( InitCheck() will return \c B_NO_INIT.
const BVolume& vol) */
{ BVolume::BVolume()
#if !_PR3_COMPATIBLE_ : fDevice(-1),
// Initialize reserved class variables to "safe" values: fCStatus(B_NO_INIT)
_reserved[0] = 0L;
_reserved[1] = 0L;
_reserved[2] = 0L;
_reserved[3] = 0L;
_reserved[4] = 0L;
_reserved[5] = 0L;
_reserved[6] = 0L;
_reserved[7] = 0L;
// Place this in a separate initialization method at
// a later time.
#endif
fDev = vol.Device();
fCStatus = vol.InitCheck();
}
// ----------------------------------------------------------------------
// ~BVolume (public, virtual)
// ----------------------------------------------------------------------
// Destructor: Destroys the BVolume object.
BVolume::~BVolume(void)
{ {
} }
// constructor
/*! \brief Creates a BVolume and initializes it to the volume specified
by the supplied device ID.
// ---------------------------------------------------------------------- InitCheck() should be called to check whether the initialization was
// InitCheck (public) successful.
// ----------------------------------------------------------------------
// Returns the status of the last initialization (from either the
// constructor or SetTo()).
\param device The device ID of the volume.
*/
BVolume::BVolume(dev_t device)
: fDevice(-1),
fCStatus(B_NO_INIT)
{
SetTo(device);
}
// copy constructor
/*! \brief Creates a BVolume and makes it a clone of the supplied one.
Afterwards the object refers to the same device the supplied object
does. If the latter is not properly initialized, this object isn't
either.
\param volume The volume object to be cloned.
*/
BVolume::BVolume(const BVolume &volume)
: fDevice(volume.fDevice),
fCStatus(volume.fCStatus)
{
}
// destructor
/*! \brief Frees all resources associated with the object.
Does nothing.
*/
BVolume::~BVolume()
{
}
// InitCheck
/*! \brief Returns the result of the last initialization.
\return
- \c B_OK: The object is properly initialized.
- an error code otherwise
*/
status_t status_t
BVolume::InitCheck(void) const BVolume::InitCheck(void) const
{ {
return fCStatus; return fCStatus;
} }
// SetTo
// ---------------------------------------------------------------------- /*! \brief Re-initializes the object to refer to the volume specified by
// SetTo (public) the supplied device ID.
// ---------------------------------------------------------------------- \param device The device ID of the volume.
// Initializes the BVolume object to represent the volume (device) \param
// identified by the argument. - \c B_OK: Everything went fine.
- an error code otherwise
*/
status_t status_t
BVolume::SetTo( BVolume::SetTo(dev_t device)
dev_t dev)
{ {
fDev = dev; // uninitialize
Unset();
// Call the kernel function that gets device information // check the parameter
// in order to determine the device status: status_t error = (device >= 0 ? B_OK : B_BAD_VALUE);
fs_info fsInfo; if (error == B_OK) {
int err = BPrivate::Storage::stat_dev(dev, &fsInfo); fs_info info;
if (fs_stat_dev(device, &info) != 0)
if (err != 0) { error = errno;
fCStatus = errno;
} }
else { // set the new value
fCStatus = B_OK; if (error == B_OK)
} fDevice = device;
// set the init status variable
fCStatus = error;
return fCStatus; return fCStatus;
} }
// Unset
// ---------------------------------------------------------------------- /*! \brief Uninitialized the BVolume.
// Unset (public) */
// ----------------------------------------------------------------------
// Uninitializes the BVolume.
void void
BVolume::Unset(void) BVolume::Unset()
{ {
fDev = 0L; fDevice = -1;
fCStatus = B_NO_INIT; fCStatus = B_NO_INIT;
} }
// Device
// ---------------------------------------------------------------------- /*! \brief Returns the device ID of the volume the object refers to.
// Device (public) \return Returns the device ID of the volume the object refers to
// ---------------------------------------------------------------------- or -1, if the object is not properly initialized.
// Returns the object's dev_t number. */
dev_t dev_t
BVolume::Device(void) const BVolume::Device() const
{ {
return fDev; return fDevice;
} }
// GetRootDirectory
// ---------------------------------------------------------------------- /*! \brief Returns the root directory of the volume referred to by the object.
// GetRootDirectory (public) \param directory A pointer to a pre-allocated BDirectory to be initialized
// ---------------------------------------------------------------------- to the volume's root directory.
// Initializes dir (which must be allocated) to refer to the volume's \return
// "root directory." The root directory stands at the "root" of the - \c B_OK: Everything went fine.
// volume's file hierarchy. - \c B_BAD_VALUE: \c NULL \a directory or the object is not properly
// initialized.
// NOTE: This isn't necessarily the root of the entire file - another error code
// hierarchy, but only the root of the volume hierarchy. */
//
// This function does not change fDev nor fCStatus.
status_t status_t
BVolume::GetRootDirectory( BVolume::GetRootDirectory(BDirectory *directory) const
BDirectory* dir) const
{ {
status_t currentStatus = fCStatus; // check parameter and initialization
status_t error = (directory && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
if ((dir != NULL) && (currentStatus == B_OK)){ // get FS stat
fs_info info;
// Obtain the device information for the current device if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
// and initialize the passed-in BDirectory object with error = errno;
// the device and root node values. // init the directory
if (error == B_OK) {
fs_info fsInfo; node_ref ref;
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo); ref.device = info.dev;
ref.node = info.root;
if (err != 0) { error = directory->SetTo(&ref);
currentStatus = errno;
} }
else { return error;
node_ref nodeRef;
nodeRef.device = fsInfo.dev;
// NOTE: This should be the same as fDev.
nodeRef.node = fsInfo.root;
currentStatus = dir->SetTo(&nodeRef);
}
}
return currentStatus;
} }
// Capacity
// ---------------------------------------------------------------------- /*! \brief Returns the volume's total storage capacity.
// Capacity (public) \return
// ---------------------------------------------------------------------- - The volume's total storage capacity (in bytes), when the object is
// Returns the volume's total storage capacity (in bytes). properly initialized.
- \c B_BAD_VALUE otherwise.
*/
off_t off_t
BVolume::Capacity(void) const BVolume::Capacity() const
{ {
off_t totalBytes = 0; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
if (fCStatus == B_OK){ // get FS stat
fs_info info;
// Obtain the device information for the current device if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
// and calculate the total storage capacity. error = errno;
return (error == B_OK ? info.total_blocks * info.block_size : error);
fs_info fsInfo;
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo);
if (err == 0) {
totalBytes = fsInfo.block_size * fsInfo.total_blocks;
}
}
return totalBytes;
} }
// FreeBytes
// ---------------------------------------------------------------------- /*! \brief Returns the amount of storage that's currently unused on the
// FreeBytes (public) volume (in bytes).
// ---------------------------------------------------------------------- \return
// Returns the amount of storage that's currently unused on the - The amount of storage that's currently unused on the volume (in bytes),
// volume (in bytes). when the object is properly initialized.
- \c B_BAD_VALUE otherwise.
*/
off_t off_t
BVolume::FreeBytes(void) const BVolume::FreeBytes() const
{ {
off_t remainingBytes = 0L; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
if (fCStatus == B_OK){ // get FS stat
fs_info info;
// Obtain the device information for the current device if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
// and calculate the free storage available. error = errno;
return (error == B_OK ? info.free_blocks * info.block_size : error);
fs_info fsInfo;
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo);
if (err == 0) {
remainingBytes = fsInfo.block_size * fsInfo.free_blocks;
}
}
return remainingBytes;
} }
// GetName
/*! \brief Returns the name of the volume.
// ---------------------------------------------------------------------- The name of the volume is copied into the provided buffer.
// GetName (public)
// ----------------------------------------------------------------------
// Copies the name of the volume into the supplied buffer.
//
// The string pointed to by \a name must be long enough to
// hold the entire volume name. A length of B_PATH_NAME_LENGTH
// is safe and reccommended.
\param name A pointer to a pre-allocated character buffer of size
\c B_FILE_NAME_LENGTH or larger into which the name of the
volume shall be written.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \c NULL \a name or the object is not properly
initialized.
- another error code
*/
status_t status_t
BVolume::GetName( BVolume::GetName(char *name) const
char* name) const
{ {
status_t currentStatus = fCStatus; // check parameter and initialization
status_t error = (name && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
if ((name != NULL) && (currentStatus == B_OK)) { // get FS stat
fs_info info;
// Obtain the device information for the current device if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
// and copies the device name into the buffer. error = errno;
// copy the name
fs_info fsInfo; if (error == B_OK)
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo); strncpy(name, info.volume_name, B_FILE_NAME_LENGTH);
return error;
if (err != 0) {
currentStatus = errno;
}
else {
strcpy(name, fsInfo.volume_name);
currentStatus = B_OK;
}
}
return currentStatus;
} }
// SetName
// ---------------------------------------------------------------------- /*! \brief Sets the name of the volume referred to by this object.
// SetName (public) \param name The volume's new name. Must not be longer than
// ---------------------------------------------------------------------- \c B_FILE_NAME_LENGTH (including the terminating null).
// Sets the name of the volume to the supplied string. \return
// Setting the name is typically (and most politely) the user's - \c B_OK: Everything went fine.
// responsibility (a task that's performed, most easily, through the - \c B_BAD_VALUE: \c NULL \a name or the object is not properly
// Tracker). If you really want to set the name of the volume initialized.
// programmatically, you do so by renaming the volume's root directory. - another error code
*/
status_t status_t
BVolume::SetName( BVolume::SetName(const char *name)
const char* name)
{ {
status_t currentStatus = B_ERROR; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// *** Call a kernel or, more indirectly, a POSIX function if (error == B_OK)
// that sets a volume name *** error = BPrivate::Storage::set_volume_name(fDevice, name);
return error;
return currentStatus;
} }
// GetIcon
// ---------------------------------------------------------------------- /*! \brief Returns the icon of the volume.
// GetIcon (public) \param icon A pointer to a pre-allocated BBitmap of the correct dimension
// ---------------------------------------------------------------------- to store the requested icon (16x16 for the mini and 32x32 for the
// Returns the volume's icon in icon. which specifies the icon to large icon).
// retrieve, either B_MINI_ICON (16x16) or B_LARGE_ICON (32x32). \param which Specifies the size of the icon to be retrieved:
\c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon.
*/
status_t status_t
BVolume::GetIcon( BVolume::GetIcon(BBitmap *icon, icon_size which) const
BBitmap* icon,
icon_size which) const
{ {
status_t currentStatus = fCStatus; // check parameter and initialization
status_t error = (icon && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
if ((icon != NULL) && (currentStatus == B_OK) BRect rect;
&& ((which == B_MINI_ICON) || (which == B_LARGE_ICON))) { if (error == B_OK) {
char deviceName[B_DEV_NAME_LENGTH]; if (which == B_MINI_ICON)
rect.Set(0, 0, 15, 15);
currentStatus = GetName(deviceName); else if (which == B_LARGE_ICON)
rect.Set(0, 0, 31, 31);
if (currentStatus == B_OK) else
{ error = B_BAD_VALUE;
currentStatus = get_device_icon(deviceName, icon, which);
} }
// check whether icon size and bitmap dimensions do match
if (error == B_OK
&& (icon->Bounds() != rect || icon->ColorSpace() != B_CMAP8)) {
error = B_BAD_VALUE;
} }
// get FS stat
return (currentStatus); fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
// get the icon
if (error == B_OK)
error = get_device_icon(info.device_name, icon->Bits(), which);
return error;
} }
// IsRemovable
// ---------------------------------------------------------------------- /*! \brief Returns whether the volume is removable.
// IsRemovable (public) \return \c true, when the object is properly initialized and the
// ---------------------------------------------------------------------- referred to volume is removable, \c false otherwise.
// Tests the volume and returns whether or not it is removable. */
bool bool
BVolume::IsRemovable(void) const BVolume::IsRemovable() const
{ {
bool volumeIsRemovable = false; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// Obtain the device information for the current device // get FS stat
// and determines whether or not the device is removable. fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
fs_info fsInfo; error = errno;
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo); return (error == B_OK && (info.flags & B_FS_IS_REMOVABLE));
if (err == 0) {
volumeIsRemovable = (fsInfo.flags & B_FS_IS_REMOVABLE);
}
return (volumeIsRemovable);
} }
// IsReadOnly
// ---------------------------------------------------------------------- /*! \brief Returns whether the volume is read only.
// IsReadOnly (public) \return \c true, when the object is properly initialized and the
// ---------------------------------------------------------------------- referred to volume is read only, \c false otherwise.
// Tests the volume and returns whether or not it is read-only. */
bool bool
BVolume::IsReadOnly(void) const BVolume::IsReadOnly(void) const
{ {
bool volumeIsReadOnly = false; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// Obtain the device information for the current device // get FS stat
// and determines whether or not the device is read-only. fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
fs_info fsInfo; error = errno;
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo); return (error == B_OK && (info.flags & B_FS_IS_READONLY));
if (err == 0) {
volumeIsReadOnly = (fsInfo.flags & B_FS_IS_READONLY);
}
return (volumeIsReadOnly);
} }
// IsPersistent
// ---------------------------------------------------------------------- /*! \brief Returns whether the volume is persistent.
// IsPersistent (public) \return \c true, when the object is properly initialized and the
// ---------------------------------------------------------------------- referred to volume is persistent, \c false otherwise.
// Tests the volume and returns whether or not it is persistent. */
bool bool
BVolume::IsPersistent(void) const BVolume::IsPersistent(void) const
{ {
bool volumeIsPersistent = false; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// Obtain the device information for the current device // get FS stat
// and determines whether or not the storage medium fs_info info;
// is persistent. if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
fs_info fsInfo; return (error == B_OK && (info.flags & B_FS_IS_PERSISTENT));
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo);
if (err == 0) {
volumeIsPersistent = (fsInfo.flags & B_FS_IS_PERSISTENT);
}
return (volumeIsPersistent);
} }
// IsShared
// ---------------------------------------------------------------------- /*! \brief Returns whether the volume is shared.
// IsShared (public) \return \c true, when the object is properly initialized and the
// ---------------------------------------------------------------------- referred to volume is shared, \c false otherwise.
// Tests the volume and returns whether or not it is shared. */
bool bool
BVolume::IsShared(void) const BVolume::IsShared(void) const
{ {
bool volumeIsShared = false; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// Obtain the device information for the current device // get FS stat
// and determines whether or not the volume is shared fs_info info;
// over a network. if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
fs_info fsInfo; return (error == B_OK && (info.flags & B_FS_IS_SHARED));
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo);
if (err == 0) {
volumeIsShared = (fsInfo.flags & B_FS_IS_SHARED);
}
return (volumeIsShared);
} }
// KnowsMime
// ---------------------------------------------------------------------- /*! \brief Returns whether the volume supports MIME types.
// KnowsMime (public) \return \c true, when the object is properly initialized and the
// ---------------------------------------------------------------------- referred to volume supports MIME types, \c false otherwise.
// Tests the volume and returns whether or not it uses MIME types. */
bool bool
BVolume::KnowsMime(void) const BVolume::KnowsMime(void) const
{ {
bool volumeKnowsMime = false; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// Obtain the device information for the current device // get FS stat
// and determines whether or not the volume supports fs_info info;
// MIME types. if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
fs_info fsInfo; return (error == B_OK && (info.flags & B_FS_HAS_MIME));
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo);
if (err == 0) {
volumeKnowsMime = (fsInfo.flags & B_FS_HAS_MIME);
}
return (volumeKnowsMime);
} }
// KnowsAttr
// ---------------------------------------------------------------------- /*! \brief Returns whether the volume supports attributes.
// KnowsAttr (public) \return \c true, when the object is properly initialized and the
// ---------------------------------------------------------------------- referred to volume supports attributes, \c false otherwise.
// Tests the volume and returns whether or not its files */
// accept attributes.
bool bool
BVolume::KnowsAttr(void) const BVolume::KnowsAttr(void) const
{ {
bool volumeKnowsAttr = false; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// Obtain the device information for the current device // get FS stat
// and determines whether or not the files on the fs_info info;
// volume accept attributes. if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
fs_info fsInfo; return (error == B_OK && (info.flags & B_FS_HAS_ATTR));
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo);
if (err == 0) {
volumeKnowsAttr = (fsInfo.flags & B_FS_HAS_ATTR);
}
return (volumeKnowsAttr);
} }
// KnowsQuery
// ---------------------------------------------------------------------- /*! \brief Returns whether the volume supports queries.
// KnowsQuery (public) \return \c true, when the object is properly initialized and the
// ---------------------------------------------------------------------- referred to volume supports queries, \c false otherwise.
// Tests the volume and returns whether or not it can respond */
// to queries.
bool bool
BVolume::KnowsQuery(void) const BVolume::KnowsQuery(void) const
{ {
bool volumeKnowsQuery = false; // check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// Obtain the device information for the current device // get FS stat
// and determines whether or not the volume can fs_info info;
// respond to queries. if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
fs_info fsInfo; return (error == B_OK && (info.flags & B_FS_HAS_QUERY));
int err = BPrivate::Storage::stat_dev(fDev, &fsInfo);
if (err == 0) {
volumeKnowsQuery = (fsInfo.flags & B_FS_HAS_QUERY);
}
return (volumeKnowsQuery);
} }
// ==
/*! \brief Returns whether two BVolume objects are equal.
// ---------------------------------------------------------------------- Two volume objects are said to be equal, if they either are both
// operator == (public) uninitialized, or both are initialized and refer to the same volume.
// ----------------------------------------------------------------------
// Two BVolume objects are said to be equal if they refer to the
// same volume, or if they're both uninitialized.
// Returns whether or not the volumes are equal.
\param volume The object to be compared with.
\result \c true, if this object and the supplied one are equal, \c false
otherwise.
*/
bool bool
BVolume::operator==( BVolume::operator==(const BVolume &volume) const
const BVolume& vol) const
{ {
// First determine whether both objects are uninitialized, return (InitCheck() != B_OK && volume.InitCheck() != B_OK
// since comparing the fDev members of uninitialized BVolume || fDevice == volume.fDevice);
// instances will return an invalid result.
bool areEqual = ((this->fCStatus == B_NO_INIT)
&& (vol.InitCheck() == B_NO_INIT));
if (!areEqual) {
// The BVolume instance are initialized, test the
// fDev member values:
areEqual = (this->fDev == vol.Device());
}
return (areEqual);
} }
// !=
/*! \brief Returns whether two BVolume objects are unequal.
// ---------------------------------------------------------------------- Two volume objects are said to be equal, if they either are both
// operator != (public) uninitialized, or both are initialized and refer to the same volume.
// ----------------------------------------------------------------------
// Two BVolume objects are said to be equal if they refer to the
// same volume, or if they're both uninitialized.
// Returns whether or not the volumes are not equal.
\param volume The object to be compared with.
\result \c true, if this object and the supplied one are unequal, \c false
otherwise.
*/
bool bool
BVolume::operator!=( BVolume::operator!=(const BVolume &volume) const
const BVolume& vol) const
{ {
bool areNotEqual = !(*this == vol); return !(*this == volume);
return (areNotEqual);
} }
// =
/*! \brief Assigns another BVolume object to this one.
// ---------------------------------------------------------------------- This object is made an exact clone of the supplied one.
// operator = (public)
// ----------------------------------------------------------------------
// In the expression:
//
// BVolume a = b;
//
// BVolume a is initialized to refer to the same volume as b.
// To gauge the success of the assignment, you should call InitCheck()
// immediately afterwards.
//
// Assigning a BVolume to itself is safe.
// Assigning from an uninitialized BVolume is "successful":
// The assigned-to BVolume will also be uninitialized (B_NO_INIT).
\param volume The volume from which shall be assigned.
\return A reference to this object.
*/
BVolume& BVolume&
BVolume::operator=( BVolume::operator=(const BVolume &volume)
const BVolume& vol)
{ {
this->fDev = vol.Device(); if (&volume != this) {
this->fCStatus = vol.InitCheck(); this->fDevice = volume.fDevice;
this->fCStatus = volume.fCStatus;
return (*this); }
return *this;
} }
// FBC // FBC
void BVolume::_TurnUpTheVolume1() {} void BVolume::_ReservedVolume1() {}
void BVolume::_TurnUpTheVolume2() {} void BVolume::_ReservedVolume2() {}
void BVolume::_TurnUpTheVolume3() {} void BVolume::_ReservedVolume3() {}
void BVolume::_TurnUpTheVolume4() {} void BVolume::_ReservedVolume4() {}
void BVolume::_TurnUpTheVolume5() {} void BVolume::_ReservedVolume5() {}
void BVolume::_TurnUpTheVolume6() {} void BVolume::_ReservedVolume6() {}
void BVolume::_TurnUpTheVolume7() {} void BVolume::_ReservedVolume7() {}
void BVolume::_TurnUpTheVolume8() {} void BVolume::_ReservedVolume8() {}
#ifdef USE_OPENBEOS_NAMESPACE #ifdef USE_OPENBEOS_NAMESPACE
} }
#endif #endif
+183 -147
View File
@@ -6,180 +6,216 @@
// //
// Description: BVolumeRoster class // Description: BVolumeRoster class
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/*!
\file VolumeRoster.cpp
BVolumeRoster implementation.
*/
#include <VolumeRoster.h>
#include <Directory.h>
#include <Bitmap.h>
#include <Node.h>
#include <errno.h> #include <errno.h>
#include <new.h>
#include <Bitmap.h>
#include <Directory.h>
#include <fs_info.h> #include <fs_info.h>
#include <kernel_interface.h> #include <kernel_interface.h>
#include <Node.h>
#include <NodeMonitor.h>
#include <VolumeRoster.h>
static const char kBootVolumePath[] = "/boot";
#ifdef USE_OPENBEOS_NAMESPACE #ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS { namespace OpenBeOS {
#endif #endif
// ---------------------------------------------------------------------- /*!
// BVolumeRoster (public) \class BVolumeRoster
// ---------------------------------------------------------------------- \brief A roster of all volumes available in the system
// Default constructor: creates a new BVolumeRoster object.
// You don't have to "initialize" the object before using it (as you do
// with most other Storage Kit classes). You can call GetNextVolume()
// (or another method) immediately after constructing.
BVolumeRoster::BVolumeRoster(void) Provides an interface for iterating through the volumes available in
the system and watching volume mounting/unmounting.
The class wraps the next_dev() function for iterating through the
volume list and the watch_node()/stop_watching() for the watching
features.
\author Vincent Dominguez
\author <a href='mailto:[email protected]'>Ingo Weinhold</a>
\version 0.0.0
*/
/*! \var dev_t BVolumeRoster::fCookie
\brief The iteration cookie for next_dev(). Initialized with 0.
*/
/*! \var dev_t BVolumeRoster::fTarget
\brief BMessenger referring to the target to which the watching
notification messages are sent.
The object is allocated and owned by the roster. \c NULL, if not watching.
*/
// constructor
/*! \brief Creates a new BVolumeRoster.
The object is ready to be used.
*/
BVolumeRoster::BVolumeRoster()
: fCookie(0),
fTarget(NULL)
{ {
#if !_PR3_COMPATIBLE_ }
// Initialize reserved class variables to "safe" values:
_reserved[0] = 0L;
_reserved[1] = 0L;
_reserved[2] = 0L;
// Place this in a separate initialization method at
// a later time.
#endif
fPos = 0; // destructor
/*! \brief Frees all resources associated with this object.
If a watching was activated on (StartWatching()), it is deactived.
*/
BVolumeRoster::~BVolumeRoster()
{
StopWatching();
}
// GetNextVolume
/*! \brief Returns the next volume in the list of available volumes.
\param volume A pointer to a pre-allocated BVolume to be initialized to
refer to the next volume in the list of available volumes.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: The last volume in the list has already been returned.
*/
status_t
BVolumeRoster::GetNextVolume(BVolume *volume)
{
// check parameter
status_t error = (volume ? B_OK : B_BAD_VALUE);
// get next device
dev_t device;
if (error == B_OK) {
device = next_dev(&fCookie);
if (device < 0)
error = device;
}
// init volume
if (error == B_OK)
error = volume->SetTo(device);
return error;
}
// Rewind
/*! \brief Rewinds the list of available volumes such that the next call to
GetNextVolume() will return the first element in the list.
*/
void
BVolumeRoster::Rewind()
{
fCookie = 0;
}
// GetBootVolume
/*! \brief Returns the boot volume.
Currently, this function looks for the volume that is mounted at "/boot".
The only way to fool the system into thinking that there is not a boot
volume is to rename "/boot" -- but, please refrain from doing so...(:o(
\param volume A pointer to a pre-allocated BVolume to be initialized to
refer to the boot volume.
\return
- \c B_OK: Everything went fine.
- an error code otherwise
*/
status_t
BVolumeRoster::GetBootVolume(BVolume *volume)
{
// check parameter
status_t error = (volume ? B_OK : B_BAD_VALUE);
// get device
dev_t device;
if (error == B_OK) {
device = dev_for_path(kBootVolumePath);
if (device < 0)
error = device;
}
// init volume
if (error == B_OK)
error = volume->SetTo(device);
return error;
}
// StartWatching
/*! \brief Starts watching the list of volumes available in the system.
Notifications are sent to the specified target whenever a volume is
mounted or unmounted. The format of the notification messages is
described under watch_node(). Actually BVolumeRoster just provides a
more convenient interface for it.
If StartWatching() has been called before with another target and no
StopWatching() since, StopWatching() is called first, so that the former
target won't receive any notifications anymore.
When the object is destroyed all watching has an end as well.
\param messenger The target to which the notification messages shall be
sent.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: The supplied BMessenger is invalid.
- \c B_NO_MEMORY: Insufficient memory to carry out this operation.
*/
status_t
BVolumeRoster::StartWatching(BMessenger messenger)
{
StopWatching();
status_t error = (messenger.IsValid() ? B_OK : B_ERROR);
// clone messenger
if (error == B_OK) {
fTarget = new(nothrow) BMessenger(messenger);
if (!fTarget)
error = B_NO_MEMORY;
}
// start watching
if (error == B_OK)
error = watch_node(NULL, B_WATCH_MOUNT, messenger);
// cleanup on failure
if (error != B_OK && fTarget) {
delete fTarget;
fTarget = NULL; fTarget = NULL;
}
// ----------------------------------------------------------------------
// ~BVolumeRoster (public, virtual)
// ----------------------------------------------------------------------
// Destructor: Destroys the BVolumeRoster object.
// If this BVolumeRoster object was watching volumes,
// the watch is called off.
BVolumeRoster::~BVolumeRoster(void)
{
}
// ----------------------------------------------------------------------
// GetNextVolume (public)
// ----------------------------------------------------------------------
// Retrieves the "next" volume from the volume list and uses it to
// initialize the argument (which must be allocated). When the function
// returns B_BAD_VALUE, you've reached the end of the list.
status_t
BVolumeRoster::GetNextVolume(BVolume* vol)
{
status_t currentStatus = B_BAD_VALUE;
dev_t deviceID = next_dev(&fPos);
if ((deviceID >= 0) && (vol != NULL))
{
currentStatus = vol->SetTo(deviceID);
} }
return error;
return currentStatus;
} }
// StopWatching
// ---------------------------------------------------------------------- /*! \brief Stops volume watching initiated with StartWatching() before.
// Rewind (public) */
// ----------------------------------------------------------------------
// Rewinds the volume list such that the next call to GetNextVolume()
// will return the first element in the list.
void void
BVolumeRoster::Rewind(void) BVolumeRoster::StopWatching()
{ {
fPos = 0; if (fTarget) {
} stop_watching(*fTarget);
delete fTarget;
fTarget = NULL;
// ----------------------------------------------------------------------
// GetBootVolume (public)
// ----------------------------------------------------------------------
// Initializes boot_vol to refer to the "boot volume." This is the
// volume that was used to boot the computer. boot_vol must be
// allocated before you pass it in. If the boot volume can't be found,
// the argument is uninitialized.
//
// Currently, this function looks for the volume that is mounted at /boot.
// The only way to fool the system into thinking that there is not a boot
// volume is to rename /boot -- but, please refrain from doing so...(:o(
status_t
BVolumeRoster::GetBootVolume(BVolume* boot_vol)
{
int32 pos = 0;
dev_t deviceID = 0;
status_t currentStatus = B_BAD_VALUE;
do {
deviceID = next_dev(&pos);
if(deviceID >= 0) {
fs_info fsInfo;
int err = BPrivate::Storage::stat_dev(deviceID, &fsInfo);
if (err == 0) {
if(std::strcmp(fsInfo.device_name, kBootVolumeName) == 0) {
fPos = pos;
currentStatus = boot_vol->SetTo(deviceID);
break;
} }
}
}
} while(deviceID >= 0);
return currentStatus;
} }
// Messenger
// ---------------------------------------------------------------------- /*! \brief Returns a messenger to the target currently watching the volume
// StartWatching (public) list.
// ---------------------------------------------------------------------- \return A messenger to the target currently watching the volume list, or
// Registers a request for notifications of volume mounts and unmounts. an invalid messenger, if noone is currently watching.
// The notifications are sent (as BMessages) to the BHandler/BLooper */
// pair specified by the argument. There are separate messages for
// mounting and unmounting; their formats are described below.
//
// The caller retains possession of the BHandler/BLooper that the
// BMessenger represents. The volume watching continues until this
// BVolumeRoster object is destroyed, or until you call StopWatching().
status_t
BVolumeRoster::StartWatching(BMessenger msngr)
{
return B_BAD_VALUE;
}
// ----------------------------------------------------------------------
// StopWatching (public)
// ----------------------------------------------------------------------
// Tells the volume-watcher to stop watching. Notifications of volume
// mounts and unmounts are no longer sent to the BVolumeRoster's target.
void
BVolumeRoster::StopWatching(void)
{
}
// ----------------------------------------------------------------------
// Messenger (public)
// ----------------------------------------------------------------------
// Returns a copy of the BMessenger object that was set in the
// previous StartWatching() call.
BMessenger BMessenger
BVolumeRoster::Messenger(void) const BVolumeRoster::Messenger() const
{ {
return *fTarget; return (fTarget ? *fTarget : BMessenger());
} }
// FBC
void BVolumeRoster::_ReservedVolumeRoster1() {}
void BVolumeRoster::_ReservedVolumeRoster2() {}
#ifdef USE_OPENBEOS_NAMESPACE #ifdef USE_OPENBEOS_NAMESPACE
} }
#endif #endif