Added notification support for the mounting and mount point moving events. Several fixes.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2680 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2003-02-10 00:23:46 +00:00
parent c947b11347
commit 30bb74bbd2
8 changed files with 377 additions and 64 deletions

View File

@ -7,30 +7,33 @@
#include <RegistrarDefs.h>
#include "DiskDeviceManager.h"
#include "Debug.h"
#include "EventMaskWatcher.h"
#include "RDiskDevice.h"
#include "RDiskDeviceList.h"
#include "RPartition.h"
#include "RSession.h"
#include "Debug.h"
enum {
REQUEST_PRIORITY = 0,
NODE_MONITOR_PRIORITY = 10,
REQUEST_PRIORITY = 0,
NODE_MONITOR_PRIORITY = 10,
WATCHING_REQUEST_PRIORITY = 20,
};
// constructor
DiskDeviceManager::DiskDeviceManager()
: BLooper("disk device manager"),
fDeviceListLock(),
fWatchingService(),
fVolumeList(BMessenger(this), fDeviceListLock),
fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList),
fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList,
&fWatchingService),
fMessageQueue(),
fWorker(-1),
fMessageCounter(-1),
fTerminating(false)
{
// set up the device list
fVolumeList.Rescan();
fVolumeList.Dump();
fDeviceList.Rescan();
fDeviceList.Dump();
@ -61,10 +64,14 @@ DiskDeviceManager::MessageReceived(BMessage *message)
case B_REG_NEXT_DISK_DEVICE:
case B_REG_GET_DISK_DEVICE:
case B_REG_UPDATE_DISK_DEVICE:
DetachCurrentMessage();
if (!_PushMessage(message, REQUEST_PRIORITY))
delete message;
break;
case B_REG_DEVICE_START_WATCHING:
case B_REG_DEVICE_STOP_WATCHING:
DetachCurrentMessage();
if (!_PushMessage(message, REQUEST_PRIORITY))
if (!_PushMessage(message, WATCHING_REQUEST_PRIORITY))
delete message;
break;
case B_NODE_MONITOR:
@ -80,13 +87,14 @@ DiskDeviceManager::MessageReceived(BMessage *message)
// _NextDiskDeviceRequest
void
DiskDeviceManager::_NextDiskDeviceRequest(BMessage *message)
DiskDeviceManager::_NextDiskDeviceRequest(BMessage *request)
{
FUNCTION_START();
Lock();
status_t error = B_OK;
int32 cookie = 0;
BMessage reply(B_REG_RESULT);
if (message->FindInt32("cookie", &cookie) == B_OK) {
if (request->FindInt32("cookie", &cookie) == B_OK) {
// get next device
if (RDiskDevice *device = fDeviceList.DeviceWithID(cookie, false)) {
// archive device
@ -103,23 +111,25 @@ DiskDeviceManager::_NextDiskDeviceRequest(BMessage *message)
SET_ERROR(error, B_BAD_VALUE);
// add result and send reply
reply.AddInt32("result", error);
message->SendReply(&reply);
request->SendReply(&reply);
Unlock();
}
// _GetDiskDeviceRequest
void
DiskDeviceManager::_GetDiskDeviceRequest(BMessage *message)
DiskDeviceManager::_GetDiskDeviceRequest(BMessage *request)
{
Lock();
status_t error = B_ENTRY_NOT_FOUND;
// get the device
RDiskDevice *device = NULL;
int32 id = 0;
if (message->FindInt32("device_id", &id) == B_OK)
if (request->FindInt32("device_id", &id) == B_OK)
device = fDeviceList.DeviceWithID(id);
else if (message->FindInt32("session_id", &id) == B_OK) {
else if (request->FindInt32("session_id", &id) == B_OK) {
if (RSession *session = fDeviceList.SessionWithID(id))
device = session->Device();
} else if (message->FindInt32("partition_id", &id) == B_OK) {
} else if (request->FindInt32("partition_id", &id) == B_OK) {
if (RPartition *partition = fDeviceList.PartitionWithID(id))
device = partition->Device();
} else
@ -134,13 +144,15 @@ DiskDeviceManager::_GetDiskDeviceRequest(BMessage *message)
}
// add result and send reply
reply.AddInt32("result", error);
message->SendReply(&reply);
request->SendReply(&reply);
Unlock();
}
// _UpdateDiskDeviceRequest
void
DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *request)
{
Lock();
status_t error = B_ENTRY_NOT_FOUND;
// get the device and check the object is up to date
bool upToDate = false;
@ -148,20 +160,20 @@ DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
int32 id = 0;
int32 changeCounter = 0;
uint32 policy = 0;
if (message->FindInt32("change_counter", &changeCounter) != B_OK
|| message->FindInt32("update_policy", (int32*)&policy) != B_OK) {
// bad request message
if (request->FindInt32("change_counter", &changeCounter) != B_OK
|| request->FindInt32("update_policy", (int32*)&policy) != B_OK) {
// bad request request
SET_ERROR(error, B_BAD_VALUE);
} else if (message->FindInt32("device_id", &id) == B_OK) {
} else if (request->FindInt32("device_id", &id) == B_OK) {
device = fDeviceList.DeviceWithID(id);
if (device)
upToDate = (device->ChangeCounter() == changeCounter);
} else if (message->FindInt32("session_id", &id) == B_OK) {
} else if (request->FindInt32("session_id", &id) == B_OK) {
if (RSession *session = fDeviceList.SessionWithID(id)) {
device = session->Device();
upToDate = (session->ChangeCounter() == changeCounter);
}
} else if (message->FindInt32("partition_id", &id) == B_OK) {
} else if (request->FindInt32("partition_id", &id) == B_OK) {
if (RPartition *partition = fDeviceList.PartitionWithID(id)) {
device = partition->Device();
upToDate = (partition->ChangeCounter() == changeCounter);
@ -184,9 +196,66 @@ DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
if (error == B_OK)
error = reply.AddBool("up_to_date", upToDate);
reply.AddInt32("result", error);
message->SendReply(&reply);
request->SendReply(&reply);
Unlock();
}
// _StartWatchingRequest
void
DiskDeviceManager::_StartWatchingRequest(BMessage *request)
{
FUNCTION_START();
Lock();
status_t error = B_OK;
// get the parameters
BMessenger target;
uint32 events;
if (error == B_OK
&& (request->FindMessenger("target", &target) != B_OK
|| request->FindInt32("events", (int32*)&events) != B_OK)) {
SET_ERROR(error, B_BAD_VALUE);
}
// add the new watcher
if (error == B_OK) {
Watcher *watcher = new(nothrow) EventMaskWatcher(target, events);
if (watcher) {
if (!fWatchingService.AddWatcher(watcher)) {
SET_ERROR(error, B_NO_MEMORY);
delete watcher;
}
} else
SET_ERROR(error, B_NO_MEMORY);
}
// add result and send reply
BMessage reply(B_REG_RESULT);
reply.AddInt32("result", error);
request->SendReply(&reply);
Unlock();
};
// _StopWatchingRequest
void
DiskDeviceManager::_StopWatchingRequest(BMessage *request)
{
FUNCTION_START();
Lock();
status_t error = B_OK;
// get the parameters
BMessenger target;
if (error == B_OK && request->FindMessenger("target", &target) != B_OK)
error = B_BAD_VALUE;
// remove the watcher
if (error == B_OK) {
if (!fWatchingService.RemoveWatcher(target))
error = B_BAD_VALUE;
}
// add result and send reply
BMessage reply(B_REG_RESULT);
reply.AddInt32("result", error);
request->SendReply(&reply);
Unlock();
};
// _PushMessage
bool
DiskDeviceManager::_PushMessage(BMessage *message, int32 priority)
@ -233,7 +302,10 @@ DiskDeviceManager::_Worker()
_UpdateDiskDeviceRequest(message);
break;
case B_REG_DEVICE_START_WATCHING:
_StartWatchingRequest(message);
break;
case B_REG_DEVICE_STOP_WATCHING:
_StopWatchingRequest(message);
break;
case B_NODE_MONITOR:
{

View File

@ -13,6 +13,7 @@
#include "PriorityMessageQueue.h"
#include "RDiskDeviceList.h"
#include "RVolumeList.h"
#include "WatchingService.h"
class DiskDeviceManager : public BLooper {
public:
@ -23,9 +24,11 @@ public:
private:
// requests
void _NextDiskDeviceRequest(BMessage *message);
void _GetDiskDeviceRequest(BMessage *message);
void _UpdateDiskDeviceRequest(BMessage *message);
void _NextDiskDeviceRequest(BMessage *request);
void _GetDiskDeviceRequest(BMessage *request);
void _UpdateDiskDeviceRequest(BMessage *request);
void _StartWatchingRequest(BMessage *request);
void _StopWatchingRequest(BMessage *request);
bool _PushMessage(BMessage *message, int32 priority);
BMessage *_PopMessage();
@ -35,6 +38,7 @@ private:
private:
BLocker fDeviceListLock;
WatchingService fWatchingService;
RVolumeList fVolumeList;
RDiskDeviceList fDeviceList;
PriorityMessageQueue fMessageQueue;

View File

@ -141,10 +141,10 @@ RDiskDevice::RemoveSession(int32 index)
{
RSession *session = SessionAt(index);
if (session) {
session->SetDevice(NULL);
fSessions.RemoveItemAt(index);
if (RDiskDeviceList *deviceList = DeviceList())
deviceList->SessionRemoved(session);
session->SetDevice(NULL);
fSessions.RemoveItemAt(index);
delete session;
}
return (session != NULL);

View File

@ -12,6 +12,7 @@
#include <sys/stat.h>
#include <Directory.h>
#include <DiskDeviceRoster.h>
#include <Drivers.h>
#include <Entry.h>
#include <Locker.h>
@ -19,24 +20,13 @@
#include "RDiskDeviceList.h"
#include "Debug.h"
#include "EventMaskWatcher.h"
#include "RDiskDevice.h"
#include "RPartition.h"
#include "RSession.h"
#include "WatchingService.h"
// compare_ids
/*template<typename T>
static
int
compare_ids(const T *object1, const T *object2)
{
int32 id1 = object1->ID();
int32 id2 = object2->ID();
if (id1 < id2)
return -1;
if (id1 > id2)
return 1;
return 0;
}*/
namespace RDiskDeviceListPredicates {
// CompareIDPredicate
template <typename T>
@ -71,14 +61,36 @@ private:
const char *fPath;
};
// ComparePartitionPathPredicate
struct ComparePartitionPathPredicate : public UnaryPredicate<RPartition> {
ComparePartitionPathPredicate(const char *path) : fPath(path) {}
virtual int operator()(const RPartition *partition) const
{
char path[B_FILE_NAME_LENGTH];
partition->GetPath(path);
return strcmp(fPath, path);
}
private:
const char *fPath;
};
} // namespace RDiskDeviceListPredicates
using namespace RDiskDeviceListPredicates;
// constructor
RDiskDeviceList::RDiskDeviceList(BMessenger target, BLocker &lock,
RVolumeList &volumeList)
RVolumeList &volumeList,
WatchingService *watchingService)
: MessageHandler(),
RVolumeListListener(),
fLock(lock),
fTarget(target),
fVolumeList(volumeList),
fWatchingService(watchingService),
fDevices(20, true),
fSessions(40, false),
fPartitions(80, false)
@ -110,6 +122,21 @@ void
RDiskDeviceList::VolumeMounted(const RVolume *volume)
{
PRINT(("RDiskDeviceList::VolumeMounted(%ld)\n", volume->ID()));
Lock();
// get the partition and set its volume
const char *devicePath = volume->DevicePath();
if (RPartition *partition = PartitionWithPath(devicePath)) {
partition->SetVolume(volume);
// send notifications
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification,
B_DEVICE_PARTITION_MOUNTED, B_DEVICE_CAUSE_UNKNOWN,
partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
Unlock();
}
// VolumeUnmounted
@ -117,13 +144,46 @@ void
RDiskDeviceList::VolumeUnmounted(const RVolume *volume)
{
PRINT(("RDiskDeviceList::VolumeUnmounted(%ld)\n", volume->ID()));
Lock();
// get the partition and set its volume
const char *devicePath = volume->DevicePath();
if (RPartition *partition = PartitionWithPath(devicePath)) {
partition->SetVolume(NULL);
// send notifications
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification,
B_DEVICE_PARTITION_UNMOUNTED, B_DEVICE_CAUSE_UNKNOWN,
partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
Unlock();
}
// MountPointMoved
void
RDiskDeviceList::MountPointMoved(const RVolume *volume)
RDiskDeviceList::MountPointMoved(const RVolume *volume,
const entry_ref *oldRoot,
const entry_ref *newRoot)
{
PRINT(("RDiskDeviceList::MountPointMoved(%ld)\n", volume->ID()));
Lock();
// get the partition
const char *devicePath = volume->DevicePath();
if (RPartition *partition = PartitionWithPath(devicePath)) {
// send notifications
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification,
B_DEVICE_MOUNT_POINT_MOVED, B_DEVICE_CAUSE_UNKNOWN,
partition) == B_OK
&& notification.AddRef("old_directory", oldRoot) == B_OK
&& notification.AddRef("new_directory", newRoot) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNT_POINT);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
Unlock();
}
// AddDevice
@ -145,9 +205,9 @@ RDiskDeviceList::RemoveDevice(int32 index)
{
RDiskDevice *device = DeviceAt(index);
if (device) {
DeviceRemoved(device);
device->SetDeviceList(NULL);
fDevices.RemoveItemAt(index);
DeviceRemoved(device);
delete device;
}
return (device != NULL);
@ -206,6 +266,15 @@ RDiskDeviceList::DeviceWithPath(const char *path) const
return const_cast<RDiskDevice*>(device);
}
// PartitionWithPath
RPartition *
RDiskDeviceList::PartitionWithPath(const char *path) const
{
const RPartition *partition
= fPartitions.FindIf(ComparePartitionPathPredicate(path));
return const_cast<RPartition*>(partition);
}
// Rescan
status_t
RDiskDeviceList::Rescan()
@ -273,6 +342,8 @@ RDiskDeviceList::DeviceRemoved(RDiskDevice *device, uint32 cause)
void
RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
{
// add the session to our list
fSessions.BinaryInsert(session, CompareIDPredicate<RSession>(session));
// propagate to partitions
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
@ -284,6 +355,12 @@ RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
void
RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause)
{
// remove the session from our list
bool success = false;
int32 index = fSessions.FindBinaryInsertionIndex(
CompareIDPredicate<RSession>(session), &success);
if (success)
fSessions.RemoveItemAt(index);
// propagate to partitions
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
@ -295,6 +372,9 @@ RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause)
void
RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause)
{
// add the partition to our list
fPartitions.BinaryInsert(partition,
CompareIDPredicate<RPartition>(partition));
// get the corresponding volume, if partition is mounted
char path[B_FILE_NAME_LENGTH];
partition->GetPath(path);
@ -308,6 +388,12 @@ RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause)
void
RDiskDeviceList::PartitionRemoved(RPartition *partition, uint32 cause)
{
// remove the partition from our list
bool success = false;
int32 index = fPartitions.FindBinaryInsertionIndex(
CompareIDPredicate<RPartition>(partition), &success);
if (success)
fPartitions.RemoveItemAt(index);
// notifications
// ...
}
@ -393,3 +479,64 @@ RDiskDeviceList::_ScanDevice(const char *path)
return error;
}
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause)
{
status_t error = (message ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
message->what = B_DEVICE_UPDATE;
error = message->AddInt32("event", event);
}
if (error == B_OK)
error = message->AddInt32("cause", cause);
return error;
}
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RDiskDevice *device)
{
status_t error = (device ? B_OK : B_BAD_VALUE);
if (error == B_OK)
error = _InitNotificationMessage(message, event, cause);
if (error == B_OK)
error = message->AddInt32("device_id", device->ID());
return error;
}
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RSession *session)
{
status_t error = (session ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
error = _InitNotificationMessage(message, event, cause,
session->Device());
}
if (error == B_OK)
error = message->AddInt32("session_id", session->ID());
return error;
}
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RPartition *partition)
{
status_t error = (partition ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
error = _InitNotificationMessage(message, event, cause,
partition->Session());
}
if (error == B_OK)
error = message->AddInt32("partition_id", partition->ID());
return error;
}

View File

@ -19,6 +19,7 @@ class BLocker;
class RDiskDevice;
class RPartition;
class RSession;
class WatchingService;
// device list modification causes
// TODO: to be moved to <DiskDeviceRoster.h>
@ -36,14 +37,17 @@ enum {
class RDiskDeviceList : public MessageHandler, public RVolumeListListener {
public:
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList);
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList,
WatchingService *watchingService);
~RDiskDeviceList();
virtual void HandleMessage(BMessage *message);
virtual void VolumeMounted(const RVolume *volume);
virtual void VolumeUnmounted(const RVolume *volume);
virtual void MountPointMoved(const RVolume *volume);
virtual void MountPointMoved(const RVolume *volume,
const entry_ref *oldRoot,
const entry_ref *newRoot);
bool AddDevice(RDiskDevice *device);
bool RemoveDevice(int32 index);
@ -63,6 +67,7 @@ public:
RPartition *PartitionWithID(int32 id) const;
RDiskDevice *DeviceWithPath(const char *path) const;
RPartition *PartitionWithPath(const char *path) const;
status_t Rescan();
@ -88,10 +93,21 @@ private:
status_t _Scan(BDirectory &dir);
status_t _ScanDevice(const char *path);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause, const RDiskDevice *device);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause, const RSession *session);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RPartition *partition);
private:
mutable BLocker &fLock;
BMessenger fTarget;
RVolumeList &fVolumeList;
WatchingService *fWatchingService;
BObjectList<RDiskDevice> fDevices; // sorted by ID
BObjectList<RSession> fSessions; //
BObjectList<RPartition> fPartitions; //

View File

@ -109,10 +109,10 @@ RSession::RemovePartition(int32 index)
{
RPartition *partition = PartitionAt(index);
if (partition) {
partition->SetSession(NULL);
fPartitions.RemoveItemAt(index);
if (RDiskDeviceList *deviceList = DeviceList())
deviceList->PartitionRemoved(partition);
partition->SetSession(NULL);
fPartitions.RemoveItemAt(index);
delete partition;
}
return (partition != NULL);

View File

@ -5,14 +5,19 @@
#include <string.h>
#include <Directory.h>
#include <Entry.h>
#include <Locker.h>
#include <Message.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <Volume.h>
#include "RVolumeList.h"
#include "Debug.h"
namespace RVolumeListPredicates {
// CompareIDPredicate
struct CompareIDPredicate : public UnaryPredicate<RVolume> {
CompareIDPredicate(dev_t id) : fID(id) {}
@ -45,13 +50,18 @@ private:
const char *fPath;
};
} // namespace RVolumeListPredicates
using namespace RVolumeListPredicates;
// RVolume
// constructor
RVolume::RVolume()
: fID(-1),
fRootNode(-1)
fRootNode(-1),
fRootEntry()
{
}
@ -60,13 +70,31 @@ status_t
RVolume::SetTo(dev_t id)
{
status_t error = B_OK;
// get general info
fs_info info;
error = fs_stat_dev(id, &info);
if (error == B_OK) {
fID = id;
fRootNode = info.root;
strcpy(fDevicePath, info.device_name);
} else
if (info.device_name[0] != '\0')
strcpy(fDevicePath, info.device_name);
else // generate a pseudo name -- needed for the list
sprintf(fDevicePath, "%ld", id);
}
// get root dir entry_ref
if (error == B_OK) {
node_ref ref;
GetRootDirNode(&ref);
BDirectory dir;
error = dir.SetTo(&ref);
BEntry entry;
if (error == B_OK)
error = dir.GetEntry(&entry);
if (error == B_OK)
error = entry.GetRef(&fRootEntry);
}
// cleanup on error
if (error != B_OK)
Unset();
return error;
}
@ -126,7 +154,9 @@ RVolumeListListener::VolumeUnmounted(const RVolume *volume)
// MountPointMoved
void
RVolumeListListener::MountPointMoved(const RVolume *volume)
RVolumeListListener::MountPointMoved(const RVolume *volume,
const entry_ref *oldRoot,
const entry_ref *newRoot)
{
}
@ -194,12 +224,15 @@ RVolumeList::HandleMessage(BMessage *message)
status_t
RVolumeList::Rescan()
{
fVolumes.MakeEmpty();
PRINT(("RVolumeList::Rescan()\n"));
for (int32 i = fVolumes.CountItems() - 1; i >= 0; i--)
_RemoveVolumeAt(i);
fRoster.Rewind();
BVolume bVolume;
while (fRoster.GetNextVolume(&bVolume) == B_OK)
_AddVolume(bVolume.Device());
return B_ERROR;
PRINT(("RVolumeList::Rescan() done\n"));
return B_OK;
}
// VolumeForDevicePath
@ -272,6 +305,18 @@ RVolumeList::_AddVolume(dev_t id)
return volume;
}
// _RemoveVolumeAt
bool
RVolumeList::_RemoveVolumeAt(int32 index)
{
bool result = false;
if (RVolume *volume = fVolumes.RemoveItemAt(index)) {
volume->StopWatching(fTarget);
delete volume;
}
return result;
}
// _DeviceMounted
void
RVolumeList::_DeviceMounted(BMessage *message)
@ -307,12 +352,33 @@ RVolumeList::_DeviceUnmounted(BMessage *message)
void
RVolumeList::_MountPointMoved(BMessage *message)
{
// Note: The "device" field of the message refers to the device of the
// parent directory. Therefore we need to get an entry_ref, turn it into
// a path and get the device for that path.
// get the message fields
dev_t device;
if (message->FindInt32("device", &device) == B_OK) {
PRINT(("RVolumeList::_MountPointMoved(%ld)\n", device));
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) {
if (fListener)
fListener->MountPointMoved(volume);
ino_t directory;
const char *name;
if (message->FindInt32("device", &device) == B_OK
&& message->FindInt64("to directory", &directory) == B_OK
&& message->FindString("name", &name) == B_OK) {
// init an entry_ref
entry_ref ref;
ref.device = device;
ref.directory = directory;
ref.set_name(name);
// get the path and the device for that path
BPath path;
if (path.SetTo(&ref) == B_OK
&& (device = dev_for_path(path.Path())) >= 0) {
PRINT(("RVolumeList::_MountPointMoved(%ld)\n", device));
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) {
entry_ref oldRoot;
volume->GetRootDirEntry(&oldRoot);
volume->SetRootDirEntry(&ref);
if (fListener)
fListener->MountPointMoved(volume, &oldRoot, &ref);
}
}
}
}

View File

@ -6,6 +6,7 @@
#ifndef VOLUME_LIST_H
#define VOLUME_LIST_H
#include <Entry.h>
#include <Messenger.h>
#include <Node.h>
#include <ObjectList.h>
@ -26,17 +27,21 @@ public:
dev_t ID() const { return fID; }
ino_t RootNode() const { return fRootNode; }
void GetRootNodeRef(node_ref *ref) const
void GetRootDirNode(node_ref *ref) const
{ ref->device = fID; ref->node = fRootNode; }
void GetRootDirEntry(entry_ref *ref) const { *ref = fRootEntry; }
const char *DevicePath() const { return fDevicePath; }
void SetRootDirEntry(const entry_ref *ref) { fRootEntry = *ref; }
status_t StartWatching(BMessenger target) const;
status_t StopWatching(BMessenger target) const;
private:
dev_t fID;
ino_t fRootNode;
char fDevicePath[B_FILE_NAME_LENGTH];
dev_t fID;
ino_t fRootNode;
entry_ref fRootEntry;
char fDevicePath[B_FILE_NAME_LENGTH];
};
// RVolumeListListener
@ -47,7 +52,9 @@ public:
virtual void VolumeMounted(const RVolume *volume);
virtual void VolumeUnmounted(const RVolume *volume);
virtual void MountPointMoved(const RVolume *volume);
virtual void MountPointMoved(const RVolume *volume,
const entry_ref *oldRoot,
const entry_ref *newRoot);
};
// RVolumeList
@ -71,6 +78,7 @@ public:
private:
RVolume *_AddVolume(dev_t id);
bool _RemoveVolumeAt(int32 index);
void _DeviceMounted(BMessage *message);
void _DeviceUnmounted(BMessage *message);
void _MountPointMoved(BMessage *message);