Removed the old, nicely working, DiskDevice API support from the registrar. We're going to reimplement it in the kernel.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3429 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c41e89d3da
commit
32453e90e0
@ -1,356 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <NodeMonitor.h>
|
||||
#include <RegistrarDefs.h>
|
||||
|
||||
#include "DiskDeviceManager.h"
|
||||
#include "Debug.h"
|
||||
#include "EventMaskWatcher.h"
|
||||
#include "EventQueue.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "RDiskDevice.h"
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "RPartition.h"
|
||||
#include "RSession.h"
|
||||
|
||||
// priorities of the different message kinds
|
||||
enum {
|
||||
REQUEST_PRIORITY = 0,
|
||||
RESCAN_PRIORITY = 5,
|
||||
NODE_MONITOR_PRIORITY = 10,
|
||||
WATCHING_REQUEST_PRIORITY = 20,
|
||||
};
|
||||
|
||||
// time interval between device rescans
|
||||
static const bigtime_t kRescanEventInterval = 5000000;
|
||||
|
||||
// constructor
|
||||
DiskDeviceManager::DiskDeviceManager(EventQueue *eventQueue)
|
||||
: BLooper("disk device manager"),
|
||||
fEventQueue(eventQueue),
|
||||
fRescanEvent(NULL),
|
||||
fDeviceListLock(),
|
||||
fWatchingService(),
|
||||
fVolumeList(BMessenger(this), fDeviceListLock),
|
||||
fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList,
|
||||
&fWatchingService),
|
||||
fMessageQueue(),
|
||||
fWorker(-1),
|
||||
fMessageCounter(-1),
|
||||
fTerminating(false)
|
||||
{
|
||||
// set up the device list
|
||||
fVolumeList.Dump();
|
||||
fDeviceList.Rescan();
|
||||
fDeviceList.Dump();
|
||||
// start the worker thread
|
||||
fMessageCounter = create_sem(0, "disk device manager msgcounter");
|
||||
if (fMessageCounter >= 0) {
|
||||
fWorker = spawn_thread(_WorkerEntry, "disk device manager worker",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
if (fWorker >= 0)
|
||||
resume_thread(fWorker);
|
||||
}
|
||||
// set up the rescan event
|
||||
fRescanEvent = new MessageEvent(system_time() + kRescanEventInterval,
|
||||
this, B_REG_ROSTER_DEVICE_RESCAN);
|
||||
fRescanEvent->SetAutoDelete(false);
|
||||
fEventQueue->AddEvent(fRescanEvent);
|
||||
}
|
||||
|
||||
// destructor
|
||||
DiskDeviceManager::~DiskDeviceManager()
|
||||
{
|
||||
// remove the rescan event from the event queue
|
||||
fEventQueue->RemoveEvent(fRescanEvent);
|
||||
// terminate the worker thread
|
||||
fTerminating = true;
|
||||
delete_sem(fMessageCounter);
|
||||
int32 dummy;
|
||||
wait_for_thread(fWorker, &dummy);
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
DiskDeviceManager::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch (message->what) {
|
||||
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, WATCHING_REQUEST_PRIORITY))
|
||||
delete message;
|
||||
break;
|
||||
case B_REG_ROSTER_DEVICE_RESCAN:
|
||||
DetachCurrentMessage();
|
||||
if (!_PushMessage(message, RESCAN_PRIORITY))
|
||||
delete message;
|
||||
break;
|
||||
case B_NODE_MONITOR:
|
||||
DetachCurrentMessage();
|
||||
if (!_PushMessage(message, NODE_MONITOR_PRIORITY))
|
||||
delete message;
|
||||
break;
|
||||
default:
|
||||
BLooper::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// _NextDiskDeviceRequest
|
||||
void
|
||||
DiskDeviceManager::_NextDiskDeviceRequest(BMessage *request)
|
||||
{
|
||||
FUNCTION_START();
|
||||
Lock();
|
||||
status_t error = B_OK;
|
||||
int32 cookie = 0;
|
||||
BMessage reply(B_REG_RESULT);
|
||||
if (request->FindInt32("cookie", &cookie) == B_OK) {
|
||||
// get next device
|
||||
if (RDiskDevice *device = fDeviceList.DeviceWithID(cookie, false)) {
|
||||
// archive device
|
||||
BMessage deviceArchive;
|
||||
SET_ERROR(error, device->Archive(&deviceArchive));
|
||||
// add archived device and next cookie to reply message
|
||||
if (error == B_OK)
|
||||
SET_ERROR(error, reply.AddMessage("device", &deviceArchive));
|
||||
if (error == B_OK)
|
||||
SET_ERROR(error, reply.AddInt32("cookie", device->ID() + 1));
|
||||
} else
|
||||
error = B_ENTRY_NOT_FOUND;
|
||||
} else
|
||||
SET_ERROR(error, B_BAD_VALUE);
|
||||
// add result and send reply
|
||||
reply.AddInt32("result", error);
|
||||
request->SendReply(&reply);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// _GetDiskDeviceRequest
|
||||
void
|
||||
DiskDeviceManager::_GetDiskDeviceRequest(BMessage *request)
|
||||
{
|
||||
Lock();
|
||||
status_t error = B_OK;
|
||||
// get the device
|
||||
RDiskDevice *device = NULL;
|
||||
int32 id = 0;
|
||||
if (request->FindInt32("device_id", &id) == B_OK)
|
||||
device = fDeviceList.DeviceWithID(id);
|
||||
else if (request->FindInt32("session_id", &id) == B_OK) {
|
||||
if (RSession *session = fDeviceList.SessionWithID(id))
|
||||
device = session->Device();
|
||||
} else if (request->FindInt32("partition_id", &id) == B_OK) {
|
||||
if (RPartition *partition = fDeviceList.PartitionWithID(id))
|
||||
device = partition->Device();
|
||||
} else
|
||||
error = B_BAD_VALUE;
|
||||
// archive device and add it to the reply message
|
||||
BMessage reply(B_REG_RESULT);
|
||||
if (device) {
|
||||
BMessage deviceArchive;
|
||||
error = device->Archive(&deviceArchive);
|
||||
if (error == B_OK)
|
||||
error = reply.AddMessage("device", &deviceArchive);
|
||||
} else // requested object not found
|
||||
error = B_ENTRY_NOT_FOUND;
|
||||
// add result and send reply
|
||||
reply.AddInt32("result", error);
|
||||
request->SendReply(&reply);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// _UpdateDiskDeviceRequest
|
||||
void
|
||||
DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *request)
|
||||
{
|
||||
Lock();
|
||||
status_t error = B_OK;
|
||||
// get the device and check the object is up to date
|
||||
bool upToDate = false;
|
||||
RDiskDevice *device = NULL;
|
||||
int32 id = 0;
|
||||
int32 changeCounter = 0;
|
||||
uint32 policy = 0;
|
||||
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 (request->FindInt32("device_id", &id) == B_OK) {
|
||||
device = fDeviceList.DeviceWithID(id);
|
||||
if (device)
|
||||
upToDate = (device->ChangeCounter() == changeCounter);
|
||||
PRINT(("DiskDeviceManager::_UpdateDiskDeviceRequest(): device id: %ld, "
|
||||
"device: %p\n", id, device));
|
||||
} else if (request->FindInt32("session_id", &id) == B_OK) {
|
||||
if (RSession *session = fDeviceList.SessionWithID(id)) {
|
||||
device = session->Device();
|
||||
upToDate = (session->ChangeCounter() == changeCounter);
|
||||
}
|
||||
} else if (request->FindInt32("partition_id", &id) == B_OK) {
|
||||
if (RPartition *partition = fDeviceList.PartitionWithID(id)) {
|
||||
device = partition->Device();
|
||||
upToDate = (partition->ChangeCounter() == changeCounter);
|
||||
}
|
||||
} else // bad request message
|
||||
SET_ERROR(error, B_BAD_VALUE);
|
||||
// archive device and add it to the reply message
|
||||
BMessage reply(B_REG_RESULT);
|
||||
if (device) {
|
||||
if (policy == B_REG_DEVICE_UPDATE_DEVICE_CHANGED)
|
||||
upToDate = (device->ChangeCounter() == changeCounter);
|
||||
if (!upToDate && policy != B_REG_DEVICE_UPDATE_CHECK) {
|
||||
BMessage deviceArchive;
|
||||
error = device->Archive(&deviceArchive);
|
||||
if (error == B_OK)
|
||||
error = reply.AddMessage("device", &deviceArchive);
|
||||
}
|
||||
} else // requested object not found
|
||||
error = B_ENTRY_NOT_FOUND;
|
||||
// add result and send reply
|
||||
if (error == B_OK)
|
||||
error = reply.AddBool("up_to_date", upToDate);
|
||||
reply.AddInt32("result", error);
|
||||
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)
|
||||
{
|
||||
bool result = fMessageQueue.PushMessage(message, priority);
|
||||
if (result)
|
||||
release_sem(fMessageCounter);
|
||||
return result;
|
||||
}
|
||||
|
||||
// _PopMessage
|
||||
BMessage *
|
||||
DiskDeviceManager::_PopMessage()
|
||||
{
|
||||
BMessage *result = NULL;
|
||||
status_t error = acquire_sem(fMessageCounter);
|
||||
if (error == B_OK)
|
||||
result = fMessageQueue.PopMessage();
|
||||
return result;
|
||||
}
|
||||
|
||||
// _WorkerEntry
|
||||
int32
|
||||
DiskDeviceManager::_WorkerEntry(void *parameters)
|
||||
{
|
||||
return static_cast<DiskDeviceManager*>(parameters)->_Worker();
|
||||
}
|
||||
|
||||
// _Worker
|
||||
int32
|
||||
DiskDeviceManager::_Worker()
|
||||
{
|
||||
while (!fTerminating) {
|
||||
if (BMessage *message = _PopMessage()) {
|
||||
// dispatch the message
|
||||
switch (message->what) {
|
||||
case B_REG_NEXT_DISK_DEVICE:
|
||||
_NextDiskDeviceRequest(message);
|
||||
break;
|
||||
case B_REG_GET_DISK_DEVICE:
|
||||
_GetDiskDeviceRequest(message);
|
||||
break;
|
||||
case B_REG_UPDATE_DISK_DEVICE:
|
||||
_UpdateDiskDeviceRequest(message);
|
||||
break;
|
||||
case B_REG_DEVICE_START_WATCHING:
|
||||
_StartWatchingRequest(message);
|
||||
break;
|
||||
case B_REG_DEVICE_STOP_WATCHING:
|
||||
_StopWatchingRequest(message);
|
||||
break;
|
||||
case B_REG_ROSTER_DEVICE_RESCAN:
|
||||
fDeviceList.Rescan();
|
||||
fRescanEvent->SetTime(system_time()
|
||||
+ kRescanEventInterval);
|
||||
fEventQueue->AddEvent(fRescanEvent);
|
||||
break;
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
fVolumeList.HandleMessage(message);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// error
|
||||
break;
|
||||
}
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,19 +1,14 @@
|
||||
SubDir OBOS_TOP src servers registrar ;
|
||||
|
||||
UsePublicHeaders app ;
|
||||
UsePrivateHeaders $(DOT) ; # needed for disk_scanner.cpp
|
||||
UsePrivateHeaders app ;
|
||||
UsePrivateHeaders shared ;
|
||||
UsePrivateHeaders storage ;
|
||||
|
||||
# needed as long as disk_scanner.cpp is compiled in
|
||||
SEARCH_SOURCE += [ FDirName $(OBOS_TOP) src kernel libroot os ] ;
|
||||
|
||||
Server obos_registrar :
|
||||
AppInfoList.cpp
|
||||
ClipboardHandler.cpp
|
||||
ClipboardTree.cpp
|
||||
DiskDeviceManager.cpp
|
||||
Event.cpp
|
||||
EventMaskWatcher.cpp
|
||||
EventQueue.cpp
|
||||
@ -21,35 +16,18 @@ Server obos_registrar :
|
||||
MessageHandler.cpp
|
||||
MessageRunnerManager.cpp
|
||||
MIMEManager.cpp
|
||||
NodeMonitoring.cpp
|
||||
PriorityMessageQueue.cpp
|
||||
RDiskDevice.cpp
|
||||
RDiskDeviceList.cpp
|
||||
RecentApps.cpp
|
||||
RecentEntries.cpp
|
||||
Registrar.cpp
|
||||
RosterAppInfo.cpp
|
||||
RosterSettingsCharStream.cpp
|
||||
RPartition.cpp
|
||||
RSession.cpp
|
||||
RVolumeList.cpp
|
||||
TRoster.cpp
|
||||
Watcher.cpp
|
||||
WatchingService.cpp
|
||||
|
||||
# from .../libroot/os
|
||||
disk_scanner.cpp
|
||||
;
|
||||
LinkSharedOSLibs obos_registrar :
|
||||
<boot!home!config!lib>libopenbeos.so
|
||||
<boot!home!config!lib>libkernelland_emu.so # needed for disk_scanner.cpp
|
||||
stdc++.r4
|
||||
be
|
||||
;
|
||||
|
||||
# Helper needed for node watching
|
||||
#
|
||||
BinCommand NodeMonitor : NodeMonitor.cpp : be ;
|
||||
|
||||
Depends obos_registrar : NodeMonitor ;
|
||||
|
||||
|
@ -1,145 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <Application.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
// Monitor
|
||||
class Monitor : public BHandler {
|
||||
public:
|
||||
Monitor(BMessenger target);
|
||||
virtual ~Monitor();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
BMessenger Target() const { return fTarget; }
|
||||
|
||||
private:
|
||||
BMessenger fTarget;
|
||||
};
|
||||
|
||||
// NodeMonitorApp
|
||||
class NodeMonitorApp : public BApplication {
|
||||
public:
|
||||
NodeMonitorApp();
|
||||
virtual ~NodeMonitorApp();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
private:
|
||||
BObjectList<Monitor> fMonitors;
|
||||
};
|
||||
|
||||
|
||||
// Monitor
|
||||
|
||||
// constructor
|
||||
Monitor::Monitor(BMessenger target)
|
||||
: BHandler(),
|
||||
fTarget(target)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
Monitor::~Monitor()
|
||||
{
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
Monitor::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_NODE_MONITOR:
|
||||
fTarget.SendMessage(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NodeMonitorApp
|
||||
|
||||
// constructor
|
||||
NodeMonitorApp::NodeMonitorApp()
|
||||
: BApplication("application/x-vnd.obos-NodeMonitor"),
|
||||
fMonitors(10, true)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
NodeMonitorApp::~NodeMonitorApp()
|
||||
{
|
||||
Lock();
|
||||
for (int32 i = 0; Monitor *monitor = fMonitors.ItemAt(i); i++)
|
||||
RemoveHandler(monitor);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
NodeMonitorApp::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case 'wtch':
|
||||
{
|
||||
status_t error = B_BAD_VALUE;
|
||||
node_ref ref;
|
||||
BMessenger target;
|
||||
uint32 flags;
|
||||
if (message->FindInt32("device", &ref.device) == B_OK
|
||||
&& message->FindInt64("node", &ref.node) == B_OK
|
||||
&& message->FindMessenger("target", &target) == B_OK
|
||||
&& message->FindInt32("flags", (int32*)&flags) == B_OK) {
|
||||
Monitor *monitor = new Monitor(target);
|
||||
fMonitors.AddItem(monitor);
|
||||
AddHandler(monitor);
|
||||
error = watch_node(&ref, flags, monitor);
|
||||
if (error != B_OK) {
|
||||
RemoveHandler(monitor);
|
||||
fMonitors.RemoveItem(monitor);
|
||||
}
|
||||
}
|
||||
BMessage reply(B_SIMPLE_DATA);
|
||||
reply.AddInt32("result", error);
|
||||
message->SendReply(&reply);
|
||||
break;
|
||||
}
|
||||
case 'hctw':
|
||||
{
|
||||
status_t error = B_BAD_VALUE;
|
||||
BMessenger target;
|
||||
if (message->FindMessenger("target", &target) == B_OK) {
|
||||
error = B_OK;
|
||||
for (int32 i = fMonitors.CountItems();
|
||||
Monitor *monitor = fMonitors.ItemAt(i);
|
||||
i--) {
|
||||
if (monitor->Target() == target) {
|
||||
error = stop_watching(monitor->Target());
|
||||
RemoveHandler(monitor);
|
||||
delete fMonitors.RemoveItemAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
BMessage reply(B_SIMPLE_DATA);
|
||||
reply.AddInt32("result", error);
|
||||
message->SendReply(&reply);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// main
|
||||
int
|
||||
main()
|
||||
{
|
||||
NodeMonitorApp app;
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,226 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// A fake implementation of the node monitoring functions.
|
||||
// They start a remote application that functions as an adapter for the
|
||||
// functions in libbe.so.
|
||||
// Note: We can't use the node monitoring provided by libbe directly, since
|
||||
// it makes sure, that the target is local using BMessenger::Target(), which
|
||||
// can't work.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <AppMisc.h>
|
||||
#include <image.h>
|
||||
#include <Locker.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
// NodeMonitor
|
||||
class NodeMonitor {
|
||||
public:
|
||||
NodeMonitor();
|
||||
~NodeMonitor();
|
||||
|
||||
status_t GetMessenger(BMessenger &monitor);
|
||||
status_t WatchingRequest(const node_ref *node, uint32 flags,
|
||||
BMessenger target, bool start);
|
||||
|
||||
private:
|
||||
bool fInitialized;
|
||||
status_t fStatus;
|
||||
thread_id fThread;
|
||||
team_id fTeam;
|
||||
BMessenger fMessenger;
|
||||
BLocker fLock;
|
||||
};
|
||||
|
||||
static NodeMonitor gNodeMonitor;
|
||||
|
||||
// constructor
|
||||
NodeMonitor::NodeMonitor()
|
||||
: fInitialized(false),
|
||||
fStatus(B_ERROR),
|
||||
fThread(-1),
|
||||
fTeam(-1),
|
||||
fMessenger(),
|
||||
fLock()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
NodeMonitor::~NodeMonitor()
|
||||
{
|
||||
fLock.Lock();
|
||||
if (fInitialized) {
|
||||
if (fMessenger.IsValid())
|
||||
fMessenger.SendMessage(B_QUIT_REQUESTED);
|
||||
else if (fThread >= 0)
|
||||
kill_thread(fThread);
|
||||
}
|
||||
fLock.Unlock();
|
||||
}
|
||||
|
||||
// GetMessenger
|
||||
status_t
|
||||
NodeMonitor::GetMessenger(BMessenger &monitor)
|
||||
{
|
||||
fLock.Lock();
|
||||
if (!fInitialized) {
|
||||
fInitialized = true;
|
||||
// get NodeMonitor path
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
fStatus = BPrivate::get_app_path(path);
|
||||
if (fStatus == B_OK) {
|
||||
if (char *leaf = strstr(path, "obos_registrar")) {
|
||||
strcpy(leaf, "../../bin/NodeMonitor");
|
||||
} else
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
// start the NodeMonitor
|
||||
if (fStatus == B_OK) {
|
||||
const char *argv[] = { path, NULL };
|
||||
fThread = load_image(1, argv,
|
||||
const_cast<const char**>(environ));
|
||||
if (fThread >= 0) {
|
||||
resume_thread(fThread);
|
||||
thread_info info;
|
||||
fStatus = get_thread_info(fThread, &info);
|
||||
if (fStatus == B_OK)
|
||||
fTeam = info.team;
|
||||
} else
|
||||
fStatus = fThread;
|
||||
}
|
||||
// find the app looper port
|
||||
port_id port = -1;
|
||||
if (fStatus == B_OK) {
|
||||
snooze(200000);
|
||||
port_info info;
|
||||
int32 cookie = 0;
|
||||
fStatus = B_ERROR;
|
||||
while (get_next_port_info(fTeam, &cookie, &info) == B_OK) {
|
||||
if (!strcmp(info.name, "AppLooperPort")) {
|
||||
fStatus = B_OK;
|
||||
port = info.port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// get a messenger
|
||||
if (fStatus == B_OK) {
|
||||
struct {
|
||||
port_id fPort;
|
||||
int32 fHandlerToken;
|
||||
team_id fTeam;
|
||||
int32 extra0;
|
||||
int32 extra1;
|
||||
bool fPreferredTarget;
|
||||
bool extra2;
|
||||
bool extra3;
|
||||
bool extra4;
|
||||
} fakeMessenger;
|
||||
fakeMessenger.fPort = port;
|
||||
fakeMessenger.fHandlerToken = -1;
|
||||
fakeMessenger.fTeam = fTeam;
|
||||
fakeMessenger.fPreferredTarget = true;
|
||||
fMessenger = *(BMessenger*)&fakeMessenger;
|
||||
if (!fMessenger.IsValid())
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
}
|
||||
// set result
|
||||
if (fStatus == B_OK)
|
||||
monitor = fMessenger;
|
||||
fLock.Unlock();
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
// WatchingRequest
|
||||
status_t
|
||||
NodeMonitor::WatchingRequest(const node_ref *node, uint32 flags,
|
||||
BMessenger target, bool start)
|
||||
{
|
||||
BMessenger monitor;
|
||||
status_t error = GetMessenger(monitor);
|
||||
// prepare request message
|
||||
BMessage request;
|
||||
if (error == B_OK) {
|
||||
if (start) {
|
||||
request.what = 'wtch';
|
||||
request.AddInt32("device", node->device);
|
||||
request.AddInt64("node", node->node);
|
||||
request.AddInt32("flags", (int32)flags);
|
||||
} else {
|
||||
request.what = 'hctw';
|
||||
}
|
||||
request.AddMessenger("target", target);
|
||||
}
|
||||
// send request
|
||||
BMessage reply;
|
||||
if (error == B_OK)
|
||||
error = monitor.SendMessage(&request, &reply);
|
||||
// analyze reply
|
||||
if (error == B_OK) {
|
||||
status_t result;
|
||||
error = reply.FindInt32("result", &result);
|
||||
if (error == B_OK)
|
||||
error = result;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// watch_node
|
||||
status_t
|
||||
watch_node(const node_ref *node, uint32 flags, BMessenger target)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (flags == B_STOP_WATCHING)
|
||||
error = stop_watching(target);
|
||||
else {
|
||||
node_ref fakeNode;
|
||||
if (!node)
|
||||
node = &fakeNode;
|
||||
error = gNodeMonitor.WatchingRequest(node, flags, target, true);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// watch_node
|
||||
status_t
|
||||
watch_node(const node_ref *node, uint32 flags, const BHandler *handler,
|
||||
const BLooper *looper)
|
||||
{
|
||||
status_t error = (handler || looper ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
BMessenger target(handler, looper);
|
||||
error = watch_node(node, flags, target);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// stop_watching
|
||||
status_t
|
||||
stop_watching(BMessenger target)
|
||||
{
|
||||
return gNodeMonitor.WatchingRequest(NULL, 0, target, false);
|
||||
}
|
||||
|
||||
// stop_watching
|
||||
status_t
|
||||
stop_watching(const BHandler *handler, const BLooper *looper)
|
||||
{
|
||||
status_t error = (handler || looper ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
BMessenger target(handler, looper);
|
||||
error = stop_watching(target);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -1,361 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <new.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <disk_scanner.h>
|
||||
|
||||
#include "RDiskDevice.h"
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "RPartition.h"
|
||||
#include "RSession.h"
|
||||
|
||||
// constructor
|
||||
RDiskDevice::RDiskDevice()
|
||||
: fSessions(10, true),
|
||||
fDeviceList(NULL),
|
||||
fID(-1),
|
||||
fChangeCounter(),
|
||||
fTouched(false),
|
||||
fPath(),
|
||||
fFD(-1),
|
||||
fMediaStatus(B_ERROR)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
RDiskDevice::~RDiskDevice()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
// SetTo
|
||||
status_t
|
||||
RDiskDevice::SetTo(const char *path, int fd, const device_geometry *geometry,
|
||||
status_t mediaStatus)
|
||||
{
|
||||
PRINT(("RDiskDevice::SetTo()\n"));
|
||||
Unset();
|
||||
status_t error = B_OK;
|
||||
fID = _NextID();
|
||||
fChangeCounter.Reset();
|
||||
fTouched = true;
|
||||
fPath.SetTo(path);
|
||||
fFD = fd;
|
||||
fGeometry = *geometry;
|
||||
fMediaStatus = mediaStatus;
|
||||
// analyze the media status
|
||||
switch (fMediaStatus) {
|
||||
case B_NO_ERROR:
|
||||
case B_DEV_NO_MEDIA:
|
||||
case B_DEV_NOT_READY:
|
||||
case B_DEV_MEDIA_CHANGE_REQUESTED:
|
||||
case B_DEV_DOOR_OPEN:
|
||||
break;
|
||||
case B_DEV_MEDIA_CHANGED:
|
||||
// the user was fast enough to change the media between opening
|
||||
// and requesting the media status -- media is in, so we are fine
|
||||
fMediaStatus = B_OK;
|
||||
break;
|
||||
default:
|
||||
error = fMediaStatus;
|
||||
break;
|
||||
}
|
||||
// scan the device for sessions
|
||||
error = _RescanSessions(B_DEVICE_CAUSE_UNKNOWN);
|
||||
// cleanup on error
|
||||
if (error != B_OK)
|
||||
Unset();
|
||||
RETURN_ERROR(error);
|
||||
// return error;
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
RDiskDevice::Unset()
|
||||
{
|
||||
for (int32 i = CountSessions() - 1; i >= 0; i--)
|
||||
RemoveSession(i, B_DEVICE_CAUSE_UNKNOWN);
|
||||
fID = -1;
|
||||
fPath.SetTo("");
|
||||
if (fFD >= 0) {
|
||||
close(fFD);
|
||||
fFD = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// MediaChanged
|
||||
status_t
|
||||
RDiskDevice::MediaChanged()
|
||||
{
|
||||
PRINT(("RDiskDevice::MediaChanged()\n"));
|
||||
Changed();
|
||||
status_t error = B_OK;
|
||||
// get the new media status
|
||||
status_t mediaStatus;
|
||||
if (ioctl(fFD, B_GET_MEDIA_STATUS, &mediaStatus) == 0) {
|
||||
fMediaStatus = mediaStatus;
|
||||
// analyze the media status
|
||||
switch (fMediaStatus) {
|
||||
case B_NO_ERROR:
|
||||
case B_DEV_NO_MEDIA:
|
||||
case B_DEV_NOT_READY:
|
||||
case B_DEV_MEDIA_CHANGE_REQUESTED:
|
||||
case B_DEV_DOOR_OPEN:
|
||||
break;
|
||||
case B_DEV_MEDIA_CHANGED:
|
||||
// Ignore changes between the ioctl() and the one before;
|
||||
// we rescan the sessions anyway.
|
||||
fMediaStatus = B_OK;
|
||||
break;
|
||||
default:
|
||||
error = fMediaStatus;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// get the device geometry
|
||||
if (ioctl(fFD, B_GET_GEOMETRY, &fGeometry) != 0)
|
||||
error = errno;
|
||||
// rescan sessions
|
||||
if (error == B_OK)
|
||||
error = _RescanSessions(B_DEVICE_CAUSE_PARENT_CHANGED);
|
||||
// notification
|
||||
if (fDeviceList)
|
||||
fDeviceList->MediaChanged(this, B_DEVICE_CAUSE_MEDIA_CHANGED);
|
||||
return error;
|
||||
}
|
||||
|
||||
// SessionLayoutChanged
|
||||
status_t
|
||||
RDiskDevice::SessionLayoutChanged()
|
||||
{
|
||||
PRINT(("RDiskDevice::SessionLayoutChanged()\n"));
|
||||
Changed();
|
||||
status_t error = B_OK;
|
||||
error = _RescanSessions(B_DEVICE_CAUSE_UNKNOWN);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Size
|
||||
off_t
|
||||
RDiskDevice::Size() const
|
||||
{
|
||||
return (off_t)fGeometry.bytes_per_sector * fGeometry.sectors_per_track
|
||||
* fGeometry.cylinder_count * fGeometry.head_count;
|
||||
}
|
||||
|
||||
// AddSession
|
||||
status_t
|
||||
RDiskDevice::AddSession(const session_info *sessionInfo, uint32 cause)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (RSession *session = new(nothrow) RSession) {
|
||||
error = session->SetTo(fFD, sessionInfo);
|
||||
if (error == B_OK)
|
||||
AddSession(session, cause);
|
||||
else
|
||||
delete session;
|
||||
} else
|
||||
error = B_NO_MEMORY;
|
||||
return error;
|
||||
}
|
||||
|
||||
// AddSession
|
||||
bool
|
||||
RDiskDevice::AddSession(RSession *session, uint32 cause)
|
||||
{
|
||||
bool success = false;
|
||||
if (session) {
|
||||
success = fSessions.AddItem(session);
|
||||
if (success) {
|
||||
session->SetDevice(this);
|
||||
Changed();
|
||||
if (RDiskDeviceList *deviceList = DeviceList())
|
||||
deviceList->SessionAdded(session, cause);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// RemoveSession
|
||||
bool
|
||||
RDiskDevice::RemoveSession(int32 index, uint32 cause)
|
||||
{
|
||||
RSession *session = SessionAt(index);
|
||||
if (session) {
|
||||
Changed();
|
||||
if (RDiskDeviceList *deviceList = DeviceList())
|
||||
deviceList->SessionRemoved(session, cause);
|
||||
session->SetDevice(NULL);
|
||||
fSessions.RemoveItemAt(index);
|
||||
delete session;
|
||||
}
|
||||
return (session != NULL);
|
||||
}
|
||||
|
||||
// RemoveSession
|
||||
bool
|
||||
RDiskDevice::RemoveSession(RSession *session, uint32 cause)
|
||||
{
|
||||
bool success = false;
|
||||
if (session) {
|
||||
int32 index = fSessions.IndexOf(session);
|
||||
if (index >= 0)
|
||||
success = RemoveSession(index, cause);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// Update
|
||||
status_t
|
||||
RDiskDevice::Update()
|
||||
{
|
||||
RChangeCounter::Locker lock(fChangeCounter);
|
||||
status_t error = B_OK;
|
||||
status_t mediaStatus = B_OK;
|
||||
if (ioctl(fFD, B_GET_MEDIA_STATUS, &mediaStatus) == 0) {
|
||||
if (mediaStatus == B_DEV_MEDIA_CHANGED
|
||||
|| (mediaStatus == B_NO_ERROR) != (fMediaStatus == B_NO_ERROR)) {
|
||||
// The media status is B_DEV_MEDIA_CHANGED or it changed from
|
||||
// B_NO_ERROR to some error code or the other way around.
|
||||
error = MediaChanged();
|
||||
} else {
|
||||
// TODO: notifications?
|
||||
fMediaStatus = mediaStatus;
|
||||
// The media has not been changed. If this is a read-only device,
|
||||
// then we are safe, since nothing can have changed. Otherwise
|
||||
// we check the sessions.
|
||||
if (!IsReadOnly() && fMediaStatus == B_OK) {
|
||||
session_info sessionInfo;
|
||||
for (int32 i = 0; error == B_OK; i++) {
|
||||
// get the session info
|
||||
status_t status = get_nth_session_info(fFD, i,
|
||||
&sessionInfo);
|
||||
if (status != B_OK) {
|
||||
if (status == B_ENTRY_NOT_FOUND) {
|
||||
// remove disappeared sessions
|
||||
for (int32 k = CountSessions() - 1; k >= i; k--)
|
||||
RemoveSession(k, B_DEVICE_CAUSE_UNKNOWN);
|
||||
} else {
|
||||
// ignore errors -- we can't help it
|
||||
// error = status;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// check the session
|
||||
if (RSession *session = SessionAt(i)) {
|
||||
if (session->Offset() == sessionInfo.offset
|
||||
&& session->Size() == sessionInfo.size) {
|
||||
session->Update(&sessionInfo);
|
||||
} else {
|
||||
// session layout changed
|
||||
error = SessionLayoutChanged();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// session added
|
||||
error = AddSession(&sessionInfo,
|
||||
B_DEVICE_CAUSE_UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Archive
|
||||
status_t
|
||||
RDiskDevice::Archive(BMessage *archive) const
|
||||
{
|
||||
status_t error = (archive ? B_OK : B_BAD_VALUE);
|
||||
// ID and change counter
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("id", fID);
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("change_counter", ChangeCounter());
|
||||
// geometry
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt64("size", Size());
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("block_size", BlockSize());
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt8("type", (int8)fGeometry.device_type);
|
||||
if (error == B_OK)
|
||||
error = archive->AddBool("removable", fGeometry.removable);
|
||||
if (error == B_OK)
|
||||
error = archive->AddBool("read_only", fGeometry.read_only);
|
||||
if (error == B_OK)
|
||||
error = archive->AddBool("write_once", fGeometry.write_once);
|
||||
// other data
|
||||
if (error == B_OK)
|
||||
error = archive->AddString("path", fPath.String());
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("media_status", fMediaStatus);
|
||||
// sessions
|
||||
for (int32 i = 0; const RSession *session = SessionAt(i); i++) {
|
||||
BMessage sessionArchive;
|
||||
error = session->Archive(&sessionArchive);
|
||||
if (error == B_OK)
|
||||
error = archive->AddMessage("sessions", &sessionArchive);
|
||||
if (error != B_OK)
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Dump
|
||||
void
|
||||
RDiskDevice::Dump() const
|
||||
{
|
||||
printf("device `%s'\n", Path());
|
||||
for (int32 i = 0; RSession *session = SessionAt(i); i++)
|
||||
session->Dump();
|
||||
}
|
||||
|
||||
// _RescanSessions
|
||||
status_t
|
||||
RDiskDevice::_RescanSessions(uint32 cause)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// remove the current sessions
|
||||
for (int32 i = CountSessions() - 1; i >= 0; i--)
|
||||
RemoveSession(i, cause);
|
||||
// scan the device for sessions, if we have a media
|
||||
if (fMediaStatus == B_OK) {
|
||||
session_info sessionInfo;
|
||||
for (int32 i = 0; error == B_OK; i++) {
|
||||
// get the session info
|
||||
status_t status = get_nth_session_info(fFD, i, &sessionInfo);
|
||||
if (status != B_OK) {
|
||||
if (status != B_ENTRY_NOT_FOUND) {
|
||||
// ignore errors -- we can't help it
|
||||
// error = status;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// create and add a RSession
|
||||
error = AddSession(&sessionInfo, cause);
|
||||
}
|
||||
}
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
// _NextID
|
||||
int32
|
||||
RDiskDevice::_NextID()
|
||||
{
|
||||
return atomic_add(&fNextID, 1);
|
||||
}
|
||||
|
||||
// fNextID
|
||||
vint32 RDiskDevice::fNextID = 0;
|
||||
|
@ -1,632 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <new.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <DiskDeviceRoster.h>
|
||||
#include <Drivers.h>
|
||||
#include <Entry.h>
|
||||
#include <Locker.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "Debug.h"
|
||||
#include "EventMaskWatcher.h"
|
||||
#include "RDiskDevice.h"
|
||||
#include "RPartition.h"
|
||||
#include "RSession.h"
|
||||
#include "WatchingService.h"
|
||||
|
||||
namespace RDiskDeviceListPredicates {
|
||||
|
||||
// CompareIDPredicate
|
||||
template <typename T>
|
||||
struct CompareIDPredicate : public UnaryPredicate<T> {
|
||||
CompareIDPredicate(int32 id) : fID(id) {}
|
||||
CompareIDPredicate(const T *object) : fID(object->ID()) {}
|
||||
|
||||
virtual int operator()(const T *object) const
|
||||
{
|
||||
int32 id = object->ID();
|
||||
if (fID < id)
|
||||
return 1;
|
||||
if (fID > id)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int32 fID;
|
||||
};
|
||||
|
||||
// CompareDevicePathPredicate
|
||||
struct CompareDevicePathPredicate : public UnaryPredicate<RDiskDevice> {
|
||||
CompareDevicePathPredicate(const char *path) : fPath(path) {}
|
||||
|
||||
virtual int operator()(const RDiskDevice *device) const
|
||||
{
|
||||
return strcmp(fPath, device->Path());
|
||||
}
|
||||
|
||||
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,
|
||||
WatchingService *watchingService)
|
||||
: MessageHandler(),
|
||||
RVolumeListListener(),
|
||||
fLock(lock),
|
||||
fTarget(target),
|
||||
fVolumeList(volumeList),
|
||||
fWatchingService(watchingService),
|
||||
fDevices(20, true),
|
||||
fSessions(40, false),
|
||||
fPartitions(80, false)
|
||||
{
|
||||
fVolumeList.SetListener(this);
|
||||
}
|
||||
|
||||
// destructor
|
||||
RDiskDeviceList::~RDiskDeviceList()
|
||||
{
|
||||
}
|
||||
|
||||
// HandleMessage
|
||||
void
|
||||
RDiskDeviceList::HandleMessage(BMessage *message)
|
||||
{
|
||||
if (Lock()) {
|
||||
switch (message->what) {
|
||||
default:
|
||||
MessageHandler::HandleMessage(message);
|
||||
break;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// VolumeMounted
|
||||
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(¬ification,
|
||||
B_DEVICE_PARTITION_MOUNTED, B_DEVICE_CAUSE_UNKNOWN,
|
||||
partition) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// VolumeUnmounted
|
||||
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(¬ification,
|
||||
B_DEVICE_PARTITION_UNMOUNTED, B_DEVICE_CAUSE_UNKNOWN,
|
||||
partition) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// MountPointMoved
|
||||
void
|
||||
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(¬ification,
|
||||
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(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// DeviceAppeared
|
||||
void
|
||||
RDiskDeviceList::DeviceAppeared(const char *devicePath)
|
||||
{
|
||||
status_t error = (devicePath ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
int fd = open(devicePath, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
bool closeFile = true;
|
||||
device_geometry geometry;
|
||||
status_t mediaStatus = B_OK;
|
||||
partition_info partitionInfo;
|
||||
if (ioctl(fd, B_GET_MEDIA_STATUS, &mediaStatus) == 0
|
||||
&& ioctl(fd, B_GET_GEOMETRY, &geometry) == 0
|
||||
&& ioctl(fd, B_GET_PARTITION_INFO, &partitionInfo) < 0) {
|
||||
PRINT(("RDiskDeviceList::DeviceAppeared(`%s')\n", devicePath));
|
||||
RDiskDevice *device = new(nothrow) RDiskDevice;
|
||||
if (device) {
|
||||
error = device->SetTo(devicePath, fd, &geometry,
|
||||
mediaStatus);
|
||||
if (error == B_OK) {
|
||||
closeFile = false;
|
||||
device->SetTouched(true);
|
||||
AddDevice(device);
|
||||
} else
|
||||
delete device;
|
||||
} else
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
if (closeFile)
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeviceDisappeared
|
||||
void
|
||||
RDiskDeviceList::DeviceDisappeared(const char *devicePath)
|
||||
{
|
||||
PRINT(("RDiskDeviceList::DeviceDisappeared(`%s')\n", devicePath));
|
||||
if (devicePath) {
|
||||
if (RDiskDevice *device = DeviceWithPath(devicePath))
|
||||
RemoveDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
// AddDevice
|
||||
bool
|
||||
RDiskDeviceList::AddDevice(RDiskDevice *device)
|
||||
{
|
||||
bool success = false;
|
||||
if (device) {
|
||||
fDevices.BinaryInsert(device, CompareIDPredicate<RDiskDevice>(device));
|
||||
device->SetDeviceList(this);
|
||||
DeviceAdded(device);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// RemoveDevice
|
||||
bool
|
||||
RDiskDeviceList::RemoveDevice(int32 index)
|
||||
{
|
||||
RDiskDevice *device = DeviceAt(index);
|
||||
if (device) {
|
||||
DeviceRemoved(device);
|
||||
device->SetDeviceList(NULL);
|
||||
fDevices.RemoveItemAt(index);
|
||||
delete device;
|
||||
}
|
||||
return (device != NULL);
|
||||
}
|
||||
|
||||
// RemoveDevice
|
||||
bool
|
||||
RDiskDeviceList::RemoveDevice(RDiskDevice *device)
|
||||
{
|
||||
bool success = false;
|
||||
if (device) {
|
||||
int32 index = fDevices.FindBinaryInsertionIndex(
|
||||
CompareIDPredicate<RDiskDevice>(device), &success);
|
||||
if (success)
|
||||
success = RemoveDevice(index);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// DeviceWithID
|
||||
RDiskDevice *
|
||||
RDiskDeviceList::DeviceWithID(int32 id, bool exact) const
|
||||
{
|
||||
bool inList = false;
|
||||
int32 index = fDevices.FindBinaryInsertionIndex(
|
||||
CompareIDPredicate<RDiskDevice>(id), &inList);
|
||||
return (inList || !exact ? DeviceAt(index) : NULL);
|
||||
}
|
||||
|
||||
// SessionWithID
|
||||
RSession *
|
||||
RDiskDeviceList::SessionWithID(int32 id) const
|
||||
{
|
||||
bool inList = false;
|
||||
int32 index = fSessions.FindBinaryInsertionIndex(
|
||||
CompareIDPredicate<RSession>(id), &inList);
|
||||
return (inList ? SessionAt(index) : NULL);
|
||||
}
|
||||
|
||||
// PartitionWithID
|
||||
RPartition *
|
||||
RDiskDeviceList::PartitionWithID(int32 id) const
|
||||
{
|
||||
bool inList = false;
|
||||
int32 index = fPartitions.FindBinaryInsertionIndex(
|
||||
CompareIDPredicate<RPartition>(id), &inList);
|
||||
return (inList ? PartitionAt(index) : NULL);
|
||||
}
|
||||
|
||||
// DeviceWithPath
|
||||
RDiskDevice *
|
||||
RDiskDeviceList::DeviceWithPath(const char *path) const
|
||||
{
|
||||
const RDiskDevice *device
|
||||
= fDevices.FindIf(CompareDevicePathPredicate(path));
|
||||
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()
|
||||
{
|
||||
FUNCTION_START();
|
||||
// TODO: This method should be reworked, as soon as we react on events only
|
||||
// and don't need to poll anymore. This method will then do an initial
|
||||
// scan only.
|
||||
status_t error = B_OK;
|
||||
if (Lock()) {
|
||||
// marked all devices untouched
|
||||
for (int32 i = 0; RDiskDevice *device = DeviceAt(i); i++)
|
||||
device->SetTouched(false);
|
||||
// scan the "/dev/disk" directory for devices
|
||||
BDirectory dir;
|
||||
if (dir.SetTo("/dev/disk") == B_OK) {
|
||||
error = _Scan(dir);
|
||||
}
|
||||
// remove all untouched devices
|
||||
for (int32 i = CountDevices() - 1; i >= 0; i--) {
|
||||
RDiskDevice *device = DeviceAt(i);
|
||||
if (!device->Touched())
|
||||
DeviceDisappeared(device->Path());
|
||||
}
|
||||
Unlock();
|
||||
} else
|
||||
error = B_ERROR;
|
||||
FUNCTION_END();
|
||||
return error;
|
||||
}
|
||||
|
||||
// Lock
|
||||
bool
|
||||
RDiskDeviceList::Lock()
|
||||
{
|
||||
return fLock.Lock();
|
||||
}
|
||||
|
||||
// Unlock
|
||||
void
|
||||
RDiskDeviceList::Unlock()
|
||||
{
|
||||
fLock.Unlock();
|
||||
}
|
||||
|
||||
// DeviceAdded
|
||||
void
|
||||
RDiskDeviceList::DeviceAdded(RDiskDevice *device, uint32 cause)
|
||||
{
|
||||
// propagate to sessions
|
||||
for (int32 i = 0; RSession *session = device->SessionAt(i); i++)
|
||||
SessionAdded(session, B_DEVICE_CAUSE_PARENT_CHANGED);
|
||||
// notifications
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_ADDED,
|
||||
cause, device) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE_LIST);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
|
||||
// DeviceRemoved
|
||||
void
|
||||
RDiskDeviceList::DeviceRemoved(RDiskDevice *device, uint32 cause)
|
||||
{
|
||||
// propagate to sessions
|
||||
for (int32 i = 0; RSession *session = device->SessionAt(i); i++)
|
||||
SessionRemoved(session, B_DEVICE_CAUSE_PARENT_CHANGED);
|
||||
// notifications
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_REMOVED,
|
||||
cause, device) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE_LIST);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
|
||||
// MediaChanged
|
||||
void
|
||||
RDiskDeviceList::MediaChanged(RDiskDevice *device, uint32 cause)
|
||||
{
|
||||
// notifications
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_MEDIA_CHANGED,
|
||||
cause, device) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
|
||||
// SessionAdded
|
||||
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);
|
||||
// notifications
|
||||
// TODO: bundle multiple session added events per device
|
||||
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_SESSION_ADDED,
|
||||
cause, session) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SessionRemoved
|
||||
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);
|
||||
// notifications
|
||||
// TODO: bundle multiple session removed events per device
|
||||
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_SESSION_REMOVED,
|
||||
cause, session) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PartitionAdded
|
||||
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);
|
||||
if (const RVolume *volume = fVolumeList.VolumeForDevicePath(path))
|
||||
partition->SetVolume(volume);
|
||||
// notifications
|
||||
// TODO: bundle multiple partition added events per session
|
||||
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_PARTITION_ADDED,
|
||||
cause, partition) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_SESSION);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PartitionRemoved
|
||||
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
|
||||
// TODO: bundle multiple partition removed events per session
|
||||
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_PARTITION_REMOVED,
|
||||
cause, partition) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_SESSION);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PartitionChanged
|
||||
void
|
||||
RDiskDeviceList::PartitionChanged(RPartition *partition, uint32 cause)
|
||||
{
|
||||
// notifications
|
||||
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification, B_DEVICE_PARTITION_CHANGED,
|
||||
cause, partition) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_PARTITION);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dump
|
||||
void
|
||||
RDiskDeviceList::Dump() const
|
||||
{
|
||||
for (int32 i = 0; RDiskDevice *device = DeviceAt(i); i++)
|
||||
device->Dump();
|
||||
}
|
||||
|
||||
// _Scan
|
||||
status_t
|
||||
RDiskDeviceList::_Scan(BDirectory &dir)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
BEntry entry;
|
||||
while (dir.GetNextEntry(&entry) == B_OK) {
|
||||
struct stat st;
|
||||
if (entry.GetStat(&st) == B_OK) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
BDirectory subdir;
|
||||
if (subdir.SetTo(&entry) == B_OK)
|
||||
error = _Scan(subdir);
|
||||
} else if (!S_ISLNK(st.st_mode)) {
|
||||
BPath path;
|
||||
if (entry.GetPath(&path) == B_OK) {
|
||||
_ScanDevice(path.Path());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _ScanDevice
|
||||
status_t
|
||||
RDiskDeviceList::_ScanDevice(const char *path)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// search the list for a device with that path
|
||||
if (RDiskDevice *device = DeviceWithPath(path)) {
|
||||
// found: just update it
|
||||
device->SetTouched(true);
|
||||
error = device->Update();
|
||||
} else {
|
||||
// not found: check whether it is really a disk device and add it to
|
||||
// the list
|
||||
// The event hook does the work anyway:
|
||||
DeviceAppeared(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;
|
||||
}
|
||||
|
@ -1,207 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include "RPartition.h"
|
||||
#include "RDiskDevice.h"
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "RSession.h"
|
||||
|
||||
// constructor
|
||||
RPartition::RPartition()
|
||||
: fSession(NULL),
|
||||
fID(-1),
|
||||
fChangeCounter(),
|
||||
fVolume(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
RPartition::~RPartition()
|
||||
{
|
||||
}
|
||||
|
||||
// SetTo
|
||||
status_t
|
||||
RPartition::SetTo(int fd, const extended_partition_info *partitionInfo)
|
||||
{
|
||||
Unset();
|
||||
status_t error = B_OK;
|
||||
fID = _NextID();
|
||||
fChangeCounter.Reset();
|
||||
fInfo = *partitionInfo;
|
||||
return error;
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
RPartition::Unset()
|
||||
{
|
||||
fID = -1;
|
||||
}
|
||||
|
||||
// PartitionChanged
|
||||
status_t
|
||||
RPartition::PartitionChanged()
|
||||
{
|
||||
Changed();
|
||||
status_t error = B_OK;
|
||||
// notification
|
||||
if (RDiskDeviceList *deviceList = DeviceList())
|
||||
deviceList->PartitionChanged(this, B_DEVICE_CAUSE_UNKNOWN);
|
||||
return error;
|
||||
}
|
||||
|
||||
// DeviceList
|
||||
RDiskDeviceList *
|
||||
RPartition::DeviceList() const
|
||||
{
|
||||
return (fSession ? fSession->DeviceList() : NULL);
|
||||
}
|
||||
|
||||
// Device
|
||||
RDiskDevice *
|
||||
RPartition::Device() const
|
||||
{
|
||||
return (fSession ? fSession->Device() : NULL);
|
||||
}
|
||||
|
||||
// Changed
|
||||
void
|
||||
RPartition::Changed()
|
||||
{
|
||||
if (fChangeCounter.Increment() && fSession)
|
||||
fSession->Changed();
|
||||
}
|
||||
|
||||
// Index
|
||||
int32
|
||||
RPartition::Index() const
|
||||
{
|
||||
if (fSession)
|
||||
return fSession->IndexOfPartition(this);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// GetPath
|
||||
void
|
||||
RPartition::GetPath(char *path) const
|
||||
{
|
||||
RDiskDevice *device = Device();
|
||||
if (path && device) {
|
||||
strcpy(path, device->Path());
|
||||
if (char *lastSlash = strrchr(path, '/'))
|
||||
sprintf(lastSlash + 1, "%ld_%ld", Session()->Index(), Index());
|
||||
}
|
||||
}
|
||||
|
||||
// Update
|
||||
status_t
|
||||
RPartition::Update(const extended_partition_info *partitionInfo)
|
||||
{
|
||||
RChangeCounter::Locker lock(fChangeCounter);
|
||||
status_t error = B_OK;
|
||||
// check the partition info for changes
|
||||
// Currently there is very little that can have changed. offset and size
|
||||
// must not be changed, logical_block_size and device are ignored anyway
|
||||
// and session and partition index don't change.
|
||||
// So only the fields in extended_partition_info - partition_info remain.
|
||||
if (partitionInfo->flags != fInfo.flags
|
||||
|| strcmp(partitionInfo->partition_name, fInfo.partition_name)
|
||||
|| strcmp(partitionInfo->partition_type, fInfo.partition_type)
|
||||
|| strcmp(partitionInfo->file_system_short_name,
|
||||
fInfo.file_system_short_name)
|
||||
|| strcmp(partitionInfo->file_system_short_name,
|
||||
fInfo.file_system_short_name)
|
||||
|| strcmp(partitionInfo->file_system_long_name,
|
||||
fInfo.file_system_long_name)
|
||||
|| strcmp(partitionInfo->volume_name, fInfo.volume_name)
|
||||
|| partitionInfo->file_system_flags != fInfo.file_system_flags) {
|
||||
fInfo = *partitionInfo;
|
||||
PartitionChanged();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Archive
|
||||
status_t
|
||||
RPartition::Archive(BMessage *archive) const
|
||||
{
|
||||
status_t error = (archive ? B_OK : B_BAD_VALUE);
|
||||
// ID, change counter and index
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("id", fID);
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("change_counter", ChangeCounter());
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("index", Index());
|
||||
// fInfo.info.*
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt64("offset", fInfo.info.offset);
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt64("size", fInfo.info.size);
|
||||
// fInfo.*
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("flags", (int32)fInfo.flags);
|
||||
if (error == B_OK)
|
||||
error = archive->AddString("name", fInfo.partition_name);
|
||||
if (error == B_OK)
|
||||
error = archive->AddString("type", fInfo.partition_type);
|
||||
if (error == B_OK) {
|
||||
error = archive->AddString("fs_short_name",
|
||||
fInfo.file_system_short_name);
|
||||
}
|
||||
if (error == B_OK) {
|
||||
error = archive->AddString("fs_long_name",
|
||||
fInfo.file_system_long_name);
|
||||
}
|
||||
if (error == B_OK)
|
||||
error = archive->AddString("volume_name", fInfo.volume_name);
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("fs_flags", (int32)fInfo.file_system_flags);
|
||||
// dev_t, if mounted
|
||||
if (error == B_OK && fVolume)
|
||||
error = archive->AddInt32("volume_id", fVolume->ID());
|
||||
return error;
|
||||
}
|
||||
|
||||
// print_partition_info
|
||||
static
|
||||
void
|
||||
print_partition_info(const char *prefix, const extended_partition_info &info)
|
||||
{
|
||||
printf("%soffset: %lld\n", prefix, info.info.offset);
|
||||
printf("%ssize: %lld\n", prefix, info.info.size);
|
||||
printf("%sblock size: %ld\n", prefix, info.info.logical_block_size);
|
||||
printf("%ssession ID: %ld\n", prefix, info.info.session);
|
||||
printf("%spartition ID: %ld\n", prefix, info.info.partition);
|
||||
printf("%sdevice: `%s'\n", prefix, info.info.device);
|
||||
printf("%sflags: %lx\n", prefix, info.flags);
|
||||
printf("%spartition name: `%s'\n", prefix, info.partition_name);
|
||||
printf("%spartition type: `%s'\n", prefix, info.partition_type);
|
||||
printf("%sFS short name: `%s'\n", prefix, info.file_system_short_name);
|
||||
printf("%sFS long name: `%s'\n", prefix, info.file_system_long_name);
|
||||
printf("%svolume name: `%s'\n", prefix, info.volume_name);
|
||||
// printf("%smounted at: `%s'\n", prefix, info.mounted_at);
|
||||
printf("%sFS flags: 0x%lx\n", prefix, info.file_system_flags);
|
||||
}
|
||||
|
||||
// Dump
|
||||
void
|
||||
RPartition::Dump() const
|
||||
{
|
||||
printf(" partition %ld:\n", fInfo.info.partition);
|
||||
print_partition_info(" ", fInfo);
|
||||
}
|
||||
|
||||
// _NextID
|
||||
int32
|
||||
RPartition::_NextID()
|
||||
{
|
||||
return atomic_add(&fNextID, 1);
|
||||
}
|
||||
|
||||
// fNextID
|
||||
vint32 RPartition::fNextID = 0;
|
||||
|
@ -1,305 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <new.h>
|
||||
|
||||
#include <Drivers.h>
|
||||
|
||||
#include "RSession.h"
|
||||
#include "RDiskDevice.h"
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "RPartition.h"
|
||||
|
||||
// constructor
|
||||
RSession::RSession()
|
||||
: fPartitions(10, true),
|
||||
fDevice(NULL),
|
||||
fID(-1),
|
||||
fChangeCounter()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
RSession::~RSession()
|
||||
{
|
||||
}
|
||||
|
||||
// SetTo
|
||||
status_t
|
||||
RSession::SetTo(int fd, const session_info *sessionInfo)
|
||||
{
|
||||
Unset();
|
||||
status_t error = B_OK;
|
||||
fID = _NextID();
|
||||
fChangeCounter.Reset();
|
||||
fInfo = *sessionInfo;
|
||||
// scan for partitions
|
||||
error = _RescanPartitions(fd, B_DEVICE_CAUSE_UNKNOWN);
|
||||
// cleanup on error
|
||||
if (error != B_OK)
|
||||
Unset();
|
||||
return error;
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
RSession::Unset()
|
||||
{
|
||||
for (int32 i = CountPartitions() - 1; i >= 0; i--)
|
||||
RemovePartition(i, B_DEVICE_CAUSE_UNKNOWN);
|
||||
fID = -1;
|
||||
}
|
||||
|
||||
// DeviceList
|
||||
RDiskDeviceList *
|
||||
RSession::DeviceList() const
|
||||
{
|
||||
return (fDevice ? fDevice->DeviceList() : NULL);
|
||||
}
|
||||
|
||||
// PartitionLayoutChanged
|
||||
status_t
|
||||
RSession::PartitionLayoutChanged()
|
||||
{
|
||||
PRINT(("RSession::PartitionLayoutChanged()\n"));
|
||||
Changed();
|
||||
status_t error = (fDevice ? B_OK : B_ERROR);
|
||||
if (error == B_OK)
|
||||
error = _RescanPartitions(fDevice->FD(), B_DEVICE_CAUSE_UNKNOWN);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Changed
|
||||
void
|
||||
RSession::Changed()
|
||||
{
|
||||
if (fChangeCounter.Increment() && fDevice)
|
||||
fDevice->Changed();
|
||||
}
|
||||
|
||||
// Index
|
||||
int32
|
||||
RSession::Index() const
|
||||
{
|
||||
if (fDevice)
|
||||
return fDevice->IndexOfSession(this);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// AddPartition
|
||||
status_t
|
||||
RSession::AddPartition(int fd, const extended_partition_info *partitionInfo,
|
||||
uint32 cause)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (RPartition *partition = new(nothrow) RPartition) {
|
||||
error = partition->SetTo(fd, partitionInfo);
|
||||
if (error == B_OK)
|
||||
AddPartition(partition, cause);
|
||||
else
|
||||
delete partition;
|
||||
} else
|
||||
error = B_NO_MEMORY;
|
||||
return error;
|
||||
}
|
||||
|
||||
// AddPartition
|
||||
bool
|
||||
RSession::AddPartition(RPartition *partition, uint32 cause)
|
||||
{
|
||||
bool success = false;
|
||||
if (partition) {
|
||||
success = fPartitions.AddItem(partition);
|
||||
if (success) {
|
||||
partition->SetSession(this);
|
||||
Changed();
|
||||
// trigger notifications
|
||||
if (RDiskDeviceList *deviceList = DeviceList())
|
||||
deviceList->PartitionAdded(partition, cause);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// RemovePartition
|
||||
bool
|
||||
RSession::RemovePartition(int32 index, uint32 cause)
|
||||
{
|
||||
RPartition *partition = PartitionAt(index);
|
||||
if (partition) {
|
||||
Changed();
|
||||
if (RDiskDeviceList *deviceList = DeviceList())
|
||||
deviceList->PartitionRemoved(partition, cause);
|
||||
partition->SetSession(NULL);
|
||||
fPartitions.RemoveItemAt(index);
|
||||
delete partition;
|
||||
}
|
||||
return (partition != NULL);
|
||||
}
|
||||
|
||||
// RemovePartition
|
||||
bool
|
||||
RSession::RemovePartition(RPartition *partition, uint32 cause)
|
||||
{
|
||||
bool success = false;
|
||||
if (partition) {
|
||||
int32 index = fPartitions.IndexOf(partition);
|
||||
if (index >= 0)
|
||||
success = RemovePartition(index, cause);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// Update
|
||||
status_t
|
||||
RSession::Update(const session_info *sessionInfo)
|
||||
{
|
||||
RChangeCounter::Locker lock(fChangeCounter);
|
||||
status_t error = (fDevice ? B_OK : B_ERROR);
|
||||
// check the session info for changes
|
||||
// Currently there is very little that can have changed. offset and size
|
||||
// must not be changed, logical_block_size is ignored anyway and index
|
||||
// doesn't change. So only flags remains, but that indicates only, if the
|
||||
// session is virtual or a data/audio partition. So we don't do anything
|
||||
// for now.
|
||||
fInfo = *sessionInfo;
|
||||
int fd = (fDevice ? fDevice->FD() : -1);
|
||||
// check the partitions
|
||||
for (int32 i = 0; error == B_OK; i++) {
|
||||
// get the partition info
|
||||
extended_partition_info partitionInfo;
|
||||
char partitioningSystem[B_FILE_NAME_LENGTH];
|
||||
status_t status = get_nth_partition_info(fd, sessionInfo->index, i,
|
||||
&partitionInfo, (i == 0 ? partitioningSystem : NULL));
|
||||
// check the partitioning system
|
||||
if ((status == B_OK || status == B_ENTRY_NOT_FOUND) && i == 0
|
||||
&& strcmp(partitioningSystem, fPartitioningSystem)) {
|
||||
// partitioning system has changed
|
||||
error = PartitionLayoutChanged();
|
||||
break;
|
||||
}
|
||||
if (status != B_OK) {
|
||||
if (status == B_ENTRY_NOT_FOUND) {
|
||||
// remove disappeared partitions
|
||||
for (int32 k = CountPartitions() - 1; k >= i; k--)
|
||||
RemovePartition(k, B_DEVICE_CAUSE_UNKNOWN);
|
||||
} else {
|
||||
// ignore errors -- we can't help it
|
||||
// error = status;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// check the partition
|
||||
if (RPartition *partition = PartitionAt(i)) {
|
||||
if (partition->Offset() == partitionInfo.info.offset
|
||||
&& partition->Size() == partitionInfo.info.size) {
|
||||
partition->Update(&partitionInfo);
|
||||
} else {
|
||||
// partition layout changed
|
||||
error = PartitionLayoutChanged();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// partition added
|
||||
error = AddPartition(fd, &partitionInfo, B_DEVICE_CAUSE_UNKNOWN);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Archive
|
||||
status_t
|
||||
RSession::Archive(BMessage *archive) const
|
||||
{
|
||||
status_t error = (archive ? B_OK : B_BAD_VALUE);
|
||||
// ID, change counter and index
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("id", fID);
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("change_counter", ChangeCounter());
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("index", Index());
|
||||
// fInfo.*
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt64("offset", fInfo.offset);
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt64("size", fInfo.size);
|
||||
if (error == B_OK)
|
||||
error = archive->AddInt32("flags", (int32)fInfo.flags);
|
||||
// other data
|
||||
if (error == B_OK)
|
||||
error = archive->AddString("partitioning", fPartitioningSystem);
|
||||
// partitions
|
||||
for (int32 i = 0; const RPartition *partition = PartitionAt(i); i++) {
|
||||
BMessage partitionArchive;
|
||||
error = partition->Archive(&partitionArchive);
|
||||
if (error == B_OK)
|
||||
error = archive->AddMessage("partitions", &partitionArchive);
|
||||
if (error != B_OK)
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// print_session_info
|
||||
static
|
||||
void
|
||||
print_session_info(const char *prefix, const session_info &info)
|
||||
{
|
||||
printf("%soffset: %lld\n", prefix, info.offset);
|
||||
printf("%ssize: %lld\n", prefix, info.size);
|
||||
printf("%sblock size: %ld\n", prefix, info.logical_block_size);
|
||||
printf("%sindex: %ld\n", prefix, info.index);
|
||||
printf("%sflags: %lx\n", prefix, info.flags);
|
||||
}
|
||||
|
||||
// Dump
|
||||
void
|
||||
RSession::Dump() const
|
||||
{
|
||||
printf(" session %ld:\n", fInfo.index);
|
||||
print_session_info(" ", fInfo);
|
||||
printf(" partitioning : `%s'\n", fPartitioningSystem);
|
||||
for (int32 i = 0; RPartition *partition = PartitionAt(i); i++)
|
||||
partition->Dump();
|
||||
}
|
||||
|
||||
// _RescanPartitions
|
||||
status_t
|
||||
RSession::_RescanPartitions(int fd, uint32 cause)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// remove the current partitions
|
||||
for (int32 i = CountPartitions() - 1; i >= 0; i--)
|
||||
RemovePartition(i, cause);
|
||||
// scan for partitions
|
||||
for (int32 i = 0; error == B_OK; i++) {
|
||||
// get the partition info
|
||||
extended_partition_info partitionInfo;
|
||||
status_t status = get_nth_partition_info(fd, fInfo.index, i,
|
||||
&partitionInfo, (i == 0 ? fPartitioningSystem : NULL));
|
||||
if (status != B_OK) {
|
||||
if (status != B_ENTRY_NOT_FOUND) {
|
||||
// ignore errors -- we can't help it
|
||||
// error = status;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// create and add a RPartition
|
||||
error = AddPartition(fd, &partitionInfo, cause);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _NextID
|
||||
int32
|
||||
RSession::_NextID()
|
||||
{
|
||||
return atomic_add(&fNextID, 1);
|
||||
}
|
||||
|
||||
// fNextID
|
||||
vint32 RSession::fNextID = 0;
|
||||
|
@ -1,385 +0,0 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#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) {}
|
||||
CompareIDPredicate(const RVolume *volume) : fID(volume->ID()) {}
|
||||
|
||||
virtual int operator()(const RVolume *volume) const
|
||||
{
|
||||
dev_t id = volume->ID();
|
||||
if (fID < id)
|
||||
return 1;
|
||||
if (fID > id)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
dev_t fID;
|
||||
};
|
||||
|
||||
// CompareDevicePathPredicate
|
||||
struct CompareDevicePathPredicate : public UnaryPredicate<RVolume> {
|
||||
CompareDevicePathPredicate(const char *path) : fPath(path) {}
|
||||
|
||||
virtual int operator()(const RVolume *volume) const
|
||||
{
|
||||
return strcmp(fPath, volume->DevicePath());
|
||||
}
|
||||
|
||||
private:
|
||||
const char *fPath;
|
||||
};
|
||||
|
||||
} // namespace RVolumeListPredicates
|
||||
|
||||
using namespace RVolumeListPredicates;
|
||||
|
||||
|
||||
// RVolume
|
||||
|
||||
// constructor
|
||||
RVolume::RVolume()
|
||||
: fID(-1),
|
||||
fRootNode(-1),
|
||||
fRootEntry()
|
||||
{
|
||||
}
|
||||
|
||||
// SetTo
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
RVolume::Unset()
|
||||
{
|
||||
fID = -1;
|
||||
fRootNode = -1;
|
||||
}
|
||||
|
||||
// StartWatching
|
||||
status_t
|
||||
RVolume::StartWatching(BMessenger target) const
|
||||
{
|
||||
node_ref ref;
|
||||
ref.device = fID;
|
||||
ref.node = fRootNode;
|
||||
return watch_node(&ref, B_WATCH_NAME, target);
|
||||
}
|
||||
|
||||
// StopWatching
|
||||
status_t
|
||||
RVolume::StopWatching(BMessenger target) const
|
||||
{
|
||||
node_ref ref;
|
||||
ref.device = fID;
|
||||
ref.node = fRootNode;
|
||||
return watch_node(&ref, B_STOP_WATCHING, target);
|
||||
}
|
||||
|
||||
|
||||
// RVolumeListListener
|
||||
|
||||
// constructor
|
||||
RVolumeListListener::RVolumeListListener()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
RVolumeListListener::~RVolumeListListener()
|
||||
{
|
||||
}
|
||||
|
||||
// VolumeMounted
|
||||
void
|
||||
RVolumeListListener::VolumeMounted(const RVolume *volume)
|
||||
{
|
||||
}
|
||||
|
||||
// VolumeUnmounted
|
||||
void
|
||||
RVolumeListListener::VolumeUnmounted(const RVolume *volume)
|
||||
{
|
||||
}
|
||||
|
||||
// MountPointMoved
|
||||
void
|
||||
RVolumeListListener::MountPointMoved(const RVolume *volume,
|
||||
const entry_ref *oldRoot,
|
||||
const entry_ref *newRoot)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// RVolumeList
|
||||
|
||||
// constructor
|
||||
RVolumeList::RVolumeList(BMessenger target, BLocker &lock)
|
||||
: MessageHandler(),
|
||||
fLock(lock),
|
||||
fTarget(target),
|
||||
fVolumes(20, true),
|
||||
fRoster(),
|
||||
fListener(NULL)
|
||||
{
|
||||
// TODO: Remove work-around. At this time R5 libbe's watching functions don't
|
||||
// work for us. We have an own implementation in `NodeMonitoring.cpp'.
|
||||
// fRoster.StartWatching(BMessenger(this));
|
||||
watch_node(NULL, B_WATCH_MOUNT, fTarget);
|
||||
Rescan();
|
||||
}
|
||||
|
||||
// destructor
|
||||
RVolumeList::~RVolumeList()
|
||||
{
|
||||
// TODO: Remove work-around. At this time R5 libbe's watching functions don't
|
||||
// work for us. We have an own implementation in `NodeMonitoring.cpp'.
|
||||
// fRoster.StopWatching();
|
||||
stop_watching(fTarget);
|
||||
}
|
||||
|
||||
// HandleMessage
|
||||
void
|
||||
RVolumeList::HandleMessage(BMessage *message)
|
||||
{
|
||||
if (Lock()) {
|
||||
switch (message->what) {
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
int32 opcode = 0;
|
||||
if (message->FindInt32("opcode", &opcode) == B_OK) {
|
||||
switch (opcode) {
|
||||
case B_DEVICE_MOUNTED:
|
||||
_DeviceMounted(message);
|
||||
break;
|
||||
case B_DEVICE_UNMOUNTED:
|
||||
_DeviceUnmounted(message);
|
||||
break;
|
||||
case B_ENTRY_MOVED:
|
||||
_MountPointMoved(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MessageHandler::HandleMessage(message);
|
||||
break;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Rescan
|
||||
status_t
|
||||
RVolumeList::Rescan()
|
||||
{
|
||||
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());
|
||||
PRINT(("RVolumeList::Rescan() done\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// VolumeForDevicePath
|
||||
const RVolume *
|
||||
RVolumeList::VolumeForDevicePath(const char *devicePath) const
|
||||
{
|
||||
const RVolume *volume = NULL;
|
||||
if (devicePath && fLock.Lock()) {
|
||||
bool found = false;
|
||||
int32 index = fVolumes.FindBinaryInsertionIndex(
|
||||
CompareDevicePathPredicate(devicePath), &found);
|
||||
if (found)
|
||||
volume = fVolumes.ItemAt(index);
|
||||
fLock.Unlock();
|
||||
}
|
||||
return volume;
|
||||
}
|
||||
|
||||
// Lock
|
||||
bool
|
||||
RVolumeList::Lock()
|
||||
{
|
||||
return fLock.Lock();
|
||||
}
|
||||
|
||||
// Unlock
|
||||
void
|
||||
RVolumeList::Unlock()
|
||||
{
|
||||
fLock.Unlock();
|
||||
}
|
||||
|
||||
// SetListener
|
||||
void
|
||||
RVolumeList::SetListener(RVolumeListListener *listener)
|
||||
{
|
||||
fListener = listener;
|
||||
}
|
||||
|
||||
// Dump
|
||||
void
|
||||
RVolumeList::Dump() const
|
||||
{
|
||||
for (int32 i = 0; RVolume *volume = fVolumes.ItemAt(i); i++) {
|
||||
printf("volume %ld:\n", volume->ID());
|
||||
printf(" root node: %lld", volume->RootNode());
|
||||
printf(" device: `%s'\n", volume->DevicePath());
|
||||
}
|
||||
}
|
||||
|
||||
// _AddVolume
|
||||
RVolume *
|
||||
RVolumeList::_AddVolume(dev_t id)
|
||||
{
|
||||
RVolume *volume = new RVolume;
|
||||
if (volume) {
|
||||
status_t error = volume->SetTo(id);
|
||||
if (error == B_OK) {
|
||||
fVolumes.BinaryInsert(volume,
|
||||
CompareDevicePathPredicate(volume->DevicePath()));
|
||||
volume->StartWatching(fTarget);
|
||||
} else {
|
||||
delete volume;
|
||||
volume = NULL;
|
||||
PRINT(("RVolumeList::_AddVolume(): initializing RVolume failed: "
|
||||
"%s\n", strerror(error)));
|
||||
}
|
||||
} else
|
||||
PRINT(("RVolumeList::_AddVolume(): no memory!\n"));
|
||||
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)
|
||||
{
|
||||
dev_t device;
|
||||
if (message->FindInt32("new device", &device) == B_OK) {
|
||||
PRINT(("RVolumeList::_DeviceMounted(%ld)\n", device));
|
||||
if (RVolume *volume = _AddVolume(device)) {
|
||||
if (fListener)
|
||||
fListener->VolumeMounted(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _DeviceUnmounted
|
||||
void
|
||||
RVolumeList::_DeviceUnmounted(BMessage *message)
|
||||
{
|
||||
dev_t device;
|
||||
if (message->FindInt32("device", &device) == B_OK) {
|
||||
PRINT(("RVolumeList::_DeviceUnmounted(%ld)\n", device));
|
||||
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) {
|
||||
volume->StopWatching(fTarget);
|
||||
fVolumes.RemoveItem(volume, false);
|
||||
if (fListener)
|
||||
fListener->VolumeUnmounted(volume);
|
||||
delete volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _MountPointMoved
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <RosterPrivate.h>
|
||||
|
||||
#include "ClipboardHandler.h"
|
||||
#include "DiskDeviceManager.h"
|
||||
#include "EventQueue.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "MessageRunnerManager.h"
|
||||
@ -38,7 +37,6 @@ Registrar::Registrar()
|
||||
fRoster(NULL),
|
||||
fClipboardHandler(NULL),
|
||||
fMIMEManager(NULL),
|
||||
fDiskDeviceManager(NULL),
|
||||
fEventQueue(NULL),
|
||||
fMessageRunnerManager(NULL),
|
||||
fSanityEvent(NULL)
|
||||
@ -60,8 +58,6 @@ Registrar::~Registrar()
|
||||
delete fMessageRunnerManager;
|
||||
delete fEventQueue;
|
||||
delete fSanityEvent;
|
||||
fDiskDeviceManager->Lock();
|
||||
fDiskDeviceManager->Quit();
|
||||
fMIMEManager->Lock();
|
||||
fMIMEManager->Quit();
|
||||
RemoveHandler(fClipboardHandler);
|
||||
@ -102,15 +98,6 @@ Registrar::MessageReceived(BMessage *message)
|
||||
message->SendReply(&reply);
|
||||
break;
|
||||
}
|
||||
case B_REG_GET_DISK_DEVICE_MESSENGER:
|
||||
{
|
||||
PRINT(("B_REG_GET_DISK_DEVICE_MESSENGER\n"));
|
||||
BMessenger messenger(NULL, fDiskDeviceManager);
|
||||
BMessage reply(B_REG_SUCCESS);
|
||||
reply.AddMessenger("messenger", messenger);
|
||||
message->SendReply(&reply);
|
||||
break;
|
||||
}
|
||||
// roster requests
|
||||
case B_REG_ADD_APP:
|
||||
fRoster->HandleAddApplication(message);
|
||||
@ -229,9 +216,6 @@ Registrar::ReadyToRun()
|
||||
// create MIME manager
|
||||
fMIMEManager = new MIMEManager;
|
||||
fMIMEManager->Run();
|
||||
// create disk device manager
|
||||
fDiskDeviceManager = new DiskDeviceManager(fEventQueue);
|
||||
fDiskDeviceManager->Run();
|
||||
// create message runner manager
|
||||
fMessageRunnerManager = new MessageRunnerManager(fEventQueue);
|
||||
// init the global be_roster
|
||||
|
@ -56,7 +56,6 @@ private:
|
||||
BPrivate::TRoster *fRoster;
|
||||
ClipboardHandler *fClipboardHandler;
|
||||
MIMEManager *fMIMEManager;
|
||||
DiskDeviceManager *fDiskDeviceManager;
|
||||
EventQueue *fEventQueue;
|
||||
MessageRunnerManager *fMessageRunnerManager;
|
||||
MessageEvent *fSanityEvent;
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <Application.h>
|
||||
#include <AppMisc.h>
|
||||
#include <File.h>
|
||||
#include <storage_support.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
Loading…
Reference in New Issue
Block a user