* Copyright 2002-2009, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Tyler Dauwalder
* Ingo Weinhold
*/
#include <errno.h>
#include <string.h>
#include <Bitmap.h>
#include <Directory.h>
#include <fs_info.h>
#include <Node.h>
#include <Path.h>
#include <Volume.h>
#include <storage_support.h>
#include <syscalls.h>
#include <fs_interface.h>
BVolume::BVolume()
: fDevice((dev_t)-1),
fCStatus(B_NO_INIT)
{
}
BVolume::BVolume(dev_t device)
: fDevice((dev_t)-1),
fCStatus(B_NO_INIT)
{
SetTo(device);
}
BVolume::BVolume(const BVolume &volume)
: fDevice(volume.fDevice),
fCStatus(volume.fCStatus)
{
}
BVolume::~BVolume()
{
}
status_t
BVolume::InitCheck(void) const
{
return fCStatus;
}
status_t
BVolume::SetTo(dev_t device)
{
Unset();
status_t error = (device >= 0 ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
fs_info info;
if (fs_stat_dev(device, &info) != 0)
error = errno;
}
if (error == B_OK)
fDevice = device;
fCStatus = error;
return fCStatus;
}
void
BVolume::Unset()
{
fDevice = (dev_t)-1;
fCStatus = B_NO_INIT;
}
dev_t
BVolume::Device() const
{
return fDevice;
}
status_t
BVolume::GetRootDirectory(BDirectory *directory) const
{
status_t error = (directory && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
if (error == B_OK) {
node_ref ref;
ref.device = info.dev;
ref.node = info.root;
error = directory->SetTo(&ref);
}
return error;
}
off_t
BVolume::Capacity() const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK ? info.total_blocks * info.block_size : error);
}
off_t
BVolume::FreeBytes() const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK ? info.free_blocks * info.block_size : error);
}
off_t
BVolume::BlockSize() const
{
if (InitCheck() != B_OK)
return B_NO_INIT;
fs_info info;
if (fs_stat_dev(fDevice, &info) != 0)
return errno;
return info.block_size;
}
status_t
BVolume::GetName(char *name) const
{
status_t error = (name && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
if (error == B_OK)
strncpy(name, info.volume_name, B_FILE_NAME_LENGTH);
return error;
}
status_t
BVolume::SetName(const char *name)
{
if (!name || InitCheck() != B_OK)
return B_BAD_VALUE;
if (strlen(name) >= B_FILE_NAME_LENGTH)
return B_NAME_TOO_LONG;
fs_info oldInfo;
if (fs_stat_dev(fDevice, &oldInfo) != 0)
return errno;
if (strcmp(name, oldInfo.volume_name) == 0)
return B_OK;
fs_info newInfo;
strlcpy(newInfo.volume_name, name, sizeof(newInfo.volume_name));
status_t error = _kern_write_fs_info(fDevice, &newInfo,
FS_WRITE_FSINFO_NAME);
if (error != B_OK)
return error;
BPath entryPath;
BEntry entry;
BEntry traversedEntry;
node_ref entryNodeRef;
if (BPrivate::Storage::check_entry_name(name) == B_OK
&& BPrivate::Storage::check_entry_name(oldInfo.volume_name) == B_OK
&& entryPath.SetTo("/", oldInfo.volume_name) == B_OK
&& entry.SetTo(entryPath.Path(), false) == B_OK
&& entry.Exists()
&& traversedEntry.SetTo(entryPath.Path(), true) == B_OK
&& traversedEntry.GetNodeRef(&entryNodeRef) == B_OK
&& entryNodeRef.device == fDevice
&& entryNodeRef.node == oldInfo.root) {
entry.Rename(name, false);
}
return error;
}
status_t
BVolume::GetIcon(BBitmap *icon, icon_size which) const
{
if (InitCheck() != B_OK)
return B_NO_INIT;
fs_info info;
if (fs_stat_dev(fDevice, &info) != 0)
return errno;
return get_device_icon(info.device_name, icon, which);
}
status_t
BVolume::GetIcon(uint8** _data, size_t* _size, type_code* _type) const
{
if (InitCheck() != B_OK)
return B_NO_INIT;
fs_info info;
if (fs_stat_dev(fDevice, &info) != 0)
return errno;
return get_device_icon(info.device_name, _data, _size, _type);
}
bool
BVolume::IsRemovable() const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK && (info.flags & B_FS_IS_REMOVABLE));
}
bool
BVolume::IsReadOnly(void) const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK && (info.flags & B_FS_IS_READONLY));
}
bool
BVolume::IsPersistent(void) const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK && (info.flags & B_FS_IS_PERSISTENT));
}
bool
BVolume::IsShared(void) const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK && (info.flags & B_FS_IS_SHARED));
}
bool
BVolume::KnowsMime(void) const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK && (info.flags & B_FS_HAS_MIME));
}
bool
BVolume::KnowsAttr(void) const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK && (info.flags & B_FS_HAS_ATTR));
}
bool
BVolume::KnowsQuery(void) const
{
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
fs_info info;
if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
error = errno;
return (error == B_OK && (info.flags & B_FS_HAS_QUERY));
}
bool
BVolume::operator==(const BVolume &volume) const
{
return ((InitCheck() != B_OK && volume.InitCheck() != B_OK)
|| fDevice == volume.fDevice);
}
bool
BVolume::operator!=(const BVolume &volume) const
{
return !(*this == volume);
}
BVolume&
BVolume::operator=(const BVolume &volume)
{
if (&volume != this) {
this->fDevice = volume.fDevice;
this->fCStatus = volume.fCStatus;
}
return *this;
}
void BVolume::_TurnUpTheVolume1() {}
void BVolume::_TurnUpTheVolume2() {}
void BVolume::_TurnUpTheVolume3() {}
void BVolume::_TurnUpTheVolume4() {}
void BVolume::_TurnUpTheVolume5() {}
void BVolume::_TurnUpTheVolume6() {}
void BVolume::_TurnUpTheVolume7() {}
void BVolume::_TurnUpTheVolume8() {}