Files
haiku-beta6/src/kits/storage/DiskDevice.cpp
T
Ingo Weinhold ca9e5772c3 * Reintroduced third LinkAgainst parameter <mapLibs>, defaulting to true.
Library names are now mapped for all targets but "host" (not only for
  "haiku") -- added one more level of indirection to achieve that.
  (TARGET_LIBRARY_NAME_MAP -> *_LIBRARY_NAME_MAP_*).
* Renamed build/HaikuBuildCompatibility.h to BeOSBuildCompatibility.h
  (auto-included when compiling something that uses the Be API for platform
  "host" on anon-BeOS platform), and introduced build/HaikuBuildCompatibility.h,
  which can be included when compiling something that can be built for both,
  Haiku and BeOS compatible platforms.
* Introduced libhaikucompat.a, a library that adds a few functions existing
  under Haiku, but not under BeOS.
* New rule AddSubDirSupportedPlatforms.
* Renamed libopenbeos.so to libbe_haiku.so.
* Introduced new target platform "libbe_test", which is basically equivalent
  to a BeOS compatible host platform target, with the exception, that instead
  of the host platform's libbe.so a special build of Haiku's libbe.so
  (libbe_haiku.so (formerly known as libopenbeos.so)) is used. Furthermore
  Haiku's public app, interface, storage, and support kit headers are used
  when compiling. This replaces the less nice way in which the test app server
  and applications for this test environment were built.
  When building for platform "libbe_test", the library name "be" is
  autotranslated to "libbe_haiku.so". Thus most applications don't need
  special fiddling when them building them for the app server test environment;
  usually an "AddSubDirSupportedPlatforms libbe_test ;" will suffice.
* Reduced the dependencies of <syscalls.h> and fixed problems caused by this
  (e.g. source files not including the needed headers directly).



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14749 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-07 16:07:25 +00:00

387 lines
8.6 KiB
C++

//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//---------------------------------------------------------------------
#include <DiskDevice.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <new.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <DiskDevice.h>
#include <DiskDeviceVisitor.h>
#include <Drivers.h>
#include <Message.h>
#include <Path.h>
#include <syscalls.h>
#include <disk_device_manager/ddm_userland_interface.h>
/*! \class BDiskDevice
\brief A BDiskDevice object represents a storage device.
*/
// constructor
/*! \brief Creates an uninitialized BDiskDevice object.
*/
BDiskDevice::BDiskDevice()
: fDeviceData(NULL)
{
}
// destructor
/*! \brief Frees all resources associated with this object.
*/
BDiskDevice::~BDiskDevice()
{
}
// HasMedia
/*! \brief Returns whether the device contains a media.
\return \c true, if the device contains a media, \c false otherwise.
*/
bool
BDiskDevice::HasMedia() const
{
return (fDeviceData
&& fDeviceData->device_flags & B_DISK_DEVICE_HAS_MEDIA);
}
// IsRemovableMedia
/*! \brief Returns whether the device media are removable.
\return \c true, if the device media are removable, \c false otherwise.
*/
bool
BDiskDevice::IsRemovableMedia() const
{
return (fDeviceData
&& fDeviceData->device_flags & B_DISK_DEVICE_REMOVABLE);
}
// IsReadOnlyMedia
bool
BDiskDevice::IsReadOnlyMedia() const
{
return (fDeviceData
&& fDeviceData->device_flags & B_DISK_DEVICE_READ_ONLY);
}
// IsWriteOnceMedia
bool
BDiskDevice::IsWriteOnceMedia() const
{
return (fDeviceData
&& fDeviceData->device_flags & B_DISK_DEVICE_WRITE_ONCE);
}
// Eject
/*! \brief Eject the device's media.
The device media must, of course, be removable, and the device must
support ejecting the media.
\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
*/
status_t
BDiskDevice::Eject(bool update)
{
/* // 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;
*/
// not implemented
return B_ERROR;
}
// SetTo
status_t
BDiskDevice::SetTo(partition_id id)
{
return _SetTo(id, true, false, 0);
}
// Update
/*! \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.
\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.
\return \c B_OK, if the update went fine, another error code otherwise.
*/
status_t
BDiskDevice::Update(bool *updated)
{
return _Update(_IsShadow(), updated);
}
// Unset
void
BDiskDevice::Unset()
{
BPartition::_Unset();
free(fDeviceData);
fDeviceData = NULL;
}
// InitCheck
status_t
BDiskDevice::InitCheck() const
{
return (fDeviceData ? B_OK : B_NO_INIT);
}
// GetPath
status_t
BDiskDevice::GetPath(BPath *path) const
{
if (!path || !fDeviceData)
return B_BAD_VALUE;
return path->SetTo(fDeviceData->path);
}
// IsModified
bool
BDiskDevice::IsModified() const
{
return (InitCheck() == B_OK && _IsShadow()
&& _kern_is_disk_device_modified(ID()));
}
// PrepareModifications
status_t
BDiskDevice::PrepareModifications()
{
// check initialization
status_t error = InitCheck();
if (error != B_OK)
return error;
if (_IsShadow())
return B_ERROR;
// ask kernel to prepare for modifications
error = _kern_prepare_disk_device_modifications(ID());
if (error != B_OK)
return error;
// update
error = _Update(true, NULL);
if (error != B_OK) {
// bad -- cancelling the modifications is all we can do
_kern_cancel_disk_device_modifications(ID());
}
return error;
}
// CommitModifications
status_t
BDiskDevice::CommitModifications(bool synchronously,
BMessenger progressMessenger,
bool receiveCompleteProgressUpdates)
{
status_t error = InitCheck();
if (error != B_OK)
return error;
if (!_IsShadow())
return B_BAD_VALUE;
// TODO: Get port and token from the progressMessenger
port_id port = -1;
int32 token = -1;
error = _kern_commit_disk_device_modifications(ID(), port, token,
receiveCompleteProgressUpdates);
if (error == B_OK)
error = _SetTo(ID(), true, false, 0);
return error;
}
// CancelModifications
status_t
BDiskDevice::CancelModifications()
{
status_t error = InitCheck();
if (error != B_OK)
return error;
if (!_IsShadow())
return B_BAD_VALUE;
error = _kern_cancel_disk_device_modifications(ID());
if (error == B_OK)
error = _SetTo(ID(), true, false, 0);
return error;
}
// copy constructor
/*! \brief Privatized copy constructor to avoid usage.
*/
BDiskDevice::BDiskDevice(const BDiskDevice &)
{
}
// =
/*! \brief Privatized assignment operator to avoid usage.
*/
BDiskDevice &
BDiskDevice::operator=(const BDiskDevice &)
{
return *this;
}
// _GetData
status_t
BDiskDevice::_GetData(partition_id id, bool deviceOnly, bool shadow,
size_t neededSize, user_disk_device_data **data)
{
// get the device data
void *buffer = NULL;
size_t bufferSize = 0;
if (neededSize > 0) {
// allocate initial buffer
buffer = malloc(neededSize);
if (!buffer)
return B_NO_MEMORY;
bufferSize = neededSize;
}
status_t error = B_OK;
do {
error = _kern_get_disk_device_data(id, deviceOnly, shadow,
(user_disk_device_data*)buffer,
bufferSize, &neededSize);
if (error == B_BUFFER_OVERFLOW) {
// buffer to small re-allocate it
if (buffer)
free(buffer);
buffer = malloc(neededSize);
if (buffer)
bufferSize = neededSize;
else
error = B_NO_MEMORY;
}
} while (error == B_BUFFER_OVERFLOW);
// set result / cleanup on error
if (error == B_OK)
*data = (user_disk_device_data*)buffer;
else if (buffer)
free(buffer);
return error;
}
// _SetTo
status_t
BDiskDevice::_SetTo(partition_id id, bool deviceOnly, bool shadow,
size_t neededSize)
{
Unset();
// get the device data
user_disk_device_data *data = NULL;
status_t error = _GetData(id, deviceOnly, shadow, neededSize, &data);
// set the data
if (error == B_OK)
error = _SetTo(data);
// cleanup on error
if (error != B_OK && data)
free(data);
return error;
}
// _SetTo
status_t
BDiskDevice::_SetTo(user_disk_device_data *data)
{
Unset();
if (!data)
return B_BAD_VALUE;
fDeviceData = data;
status_t error = BPartition::_SetTo(this, NULL,
&fDeviceData->device_partition_data);
if (error != B_OK) {
// If _SetTo() fails, the caller retains ownership of the supplied
// data. So, unset fDeviceData before calling Unset().
fDeviceData = NULL;
Unset();
}
return error;
}
// _Update
status_t
BDiskDevice::_Update(bool shadow, bool *updated)
{
if (InitCheck() != B_OK)
return InitCheck();
// get the device data
user_disk_device_data *data = NULL;
status_t error = _GetData(ID(), true, shadow, 0, &data);
// set the data
if (error == B_OK)
error = _Update(data, updated);
// cleanup on error
if (error != B_OK && data)
free(data);
return error;
}
// _Update
status_t
BDiskDevice::_Update(user_disk_device_data *data, bool *updated)
{
if (!data || !fDeviceData || ID() != data->device_partition_data.id)
return B_BAD_VALUE;
bool _updated;
if (!updated)
updated = &_updated;
*updated = false;
// remove obsolete partitions
status_t error = _RemoveObsoleteDescendants(&data->device_partition_data,
updated);
if (error != B_OK)
return error;
// update existing partitions and add new ones
error = BPartition::_Update(&data->device_partition_data, updated);
if (error == B_OK) {
user_disk_device_data *oldData = fDeviceData;
fDeviceData = data;
// check for changes
if (data->device_flags != oldData->device_flags
|| strcmp(data->path, oldData->path)) {
*updated = true;
}
free(oldData);
}
return error;
}
// _AcceptVisitor
bool
BDiskDevice::_AcceptVisitor(BDiskDeviceVisitor *visitor, int32 level)
{
return visitor->Visit(this);
}