// RootVolume.cpp
#include "RootVolume.h"
#include <new>
#include <AutoLocker.h>
#include "Compatibility.h"
#include "DebugSupport.h"
#include "ExtendedServerInfo.h"
#include "NetAddress.h"
#include "netfs_ioctl.h"
#include "ServerVolume.h"
#include "TaskManager.h"
#include "VolumeManager.h"
#include "VolumeSupport.h"
static const int32 kOptimalIOSize = 64 * 1024;
static const char* kFSName = "netfs";
// constructor
RootVolume::RootVolume(VolumeManager* volumeManager)
: VirtualVolume(volumeManager)
{
}
// destructor
RootVolume::~RootVolume()
{
}
// Init
status_t
RootVolume::Init()
{
status_t error = VirtualVolume::Init("Network");
if (error != B_OK)
return error;
// create and init the server manager
fServerManager = new(std::nothrow) ServerManager(this);
if (!fServerManager)
RETURN_ERROR(B_NO_MEMORY);
error = fServerManager->Init();
if (error != B_OK)
RETURN_ERROR(error);
return B_OK;
}
// Uninit
void
RootVolume::Uninit()
{
// delete the server manager
delete fServerManager;
fServerManager = NULL;
VirtualVolume::Uninit();
}
// PrepareToUnmount
void
RootVolume::PrepareToUnmount()
{
VirtualVolume::PrepareToUnmount();
}
// #pragma mark -
// #pragma mark ----- FS -----
// Mount
status_t
RootVolume::Mount(const char* device, uint32 flags, const char* parameters,
int32 len)
{
status_t error = NewVNode(fRootNode->GetID(), fRootNode);
if (error != B_OK)
RETURN_ERROR(error);
// start the server manager
fServerManager->Run();
return B_OK;
}
// Unmount
status_t
RootVolume::Unmount()
{
Uninit();
return B_OK;
}
// Sync
status_t
RootVolume::Sync()
{
return B_BAD_VALUE;
}
// ReadFSStat
status_t
RootVolume::ReadFSStat(fs_info* info)
{
info->flags = B_FS_IS_PERSISTENT | B_FS_HAS_MIME | B_FS_HAS_ATTR
| B_FS_IS_SHARED | B_FS_HAS_QUERY;
if (fVolumeManager->GetMountFlags() & B_MOUNT_READ_ONLY)
info->flags |= B_FS_IS_READONLY;
info->block_size = 1024;
info->io_size = kOptimalIOSize;
info->total_blocks = 0; // TODO: We could at least fill this in.
info->free_blocks = LONGLONG_MAX / info->block_size;
// keep the Tracker happy
strcpy(info->device_name, "");
strcpy(info->volume_name, GetName());
strcpy(info->fsh_name, kFSName);
return B_OK;
}
// WriteFSStat
status_t
RootVolume::WriteFSStat(struct fs_info* info, int32 mask)
{
// TODO: Allow editing the volume name.
return B_BAD_VALUE;
}
// #pragma mark -
// #pragma mark ----- files -----
// IOCtl
status_t
RootVolume::IOCtl(Node* node, void* cookie, int cmd, void* buffer,
size_t bufferSize)
{
if (node != fRootNode)
return B_BAD_VALUE;
switch (cmd) {
case NET_FS_IOCTL_ADD_SERVER:
{
// check the parameters
if (!buffer)
return B_BAD_VALUE;
netfs_ioctl_add_server* params = (netfs_ioctl_add_server*)buffer;
int32 serverNameLen = strnlen(params->serverName,
sizeof(params->serverName));
if (serverNameLen == 0
|| serverNameLen == sizeof(params->serverName)) {
return B_BAD_VALUE;
}
PRINT("RootVolume::IOCtl(): NET_FS_IOCTL_ADD_SERVER: "
"`%s'\n", params->serverName);
// get the server address
NetAddress netAddress;
NetAddressResolver resolver;
status_t error = resolver.GetHostAddress(params->serverName, &netAddress);
if (error != B_OK)
return error;
// ask the server manager to add the server
return fServerManager->AddServer(netAddress);
}
case NET_FS_IOCTL_REMOVE_SERVER:
{
// check the parameters
if (!buffer)
return B_BAD_VALUE;
netfs_ioctl_remove_server* params
= (netfs_ioctl_remove_server*)buffer;
int32 serverNameLen = strnlen(params->serverName,
sizeof(params->serverName));
if (serverNameLen == 0
|| serverNameLen == sizeof(params->serverName)) {
return B_BAD_VALUE;
}
PRINT("RootVolume::IOCtl(): NET_FS_IOCTL_REMOVE_SERVER:"
" `%s'\n", params->serverName);
// get the server volume
ServerVolume* serverVolume = _GetServerVolume(params->serverName);
if (!serverVolume)
return B_ENTRY_NOT_FOUND;
VolumePutter volumePutter(serverVolume);
// ask the server manager to remove the server
fServerManager->RemoveServer(serverVolume->GetServerAddress());
return B_OK;
}
default:
PRINT("RootVolume::IOCtl(): unknown ioctl: %d\n", cmd);
return B_BAD_VALUE;
break;
}
return B_BAD_VALUE;
}
// #pragma mark -
// ServerAdded
void
RootVolume::ServerAdded(ExtendedServerInfo* serverInfo)
{
PRINT("RootVolume::ServerAdded(%s)\n", serverInfo->GetServerName());
// check, if the server does already exist
ServerVolume* serverVolume = _GetServerVolume(serverInfo->GetAddress());
if (serverVolume) {
WARN("RootVolume::ServerAdded(): WARNING: ServerVolume does "
"already exist.\n");
serverVolume->PutVolume();
return;
}
AutoLocker<Locker> locker(fLock);
// get a unique name for the server
char serverName[B_FILE_NAME_LENGTH];
status_t error = GetUniqueEntryName(serverInfo->GetServerName(),
serverName);
if (error != B_OK)
return;
// create a server volume
serverVolume = new(std::nothrow) ServerVolume(fVolumeManager, serverInfo);
if (!serverVolume)
return;
error = serverVolume->Init(serverName);
if (error != B_OK) {
delete serverVolume;
return;
}
// add the volume to the volume manager
error = fVolumeManager->AddVolume(serverVolume);
if (error != B_OK) {
delete serverVolume;
return;
}
VolumePutter volumePutter(serverVolume);
// add the volume to us
locker.Unlock();
error = AddChildVolume(serverVolume);
if (error != B_OK) {
serverVolume->SetUnmounting(true);
return;
}
}
// ServerUpdated
void
RootVolume::ServerUpdated(ExtendedServerInfo* oldInfo,
ExtendedServerInfo* newInfo)
{
PRINT("RootVolume::ServerUpdated(%s)\n", newInfo->GetServerName());
// get the volume
ServerVolume* serverVolume = _GetServerVolume(newInfo->GetAddress());
if (!serverVolume)
return;
// set the new server info
VolumePutter _(serverVolume);
serverVolume->SetServerInfo(newInfo);
}
// ServerRemoved
void
RootVolume::ServerRemoved(ExtendedServerInfo* serverInfo)
{
PRINT("RootVolume::ServerRemoved(%s)\n", serverInfo->GetServerName());
// get the volume
ServerVolume* serverVolume = _GetServerVolume(serverInfo->GetAddress());
if (!serverVolume)
return;
// set it to unmounting
VolumePutter _(serverVolume);
serverVolume->SetUnmounting(true);
}
// #pragma mark -
// _GetServerVolume
ServerVolume*
RootVolume::_GetServerVolume(const char* name)
{
Volume* volume = GetChildVolume(name);
if (!volume)
return NULL;
if (ServerVolume* serverVolume = dynamic_cast<ServerVolume*>(volume))
return serverVolume;
fVolumeManager->PutVolume(volume);
return NULL;
}
// _GetServerVolume
ServerVolume*
RootVolume::_GetServerVolume(const NetAddress& address)
{
AutoLocker<Locker> locker(fLock);
// init a directory iterator
VirtualDirIterator iterator;
iterator.SetDirectory(fRootNode, true);
// iterate through the directory
const char* name;
Node* node;
while (iterator.GetCurrentEntry(&name, &node)) {
iterator.NextEntry();
ServerVolume* volume = dynamic_cast<ServerVolume*>(node->GetVolume());
if (volume && volume->GetServerAddress().GetIP() == address.GetIP()) {
return dynamic_cast<ServerVolume*>(
fVolumeManager->GetVolume(node->GetID()));
}
}
return NULL;
}
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fServerManager.