Removed unused files.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34223 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
9fd6a5448d
commit
d1b0d5a4af
|
@ -1,54 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include "AddOnImage.h"
|
||||
|
||||
// constructor
|
||||
AddOnImage::AddOnImage()
|
||||
: fID(-1)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
AddOnImage::~AddOnImage()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
|
||||
// Load
|
||||
status_t
|
||||
AddOnImage::Load(const char *path)
|
||||
{
|
||||
Unload();
|
||||
status_t error = (path ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
image_id id = load_add_on(path);
|
||||
if (id >= 0)
|
||||
fID = id;
|
||||
else
|
||||
error = id;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Unload
|
||||
void
|
||||
AddOnImage::Unload()
|
||||
{
|
||||
if (fID >= 0) {
|
||||
unload_add_on(fID);
|
||||
fID = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// SetID
|
||||
void
|
||||
AddOnImage::SetID(image_id id)
|
||||
{
|
||||
Unload();
|
||||
if (id >= 0)
|
||||
fID = id;
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#ifndef _ADD_ON_IMAGE_H
|
||||
#define _ADD_ON_IMAGE_H
|
||||
|
||||
#include <image.h>
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
class AddOnImage {
|
||||
public:
|
||||
AddOnImage();
|
||||
~AddOnImage();
|
||||
|
||||
status_t Load(const char *path);
|
||||
void Unload();
|
||||
|
||||
void SetID(image_id id);
|
||||
image_id ID() const { return fID; }
|
||||
|
||||
private:
|
||||
image_id fID;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
using BPrivate::AddOnImage;
|
||||
|
||||
#endif // _ADD_ON_IMAGE_H
|
|
@ -1,55 +0,0 @@
|
|||
#include "AddOnMonitor.h"
|
||||
#include "AddOnMonitorHandler.h"
|
||||
#include <Message.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <Messenger.h>
|
||||
#include <stdio.h>
|
||||
|
||||
AddOnMonitor::AddOnMonitor(AddOnMonitorHandler * handler)
|
||||
: BLooper("AddOnMonitor")
|
||||
{
|
||||
fInitCheck = B_NO_INIT;
|
||||
AddHandler(handler);
|
||||
SetPreferredHandler(handler);
|
||||
status_t status;
|
||||
BMessenger messenger(handler, this, &status);
|
||||
if (status != B_OK) {
|
||||
fInitCheck = status;
|
||||
return;
|
||||
}
|
||||
if (!messenger.IsValid()) {
|
||||
fInitCheck = B_ERROR;
|
||||
return;
|
||||
}
|
||||
fPulseMessage = new BMessage(B_PULSE);
|
||||
fPulseRunner = new BMessageRunner(messenger, fPulseMessage, 1000000);
|
||||
status = fPulseRunner->InitCheck();
|
||||
if (status != B_OK) {
|
||||
fInitCheck = status;
|
||||
fprintf(stderr, "AddOnMonitor() : bad status returned by fPulseRunner->InitCheck()\n");
|
||||
return;
|
||||
}
|
||||
thread_id id = Run();
|
||||
if (id < 0) {
|
||||
fInitCheck = (status_t)id;
|
||||
fprintf(stderr, "AddOnMonitor() : bad id returned by Run()\n");
|
||||
return;
|
||||
}
|
||||
fInitCheck = B_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* virtual */
|
||||
AddOnMonitor::~AddOnMonitor()
|
||||
{
|
||||
delete fPulseMessage;
|
||||
delete fPulseRunner;
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ status_t
|
||||
AddOnMonitor::InitCheck()
|
||||
{
|
||||
return fInitCheck;
|
||||
}
|
|
@ -1,558 +0,0 @@
|
|||
#include "AddOnMonitorHandler.h"
|
||||
#include <Directory.h>
|
||||
|
||||
#ifndef ADD_ON_STABLE_SECONDS
|
||||
#define ADD_ON_STABLE_SECONDS 15
|
||||
#endif
|
||||
|
||||
/*
|
||||
* public functions
|
||||
*/
|
||||
|
||||
AddOnMonitorHandler::AddOnMonitorHandler(const char * name)
|
||||
: NodeMonitorHandler(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AddOnMonitorHandler::~AddOnMonitorHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::MessageReceived(BMessage * msg)
|
||||
{
|
||||
if (msg->what == B_PULSE) {
|
||||
HandlePulse();
|
||||
}
|
||||
inherited::MessageReceived(msg);
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ status_t
|
||||
AddOnMonitorHandler::AddDirectory(const node_ref * nref)
|
||||
{
|
||||
// ignore directories added twice
|
||||
std::list<add_on_directory_info>::iterator diter = directories.begin();
|
||||
for( ; diter != directories.end() ; diter++) {
|
||||
if (diter->nref == *nref) {
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
BDirectory directory(nref);
|
||||
status_t status = directory.InitCheck();
|
||||
if (status != B_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
add_on_directory_info dir_info;
|
||||
dir_info.nref = *nref;
|
||||
directories.push_back(dir_info);
|
||||
|
||||
status = watch_node(nref, B_WATCH_DIRECTORY, this);
|
||||
if (status != B_OK) {
|
||||
directories.pop_back();
|
||||
return status;
|
||||
}
|
||||
|
||||
BEntry entry;
|
||||
while (directory.GetNextEntry(&entry, true) == B_OK) {
|
||||
add_on_entry_info entry_info;
|
||||
if (entry.GetName(entry_info.name) != B_OK) {
|
||||
continue; // discard and proceed
|
||||
}
|
||||
if (entry.GetNodeRef(&entry_info.nref) != B_OK) {
|
||||
continue; // discard and proceed
|
||||
}
|
||||
entry_info.dir_nref = *nref;
|
||||
pending_entries.push_back(entry_info);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AddOnMonitorHandler hooks
|
||||
*/
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::AddOnCreated(const add_on_entry_info * entry_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::AddOnEnabled(const add_on_entry_info * entry_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::AddOnDisabled(const add_on_entry_info * entry_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::AddOnRemoved(const add_on_entry_info * entry_info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NodeMonitorHandler hooks
|
||||
*/
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::EntryCreated(const char *name, ino_t directory,
|
||||
dev_t device, ino_t node)
|
||||
{
|
||||
add_on_entry_info entry_info;
|
||||
strncpy(entry_info.name, name, sizeof(entry_info.name));
|
||||
make_node_ref(device, node, &entry_info.nref);
|
||||
make_node_ref(device, directory, &entry_info.dir_nref);
|
||||
pending_entries.push_back(entry_info);
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::EntryRemoved(ino_t directory, dev_t device, ino_t node)
|
||||
{
|
||||
node_ref entry_nref;
|
||||
make_node_ref(device, node, &entry_nref);
|
||||
|
||||
// Search pending entries first, which can simply be discarded
|
||||
// We might have this entry in the pending list multiple times,
|
||||
// so we search entire list through, even after finding one.
|
||||
std::list<add_on_entry_info>::iterator eiter = pending_entries.begin();
|
||||
while (eiter != pending_entries.end()) {
|
||||
if (eiter->nref == entry_nref) {
|
||||
eiter = pending_entries.erase(eiter);
|
||||
} else {
|
||||
eiter++;
|
||||
}
|
||||
}
|
||||
|
||||
add_on_entry_info info;
|
||||
node_ref dir_nref;
|
||||
make_node_ref(device, directory, &dir_nref);
|
||||
|
||||
// find the entry's info, and the entry's directory info
|
||||
std::list<add_on_directory_info>::iterator diter = directories.begin();
|
||||
for( ; diter != directories.end() ; diter++) {
|
||||
if (diter->nref == dir_nref) {
|
||||
std::list<add_on_entry_info>::iterator eiter = diter->entries.begin();
|
||||
for( ; eiter != diter->entries.end() ; eiter++) {
|
||||
info = *eiter;
|
||||
if (eiter->nref == entry_nref) {
|
||||
info = *eiter;
|
||||
diter->entries.erase(eiter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if it was not found, we're done
|
||||
if (diter == directories.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start at the top again, and search until the directory we found
|
||||
// the old add_on in. If we find a add_on with the same name then
|
||||
// the old add_on was not enabled. So we deallocate the old
|
||||
// add_on and return.
|
||||
std::list<add_on_directory_info>::iterator diter2 = directories.begin();
|
||||
for( ; diter2 != diter ; diter2++) {
|
||||
std::list<add_on_entry_info>::iterator eiter = diter2->entries.begin();
|
||||
for( ; eiter != diter2->entries.end() ; eiter++) {
|
||||
if (strcmp(eiter->name, info.name) == 0) {
|
||||
AddOnRemoved(&info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The active plugin was removed. We need to disable and
|
||||
// then subsequently deallocate it.
|
||||
AddOnDisabled(&info);
|
||||
AddOnRemoved(&info);
|
||||
|
||||
// Continue searching for a add_on below us. If we find a add_on
|
||||
// with the same name, we must enable it.
|
||||
for (diter++ ; diter != directories.end() ; diter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter = diter->entries.begin();
|
||||
for( ; eiter != diter->entries.end() ; eiter++) {
|
||||
if (strcmp(eiter->name, info.name) == 0) {
|
||||
AddOnEnabled(&*eiter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
AddOnMonitorHandler::EntryMoved(const char *name, ino_t from_directory,
|
||||
ino_t to_directory, dev_t device, ino_t node)
|
||||
{
|
||||
node_ref from_nref;
|
||||
make_node_ref(device, from_directory, &from_nref);
|
||||
std::list<add_on_directory_info>::iterator from_iter = directories.begin();
|
||||
for ( ; from_iter != directories.end() ; from_iter++) {
|
||||
if (from_iter->nref == from_nref) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
node_ref to_nref;
|
||||
make_node_ref(device, to_directory, &to_nref);
|
||||
std::list<add_on_directory_info>::iterator to_iter = directories.begin();
|
||||
for ( ; to_iter != directories.end() ; to_iter++) {
|
||||
if (to_iter->nref == to_nref) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((from_iter == directories.end()) && (to_iter == directories.end())) {
|
||||
// huh? whatever...
|
||||
return;
|
||||
}
|
||||
|
||||
add_on_entry_info info;
|
||||
node_ref entry_nref;
|
||||
make_node_ref(device, node, &entry_nref);
|
||||
|
||||
if (to_iter == directories.end()) {
|
||||
// moved out of our view
|
||||
std::list<add_on_entry_info>::iterator eiter = from_iter->entries.begin();
|
||||
for( ; eiter != from_iter->entries.end() ; eiter++) {
|
||||
if (entry_nref == eiter->nref) {
|
||||
// save the info and remove the entry
|
||||
info = *eiter;
|
||||
from_iter->entries.erase(eiter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eiter == from_iter->entries.end()) {
|
||||
// we don't know anything about this entry yet.. ignore it
|
||||
return;
|
||||
}
|
||||
|
||||
// if the name is the same, save the information about this
|
||||
// add_on into former_entries for later use
|
||||
if (strcmp(info.name, name) == 0) {
|
||||
former_entries.push_back(info);
|
||||
}
|
||||
|
||||
// Start at the top again, and search until the from directory.
|
||||
// If we find a add_on with the same name then the moved add_on
|
||||
// was not enabled. So we are done.
|
||||
std::list<add_on_directory_info>::iterator diter = directories.begin();
|
||||
for( ; diter != from_iter ; diter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = diter->entries.begin();
|
||||
for( ; eiter2 != diter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// finally disable the add_on
|
||||
AddOnDisabled(&info);
|
||||
|
||||
// Continue searching for a add_on below us. If we find a add_on
|
||||
// with the same name, we must enable it.
|
||||
for (from_iter++ ; from_iter != directories.end() ; from_iter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = from_iter->entries.begin();
|
||||
for( ; eiter2 != from_iter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
AddOnEnabled(&*eiter2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// finally, if the new name is different, destroy the addon
|
||||
if (strcmp(info.name, name) != 0) {
|
||||
AddOnRemoved(&info);
|
||||
}
|
||||
|
||||
// done
|
||||
return;
|
||||
}
|
||||
|
||||
if (from_iter == directories.end()) {
|
||||
// moved into our view
|
||||
std::list<add_on_entry_info>::iterator eiter = former_entries.begin();
|
||||
for( ; eiter != former_entries.end() ; eiter++) {
|
||||
if (entry_nref == eiter->nref) {
|
||||
// save the info and remove the entry
|
||||
info = *eiter;
|
||||
former_entries.erase(eiter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eiter != former_entries.end()) {
|
||||
if (strcmp(info.name, name) != 0) {
|
||||
// name changed on the way in, remove the old one
|
||||
AddOnRemoved(&info);
|
||||
}
|
||||
}
|
||||
|
||||
// update the info
|
||||
strncpy(info.name, name, sizeof(info.name));
|
||||
info.nref = entry_nref;
|
||||
info.dir_nref = to_nref;
|
||||
|
||||
if (eiter == former_entries.end()) {
|
||||
// this add_on was not seen before
|
||||
AddOnCreated(&info);
|
||||
}
|
||||
|
||||
// Start at the top again, and search until the to directory.
|
||||
// If we find a add_on with the same name then the moved add_on
|
||||
// is not to be enabled. So we are done.
|
||||
std::list<add_on_directory_info>::iterator diter = directories.begin();
|
||||
for( ; diter != to_iter ; diter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = diter->entries.begin();
|
||||
for( ; eiter2 != diter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The new add_on should be enabled, but first we check to see
|
||||
// if there is an add_on below us. If we find one, we disable it.
|
||||
bool shadowing = false;
|
||||
for (diter++ ; diter != directories.end() ; diter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = diter->entries.begin();
|
||||
for( ; eiter2 != diter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
AddOnDisabled(&*eiter2);
|
||||
shadowing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shadowing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// enable the new add_on
|
||||
AddOnEnabled(&info);
|
||||
|
||||
// put the new entry into the target directory
|
||||
to_iter->entries.push_back(info);
|
||||
|
||||
// done
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<add_on_entry_info>::iterator eiter = from_iter->entries.begin();
|
||||
for( ; eiter != from_iter->entries.end() ; eiter++) {
|
||||
if (entry_nref == eiter->nref) {
|
||||
// save the old info and remove the entry
|
||||
info = *eiter;
|
||||
from_iter->entries.erase(eiter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(info.name, name) == 0) {
|
||||
// same name moved in heirarchy
|
||||
debugger("add_on moved inside the heirarchy");
|
||||
} else {
|
||||
// check to see if it was formerly enabled
|
||||
bool was_enabled = true;
|
||||
std::list<add_on_directory_info>::iterator old_iter = directories.begin();
|
||||
for( ; old_iter != from_iter ; old_iter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = old_iter->entries.begin();
|
||||
for( ; eiter2 != old_iter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
was_enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!was_enabled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if it was enabled, disable it and enable the one under us, if it exists
|
||||
if (was_enabled) {
|
||||
AddOnDisabled(&info);
|
||||
bool done = false;
|
||||
for( ; old_iter != directories.end() ; old_iter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = old_iter->entries.begin();
|
||||
for( ; eiter2 != old_iter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
AddOnEnabled(&*eiter2);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// kaboom!
|
||||
AddOnRemoved(&info);
|
||||
|
||||
// set up new addon info
|
||||
strncpy(info.name, name, sizeof(info.name));
|
||||
info.dir_nref = to_nref;
|
||||
|
||||
// presto!
|
||||
AddOnCreated(&info);
|
||||
|
||||
// check to see if we are newly enabled
|
||||
bool is_enabled = true;
|
||||
std::list<add_on_directory_info>::iterator new_iter = directories.begin();
|
||||
for( ; new_iter != to_iter ; new_iter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = new_iter->entries.begin();
|
||||
for( ; eiter2 != new_iter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
is_enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_enabled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if it is newly enabled, check under us for an enabled one, and disable that first
|
||||
if (is_enabled) {
|
||||
bool done = false;
|
||||
for( ; new_iter != directories.end() ; new_iter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter2 = new_iter->entries.begin();
|
||||
for( ; eiter2 != new_iter->entries.end() ; eiter2++) {
|
||||
if (strcmp(eiter2->name, info.name) == 0) {
|
||||
AddOnDisabled(&*eiter2);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
AddOnEnabled(&info);
|
||||
}
|
||||
}
|
||||
|
||||
// put the new entry into the target directory
|
||||
to_iter->entries.push_back(info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* process pending entries
|
||||
*/
|
||||
|
||||
void
|
||||
AddOnMonitorHandler::HandlePulse()
|
||||
{
|
||||
BDirectory directory;
|
||||
std::list<add_on_entry_info>::iterator iter = pending_entries.begin();
|
||||
while (iter != pending_entries.end()) {
|
||||
add_on_entry_info info = *iter;
|
||||
|
||||
node_ref dir_nref;
|
||||
if ((directory.GetNodeRef(&dir_nref) != B_OK) ||
|
||||
(dir_nref != info.dir_nref)) {
|
||||
if (directory.SetTo(&info.dir_nref) != B_OK) {
|
||||
// invalid directory, discard this pending entry
|
||||
iter = pending_entries.erase(iter);
|
||||
continue;
|
||||
}
|
||||
dir_nref = info.dir_nref;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (directory.GetStatFor(info.name, &st) != B_OK) {
|
||||
// invalid file name, discard this pending entry
|
||||
iter = pending_entries.erase(iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
// stat units are seconds, real_time_clock units are seconds
|
||||
if (real_time_clock() - st.st_mtime < ADD_ON_STABLE_SECONDS) {
|
||||
// entry not stable, skip the entry for this pulse
|
||||
iter++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// we are going to deal with the stable entry, so remove it
|
||||
iter = pending_entries.erase(iter);
|
||||
|
||||
// put the new entry into the directory info
|
||||
std::list<add_on_directory_info>::iterator diter = directories.begin();
|
||||
for( ; diter != directories.end() ; diter++) {
|
||||
if (diter->nref == dir_nref) {
|
||||
diter->entries.push_back(info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// report it
|
||||
AddOnCreated(&info);
|
||||
|
||||
// Start at the top again, and search until the directory we put
|
||||
// the new add_on in. If we find a add_on with the same name then
|
||||
// the new add_on should not be enabled.
|
||||
bool enabled = true;
|
||||
std::list<add_on_directory_info>::iterator diter2 = directories.begin();
|
||||
for( ; diter2 != diter ; diter2++) {
|
||||
std::list<add_on_entry_info>::iterator eiter = diter2->entries.begin();
|
||||
for( ; eiter != diter2->entries.end() ; eiter++) {
|
||||
if (strcmp(eiter->name, info.name) == 0) {
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!enabled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!enabled) {
|
||||
// if we are not enabled, go on to the next pending entry
|
||||
continue;
|
||||
}
|
||||
|
||||
// The new add_on should be enabled, but first we check to see
|
||||
// if there is an add_on below us. If we find one, we disable it.
|
||||
bool shadowing = false;
|
||||
for (diter++ ; diter != directories.end() ; diter++) {
|
||||
std::list<add_on_entry_info>::iterator eiter = diter->entries.begin();
|
||||
for( ; eiter != diter->entries.end() ; eiter++) {
|
||||
if (strcmp(eiter->name, info.name) == 0) {
|
||||
AddOnDisabled(&*eiter);
|
||||
shadowing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shadowing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// finally, enable the new entry
|
||||
AddOnEnabled(&info);
|
||||
}
|
||||
}
|
|
@ -1,385 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <DiskDevice.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <new.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
#include <DiskDevice.h>
|
||||
#include <DiskDeviceVisitor.h>
|
||||
#include <Drivers.h>
|
||||
#include <Message.h>
|
||||
#include <Path.h>
|
||||
|
||||
|
||||
/*! \class BDiskDevice
|
||||
\brief A BDiskDevice object represents a storage device.
|
||||
*/
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates an uninitialized BDiskDevice object.
|
||||
*/
|
||||
BDiskDevice::BDiskDevice()
|
||||
: fDeviceData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with this object.
|
||||
*/
|
||||
BDiskDevice::~BDiskDevice()
|
||||
{
|
||||
}
|
||||
|
||||
// HasMedia
|
||||
/*! \brief Returns whether the device contains a media.
|
||||
\return \c true, if the device contains a media, \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDevice::HasMedia() const
|
||||
{
|
||||
return (fDeviceData
|
||||
&& fDeviceData->device_flags & B_DISK_DEVICE_HAS_MEDIA);
|
||||
}
|
||||
|
||||
// IsRemovableMedia
|
||||
/*! \brief Returns whether the device media are removable.
|
||||
\return \c true, if the device media are removable, \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDevice::IsRemovableMedia() const
|
||||
{
|
||||
return (fDeviceData
|
||||
&& fDeviceData->device_flags & B_DISK_DEVICE_REMOVABLE);
|
||||
}
|
||||
|
||||
// IsReadOnlyMedia
|
||||
bool
|
||||
BDiskDevice::IsReadOnlyMedia() const
|
||||
{
|
||||
return (fDeviceData
|
||||
&& fDeviceData->device_flags & B_DISK_DEVICE_READ_ONLY);
|
||||
}
|
||||
|
||||
// IsWriteOnceMedia
|
||||
bool
|
||||
BDiskDevice::IsWriteOnceMedia() const
|
||||
{
|
||||
return (fDeviceData
|
||||
&& fDeviceData->device_flags & B_DISK_DEVICE_WRITE_ONCE);
|
||||
}
|
||||
|
||||
// Eject
|
||||
/*! \brief Eject the device's media.
|
||||
|
||||
The device media must, of course, be removable, and the device must
|
||||
support ejecting the media.
|
||||
|
||||
\param update If \c true, Update() is invoked after successful ejection.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_INIT: The device is not properly initialized.
|
||||
- \c B_BAD_VALUE: The device media is not removable.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDevice::Eject(bool update)
|
||||
{
|
||||
/* // get path
|
||||
const char *path = Path();
|
||||
status_t error = (path ? B_OK : B_NO_INIT);
|
||||
// check whether the device media is removable
|
||||
if (error == B_OK && !IsRemovable())
|
||||
error = B_BAD_VALUE;
|
||||
// open, eject and close the device
|
||||
if (error == B_OK) {
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd < 0 || ioctl(fd, B_EJECT_DEVICE) != 0)
|
||||
error = errno;
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
}
|
||||
if (error == B_OK && update)
|
||||
error = Update();
|
||||
return error;
|
||||
*/
|
||||
// not implemented
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// SetTo
|
||||
status_t
|
||||
BDiskDevice::SetTo(partition_id id)
|
||||
{
|
||||
return _SetTo(id, true, false, 0);
|
||||
}
|
||||
|
||||
// Update
|
||||
/*! \brief Updates the object to reflect the latest changes to the device.
|
||||
|
||||
Note, that subobjects (BSessions, BPartitions) may be deleted during this
|
||||
operation. It is also possible, that the device doesn't exist anymore --
|
||||
e.g. if it is hot-pluggable. Then an error is returned and the object is
|
||||
uninitialized.
|
||||
|
||||
\param updated Pointer to a bool variable which shall be set to \c true,
|
||||
if the object needed to be updated and to \c false otherwise.
|
||||
May be \c NULL. Is not touched, if the method fails.
|
||||
\return \c B_OK, if the update went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDevice::Update(bool *updated)
|
||||
{
|
||||
return _Update(_IsShadow(), updated);
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
BDiskDevice::Unset()
|
||||
{
|
||||
BPartition::_Unset();
|
||||
free(fDeviceData);
|
||||
fDeviceData = NULL;
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
BDiskDevice::InitCheck() const
|
||||
{
|
||||
return (fDeviceData ? B_OK : B_NO_INIT);
|
||||
}
|
||||
|
||||
// GetPath
|
||||
status_t
|
||||
BDiskDevice::GetPath(BPath *path) const
|
||||
{
|
||||
if (!path || !fDeviceData)
|
||||
return B_BAD_VALUE;
|
||||
return path->SetTo(fDeviceData->path);
|
||||
}
|
||||
|
||||
// IsModified
|
||||
bool
|
||||
BDiskDevice::IsModified() const
|
||||
{
|
||||
return (InitCheck() == B_OK && _IsShadow()
|
||||
&& _kern_is_disk_device_modified(ID()));
|
||||
}
|
||||
|
||||
// PrepareModifications
|
||||
status_t
|
||||
BDiskDevice::PrepareModifications()
|
||||
{
|
||||
// check initialization
|
||||
status_t error = InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (_IsShadow())
|
||||
return B_ERROR;
|
||||
// ask kernel to prepare for modifications
|
||||
error = _kern_prepare_disk_device_modifications(ID());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// update
|
||||
error = _Update(true, NULL);
|
||||
if (error != B_OK) {
|
||||
// bad -- cancelling the modifications is all we can do
|
||||
_kern_cancel_disk_device_modifications(ID());
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// CommitModifications
|
||||
status_t
|
||||
BDiskDevice::CommitModifications(bool synchronously,
|
||||
BMessenger progressMessenger,
|
||||
bool receiveCompleteProgressUpdates)
|
||||
{
|
||||
status_t error = InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (!_IsShadow())
|
||||
return B_BAD_VALUE;
|
||||
// TODO: Get port and token from the progressMessenger
|
||||
port_id port = -1;
|
||||
int32 token = -1;
|
||||
error = _kern_commit_disk_device_modifications(ID(), port, token,
|
||||
receiveCompleteProgressUpdates);
|
||||
if (error == B_OK)
|
||||
error = _SetTo(ID(), true, false, 0);
|
||||
return error;
|
||||
}
|
||||
|
||||
// CancelModifications
|
||||
status_t
|
||||
BDiskDevice::CancelModifications()
|
||||
{
|
||||
status_t error = InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (!_IsShadow())
|
||||
return B_BAD_VALUE;
|
||||
error = _kern_cancel_disk_device_modifications(ID());
|
||||
if (error == B_OK)
|
||||
error = _SetTo(ID(), true, false, 0);
|
||||
return error;
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
/*! \brief Privatized copy constructor to avoid usage.
|
||||
*/
|
||||
BDiskDevice::BDiskDevice(const BDiskDevice &)
|
||||
{
|
||||
}
|
||||
|
||||
// =
|
||||
/*! \brief Privatized assignment operator to avoid usage.
|
||||
*/
|
||||
BDiskDevice &
|
||||
BDiskDevice::operator=(const BDiskDevice &)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// _GetData
|
||||
status_t
|
||||
BDiskDevice::_GetData(partition_id id, bool deviceOnly, bool shadow,
|
||||
size_t neededSize, user_disk_device_data **data)
|
||||
{
|
||||
// get the device data
|
||||
void *buffer = NULL;
|
||||
size_t bufferSize = 0;
|
||||
if (neededSize > 0) {
|
||||
// allocate initial buffer
|
||||
buffer = malloc(neededSize);
|
||||
if (!buffer)
|
||||
return B_NO_MEMORY;
|
||||
bufferSize = neededSize;
|
||||
}
|
||||
status_t error = B_OK;
|
||||
do {
|
||||
error = _kern_get_disk_device_data(id, deviceOnly, shadow,
|
||||
(user_disk_device_data*)buffer,
|
||||
bufferSize, &neededSize);
|
||||
if (error == B_BUFFER_OVERFLOW) {
|
||||
// buffer to small re-allocate it
|
||||
if (buffer)
|
||||
free(buffer);
|
||||
buffer = malloc(neededSize);
|
||||
if (buffer)
|
||||
bufferSize = neededSize;
|
||||
else
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
} while (error == B_BUFFER_OVERFLOW);
|
||||
// set result / cleanup on error
|
||||
if (error == B_OK)
|
||||
*data = (user_disk_device_data*)buffer;
|
||||
else if (buffer)
|
||||
free(buffer);
|
||||
return error;
|
||||
}
|
||||
|
||||
// _SetTo
|
||||
status_t
|
||||
BDiskDevice::_SetTo(partition_id id, bool deviceOnly, bool shadow,
|
||||
size_t neededSize)
|
||||
{
|
||||
Unset();
|
||||
// get the device data
|
||||
user_disk_device_data *data = NULL;
|
||||
status_t error = _GetData(id, deviceOnly, shadow, neededSize, &data);
|
||||
// set the data
|
||||
if (error == B_OK)
|
||||
error = _SetTo(data);
|
||||
// cleanup on error
|
||||
if (error != B_OK && data)
|
||||
free(data);
|
||||
return error;
|
||||
}
|
||||
|
||||
// _SetTo
|
||||
status_t
|
||||
BDiskDevice::_SetTo(user_disk_device_data *data)
|
||||
{
|
||||
Unset();
|
||||
if (!data)
|
||||
return B_BAD_VALUE;
|
||||
fDeviceData = data;
|
||||
status_t error = BPartition::_SetTo(this, NULL,
|
||||
&fDeviceData->device_partition_data);
|
||||
if (error != B_OK) {
|
||||
// If _SetTo() fails, the caller retains ownership of the supplied
|
||||
// data. So, unset fDeviceData before calling Unset().
|
||||
fDeviceData = NULL;
|
||||
Unset();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _Update
|
||||
status_t
|
||||
BDiskDevice::_Update(bool shadow, bool *updated)
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return InitCheck();
|
||||
// get the device data
|
||||
user_disk_device_data *data = NULL;
|
||||
status_t error = _GetData(ID(), true, shadow, 0, &data);
|
||||
// set the data
|
||||
if (error == B_OK)
|
||||
error = _Update(data, updated);
|
||||
// cleanup on error
|
||||
if (error != B_OK && data)
|
||||
free(data);
|
||||
return error;
|
||||
}
|
||||
|
||||
// _Update
|
||||
status_t
|
||||
BDiskDevice::_Update(user_disk_device_data *data, bool *updated)
|
||||
{
|
||||
if (!data || !fDeviceData || ID() != data->device_partition_data.id)
|
||||
return B_BAD_VALUE;
|
||||
bool _updated;
|
||||
if (!updated)
|
||||
updated = &_updated;
|
||||
*updated = false;
|
||||
// remove obsolete partitions
|
||||
status_t error = _RemoveObsoleteDescendants(&data->device_partition_data,
|
||||
updated);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// update existing partitions and add new ones
|
||||
error = BPartition::_Update(&data->device_partition_data, updated);
|
||||
if (error == B_OK) {
|
||||
user_disk_device_data *oldData = fDeviceData;
|
||||
fDeviceData = data;
|
||||
// check for changes
|
||||
if (data->device_flags != oldData->device_flags
|
||||
|| strcmp(data->path, oldData->path)) {
|
||||
*updated = true;
|
||||
}
|
||||
free(oldData);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _AcceptVisitor
|
||||
bool
|
||||
BDiskDevice::_AcceptVisitor(BDiskDeviceVisitor *visitor, int32 level)
|
||||
{
|
||||
return visitor->Visit(this);
|
||||
}
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
#include <DiskDeviceJob.h>
|
||||
|
||||
// constructor
|
||||
BDiskDeviceJob::BDiskDeviceJob()
|
||||
: fID(B_NO_INIT),
|
||||
fType(B_DISK_DEVICE_JOB_BAD_TYPE),
|
||||
fPartitionID(-1),
|
||||
fDescription()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
BDiskDeviceJob::~BDiskDeviceJob()
|
||||
{
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
BDiskDeviceJob::InitCheck() const
|
||||
{
|
||||
return (fID >= 0 ? B_OK : fID);
|
||||
}
|
||||
|
||||
// SetTo
|
||||
status_t
|
||||
BDiskDeviceJob::SetTo(disk_job_id id)
|
||||
{
|
||||
Unset();
|
||||
user_disk_device_job_info info;
|
||||
status_t error = _kern_get_disk_device_job_info(id, &info);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
return _SetTo(&info);
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
BDiskDeviceJob::Unset()
|
||||
{
|
||||
fID = B_NO_INIT;
|
||||
fType = B_DISK_DEVICE_JOB_BAD_TYPE;
|
||||
fPartitionID = -1;
|
||||
fDescription.SetTo(NULL);
|
||||
}
|
||||
|
||||
// ID
|
||||
disk_job_id
|
||||
BDiskDeviceJob::ID() const
|
||||
{
|
||||
return fID;
|
||||
}
|
||||
|
||||
// Type
|
||||
uint32
|
||||
BDiskDeviceJob::Type() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
// PartitionID
|
||||
partition_id
|
||||
BDiskDeviceJob::PartitionID() const
|
||||
{
|
||||
return fPartitionID;
|
||||
}
|
||||
|
||||
// Description
|
||||
const char *
|
||||
BDiskDeviceJob::Description() const
|
||||
{
|
||||
return fDescription.String();
|
||||
}
|
||||
|
||||
// Status
|
||||
uint32
|
||||
BDiskDeviceJob::Status() const
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return B_DISK_DEVICE_JOB_UNINITIALIZED;
|
||||
disk_device_job_progress_info info;
|
||||
status_t error = _kern_get_disk_device_job_progress_info(fID, &info);
|
||||
if (error != B_OK)
|
||||
return B_DISK_DEVICE_JOB_UNINITIALIZED;
|
||||
return info.status;
|
||||
}
|
||||
|
||||
// Progress
|
||||
float
|
||||
BDiskDeviceJob::Progress() const
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return 0;
|
||||
disk_device_job_progress_info info;
|
||||
status_t error = _kern_get_disk_device_job_progress_info(fID, &info);
|
||||
if (error != B_OK)
|
||||
return 0;
|
||||
if (info.task_count < 1 || info.task_count <= info.completed_tasks)
|
||||
return 1;
|
||||
if (info.current_task_progress < 0)
|
||||
info.current_task_progress = 0;
|
||||
if (info.current_task_progress > 1)
|
||||
info.current_task_progress = 1;
|
||||
return (info.completed_tasks + info.current_task_progress)
|
||||
/ info.task_count;
|
||||
}
|
||||
|
||||
// GetProgressInfo
|
||||
status_t
|
||||
BDiskDeviceJob::GetProgressInfo(disk_device_job_progress_info *info) const
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return InitCheck();
|
||||
return _kern_get_disk_device_job_progress_info(fID, info);
|
||||
}
|
||||
|
||||
// InterruptProperties
|
||||
uint32
|
||||
BDiskDeviceJob::InterruptProperties() const
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return 0;
|
||||
disk_device_job_progress_info info;
|
||||
status_t error = _kern_get_disk_device_job_progress_info(fID, &info);
|
||||
if (error != B_OK)
|
||||
return 0;
|
||||
return info.interrupt_properties;
|
||||
}
|
||||
|
||||
// Cancel
|
||||
status_t
|
||||
BDiskDeviceJob::Cancel(bool reverse)
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return InitCheck();
|
||||
return _kern_cancel_disk_device_job(fID, reverse);
|
||||
}
|
||||
|
||||
// Pause
|
||||
status_t
|
||||
BDiskDeviceJob::Pause()
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return InitCheck();
|
||||
return _kern_pause_disk_device_job(fID);
|
||||
}
|
||||
|
||||
// _SetTo
|
||||
status_t
|
||||
BDiskDeviceJob::_SetTo(user_disk_device_job_info *info)
|
||||
{
|
||||
Unset();
|
||||
if (!info)
|
||||
return B_BAD_VALUE;
|
||||
fID = info->id;
|
||||
fType = info->type;
|
||||
fPartitionID = info->partition;
|
||||
fDescription.SetTo(info->description);
|
||||
return B_OK;
|
||||
}
|
||||
|
|
@ -1,832 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <new.h>
|
||||
|
||||
#include <DiskDevice.h>
|
||||
#include <DiskDeviceList.h>
|
||||
#include <DiskDevicePrivate.h>
|
||||
#include <DiskDeviceRoster.h>
|
||||
#include <Locker.h>
|
||||
#include <Looper.h>
|
||||
#include <ObjectLocker.h>
|
||||
#include <Partition.h>
|
||||
#include <Session.h>
|
||||
|
||||
using BPrivate::BObjectLocker;
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates an empty BDiskDeviceList object.
|
||||
*/
|
||||
BDiskDeviceList::BDiskDeviceList(bool useOwnLocker)
|
||||
: fLocker(NULL),
|
||||
fDevices(20, true),
|
||||
fSubscribed(false)
|
||||
{
|
||||
if (useOwnLocker)
|
||||
fLocker = new(nothrow) BLocker;
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with the object.
|
||||
*/
|
||||
BDiskDeviceList::~BDiskDeviceList()
|
||||
{
|
||||
if (fLocker)
|
||||
delete fLocker;
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
/*! \brief Implemented to handle notification messages.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::MessageReceived(BMessage *message)
|
||||
{
|
||||
BObjectLocker<BDiskDeviceList> _(this);
|
||||
switch (message->what) {
|
||||
case B_DEVICE_UPDATE:
|
||||
{
|
||||
uint32 event;
|
||||
if (message->FindInt32("event", (int32*)&event) == B_OK) {
|
||||
switch (event) {
|
||||
case B_DEVICE_MOUNT_POINT_MOVED:
|
||||
_MountPointMoved(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_MOUNTED:
|
||||
_PartitionMounted(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_UNMOUNTED:
|
||||
_PartitionUnmounted(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_INITIALIZED:
|
||||
_PartitionInitialized(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_RESIZED:
|
||||
_PartitionResized(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_MOVED:
|
||||
_PartitionMoved(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_CREATED:
|
||||
_PartitionCreated(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_DELETED:
|
||||
_PartitionDeleted(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_DEFRAGMENTED:
|
||||
_PartitionDefragmented(message);
|
||||
break;
|
||||
case B_DEVICE_PARTITION_REPAIRED:
|
||||
_PartitionRepaired(message);
|
||||
break;
|
||||
case B_DEVICE_MEDIA_CHANGED:
|
||||
_MediaChanged(message);
|
||||
break;
|
||||
case B_DEVICE_ADDED:
|
||||
_DeviceAdded(message);
|
||||
break;
|
||||
case B_DEVICE_REMOVED:
|
||||
_DeviceRemoved(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
BHandler::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
// SetNextHandler
|
||||
/*! \brief Implemented to unsubscribe from notification services when going
|
||||
to be detached from looper.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::SetNextHandler(BHandler *handler)
|
||||
{
|
||||
if (!handler) {
|
||||
BObjectLocker<BDiskDeviceList> _(this);
|
||||
if (fSubscribed)
|
||||
_StopWatching();
|
||||
}
|
||||
BHandler::SetNextHandler(handler);
|
||||
}
|
||||
|
||||
// Fetch
|
||||
/*! \brief Empties the list and refills it according to the current state.
|
||||
|
||||
Furthermore, if added to a looper, the list subscribes to notification
|
||||
services needed to keep the list up-to-date.
|
||||
|
||||
If an error occurs, the list Unset()s itself.
|
||||
|
||||
The object doesn't need to be locked, when this method is invoked. The
|
||||
method does itself try to lock the list, but doesn't fail, if that
|
||||
doesn't succeed. That way an object can be used without locking in a
|
||||
single threaded environment.
|
||||
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceList::Fetch()
|
||||
{
|
||||
Unset();
|
||||
BObjectLocker<BDiskDeviceList> _(this);
|
||||
// register for notifications
|
||||
status_t error = B_OK;
|
||||
if (Looper())
|
||||
error = _StartWatching();
|
||||
// get the devices
|
||||
BDiskDeviceRoster roster;
|
||||
while (error == B_OK) {
|
||||
if (BDiskDevice *device = new(nothrow) BDiskDevice) {
|
||||
status_t status = roster.GetNextDevice(device);
|
||||
if (status == B_OK)
|
||||
fDevices.AddItem(device);
|
||||
else if (status == B_ENTRY_NOT_FOUND)
|
||||
break;
|
||||
else
|
||||
error = status;
|
||||
} else
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
// cleanup on error
|
||||
if (error != B_OK)
|
||||
Unset();
|
||||
return error;
|
||||
}
|
||||
|
||||
// Unset
|
||||
/*! \brief Empties the list and unsubscribes from all notification services.
|
||||
|
||||
The object doesn't need to be locked, when this method is invoked. The
|
||||
method does itself try to lock the list, but doesn't fail, if that
|
||||
doesn't succeed. That way an object can be used without locking in a
|
||||
single threaded environment.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::Unset()
|
||||
{
|
||||
BObjectLocker<BDiskDeviceList> _(this);
|
||||
// unsubscribe from notification services
|
||||
_StopWatching();
|
||||
// empty the list
|
||||
fDevices.MakeEmpty();
|
||||
}
|
||||
|
||||
// Lock
|
||||
/*! \brief Locks the list.
|
||||
|
||||
If on construction it had been specified, that the list shall use an
|
||||
own BLocker, then this locker is locked, otherwise LockLooper() is
|
||||
invoked.
|
||||
|
||||
\return \c true, if the list could be locked successfully, \c false
|
||||
otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDeviceList::Lock()
|
||||
{
|
||||
if (fLocker)
|
||||
return fLocker->Lock();
|
||||
return LockLooper();
|
||||
}
|
||||
|
||||
// Unlock
|
||||
/*! \brief Unlocks the list.
|
||||
|
||||
If on construction it had been specified, that the list shall use an
|
||||
own BLocker, then this locker is unlocked, otherwise UnlockLooper() is
|
||||
invoked.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::Unlock()
|
||||
{
|
||||
if (fLocker)
|
||||
return fLocker->Unlock();
|
||||
return UnlockLooper();
|
||||
}
|
||||
|
||||
// CountDevices
|
||||
/*! \brief Returns the number of devices in the list.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\return The number of devices in the list.
|
||||
*/
|
||||
int32
|
||||
BDiskDeviceList::CountDevices() const
|
||||
{
|
||||
return fDevices.CountItems();
|
||||
}
|
||||
|
||||
// DeviceAt
|
||||
/*! \brief Retrieves a device by index.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\param index The list index of the device to be returned.
|
||||
\return The device with index \a index, or \c NULL, if the list is not
|
||||
locked or \a index is out of range.
|
||||
*/
|
||||
BDiskDevice *
|
||||
BDiskDeviceList::DeviceAt(int32 index) const
|
||||
{
|
||||
return fDevices.ItemAt(index);
|
||||
}
|
||||
|
||||
// VisitEachDevice
|
||||
/*! \brief Iterates through the all devices in the list.
|
||||
|
||||
The supplied visitor's Visit(BDiskDevice*) is invoked for each device.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns the respective device.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\param visitor The visitor.
|
||||
\return The respective device, if the iteration was terminated early,
|
||||
\c NULL otherwise.
|
||||
*/
|
||||
BDiskDevice *
|
||||
BDiskDeviceList::VisitEachDevice(BDiskDeviceVisitor *visitor)
|
||||
{
|
||||
if (visitor) {
|
||||
for (int32 i = 0; BDiskDevice *device = DeviceAt(i); i++) {
|
||||
if (visitor->Visit(device))
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// VisitEachPartition
|
||||
/*! \brief Iterates through the all devices' partitions.
|
||||
|
||||
The supplied visitor's Visit(BPartition*) is invoked for each partition.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns the respective partition.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\param visitor The visitor.
|
||||
\return The respective partition, if the iteration was terminated early,
|
||||
\c NULL otherwise.
|
||||
*/
|
||||
BPartition *
|
||||
BDiskDeviceList::VisitEachPartition(BDiskDeviceVisitor *visitor)
|
||||
{
|
||||
if (visitor) {
|
||||
for (int32 i = 0; BDiskDevice *device = DeviceAt(i); i++) {
|
||||
if (BPartition *partition = device->VisitEachDescendant(visitor))
|
||||
return partition;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// VisitEachMountedPartition
|
||||
/*! \brief Iterates through the all devices' partitions that are mounted.
|
||||
|
||||
The supplied visitor's Visit(BPartition*) is invoked for each mounted
|
||||
partition.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns the respective partition.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\param visitor The visitor.
|
||||
\return The respective partition, if the iteration was terminated early,
|
||||
\c NULL otherwise.
|
||||
*/
|
||||
BPartition *
|
||||
BDiskDeviceList::VisitEachMountedPartition(BDiskDeviceVisitor *visitor)
|
||||
{
|
||||
BPartition *partition = NULL;
|
||||
if (visitor) {
|
||||
struct MountedPartitionFilter : public PartitionFilter {
|
||||
virtual bool Filter(BPartition *partition, int32 level)
|
||||
{ return partition->IsMounted(); }
|
||||
} filter;
|
||||
PartitionFilterVisitor filterVisitor(visitor, &filter);
|
||||
partition = VisitEachPartition(&filterVisitor);
|
||||
}
|
||||
return partition;
|
||||
}
|
||||
|
||||
// VisitEachMountablePartition
|
||||
/*! \brief Iterates through the all devices' partitions that are mountable.
|
||||
|
||||
The supplied visitor's Visit(BPartition*) is invoked for each mountable
|
||||
partition.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns the respective partition.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\param visitor The visitor.
|
||||
\return The respective partition, if the iteration was terminated early,
|
||||
\c NULL otherwise.
|
||||
*/
|
||||
BPartition *
|
||||
BDiskDeviceList::VisitEachMountablePartition(BDiskDeviceVisitor *visitor)
|
||||
{
|
||||
BPartition *partition = NULL;
|
||||
if (visitor) {
|
||||
struct MountablePartitionFilter : public PartitionFilter {
|
||||
virtual bool Filter(BPartition *partition, int32 level)
|
||||
{ return partition->ContainsFileSystem(); }
|
||||
} filter;
|
||||
PartitionFilterVisitor filterVisitor(visitor, &filter);
|
||||
partition = VisitEachPartition(&filterVisitor);
|
||||
}
|
||||
return partition;
|
||||
}
|
||||
|
||||
// DeviceWithID
|
||||
/*! \brief Retrieves a device by ID.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\param id The ID of the device to be returned.
|
||||
\return The device with ID \a id, or \c NULL, if the list is not
|
||||
locked or no device with ID \a id is in the list.
|
||||
*/
|
||||
BDiskDevice *
|
||||
BDiskDeviceList::DeviceWithID(int32 id) const
|
||||
{
|
||||
IDFinderVisitor visitor(id);
|
||||
return const_cast<BDiskDeviceList*>(this)->VisitEachDevice(&visitor);
|
||||
}
|
||||
|
||||
// PartitionWithID
|
||||
/*! \brief Retrieves a partition by ID.
|
||||
|
||||
The list must be locked.
|
||||
|
||||
\param id The ID of the partition to be returned.
|
||||
\return The partition with ID \a id, or \c NULL, if the list is not
|
||||
locked or no partition with ID \a id is in the list.
|
||||
*/
|
||||
BPartition *
|
||||
BDiskDeviceList::PartitionWithID(int32 id) const
|
||||
{
|
||||
IDFinderVisitor visitor(id);
|
||||
return const_cast<BDiskDeviceList*>(this)->VisitEachPartition(&visitor);
|
||||
}
|
||||
|
||||
// MountPointMoved
|
||||
/*! \brief Invoked, when the mount point of a partition has been moved.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::MountPointMoved(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_MOUNT_POINT_MOVED);
|
||||
}
|
||||
|
||||
// PartitionMounted
|
||||
/*! \brief Invoked, when a partition has been mounted.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionMounted(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_PARTITION_MOUNTED);
|
||||
}
|
||||
|
||||
// PartitionUnmounted
|
||||
/*! \brief Invoked, when a partition has been unmounted.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionUnmounted(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_PARTITION_UNMOUNTED);
|
||||
}
|
||||
|
||||
// PartitionInitialized
|
||||
/*! \brief Invoked, when a partition has been initialized.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionInitialized(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_PARTITION_INITIALIZED);
|
||||
}
|
||||
|
||||
// PartitionResized
|
||||
/*! \brief Invoked, when a partition has been resized.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionResized(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_PARTITION_RESIZED);
|
||||
}
|
||||
|
||||
// PartitionMoved
|
||||
/*! \brief Invoked, when a partition has been moved.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionMoved(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_PARTITION_MOVED);
|
||||
}
|
||||
|
||||
// PartitionCreated
|
||||
/*! \brief Invoked, when a partition has been created.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionCreated(BPartition *partition)
|
||||
{
|
||||
}
|
||||
|
||||
// PartitionDeleted
|
||||
/*! \brief Invoked, when a partition has been deleted.
|
||||
|
||||
The method is called twice for a deleted partition. The first time
|
||||
before the BDiskDevice the partition belongs to has been updated. The
|
||||
\a partition parameter will point to a still valid BPartition object.
|
||||
On the second invocation the device object will have been updated and
|
||||
the partition object will have been deleted -- \a partition will be
|
||||
\c NULL then.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition. Only non- \c NULL on the first
|
||||
invocation.
|
||||
\param partitionID The ID of the concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionDeleted(BPartition *partition,
|
||||
partition_id partitionID)
|
||||
{
|
||||
}
|
||||
|
||||
// PartitionDefragmented
|
||||
/*! \brief Invoked, when a partition has been defragmented.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionDefragmented(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_PARTITION_DEFRAGMENTED);
|
||||
}
|
||||
|
||||
// PartitionRepaired
|
||||
/*! \brief Invoked, when a partition has been repaired.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param partition The concerned partition.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionRepaired(BPartition *partition)
|
||||
{
|
||||
PartitionChanged(partition, B_DEVICE_PARTITION_REPAIRED);
|
||||
}
|
||||
|
||||
// PartitionChanged
|
||||
/*! \brief Catch-all method invoked by the \c Partition*() hooks, save by
|
||||
PartitionCreated() and PartitionDeleted().
|
||||
|
||||
If you're interested only in the fact, that something about the partition
|
||||
changed, you can just override this hook instead of the ones telling you
|
||||
exactly what happened.
|
||||
|
||||
\param partition The concerned partition.
|
||||
\param event The event that occurred, if you are interested in it after all.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::PartitionChanged(BPartition *partition, uint32 event)
|
||||
{
|
||||
}
|
||||
|
||||
// MediaChanged
|
||||
/*! \brief Invoked, when the media of a device has been changed.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param device The concerned device.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::MediaChanged(BDiskDevice *device)
|
||||
{
|
||||
}
|
||||
|
||||
// DeviceAdded
|
||||
/*! \brief Invoked, when a device has been added.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param device The concerned device.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::DeviceAdded(BDiskDevice *device)
|
||||
{
|
||||
}
|
||||
|
||||
// DeviceRemoved
|
||||
/*! \brief Invoked, when a device has been removed.
|
||||
|
||||
The supplied object is already removed from the list and is going to be
|
||||
deleted after the hook returns.
|
||||
|
||||
The list is locked, when this method is invoked.
|
||||
|
||||
\param device The concerned device.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::DeviceRemoved(BDiskDevice *device)
|
||||
{
|
||||
}
|
||||
|
||||
// _StartWatching
|
||||
/*! \brief Starts watching for disk device notifications.
|
||||
|
||||
The object must be locked (if possible at all), when this method is
|
||||
invoked.
|
||||
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceList::_StartWatching()
|
||||
{
|
||||
if (!Looper() || fSubscribed)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = BDiskDeviceRoster().StartWatching(BMessenger(this));
|
||||
fSubscribed = (error == B_OK);
|
||||
return error;
|
||||
}
|
||||
|
||||
// _StopWatching
|
||||
/*! \brief Stop watching for disk device notifications.
|
||||
|
||||
The object must be locked (if possible at all), when this method is
|
||||
invoked.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_StopWatching()
|
||||
{
|
||||
if (fSubscribed) {
|
||||
BDiskDeviceRoster().StopWatching(BMessenger(this));
|
||||
fSubscribed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// _MountPointMoved
|
||||
/*! \brief Handles a "mount point moved" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_MountPointMoved(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
MountPointMoved(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionMounted
|
||||
/*! \brief Handles a "partition mounted" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionMounted(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionMounted(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionUnmounted
|
||||
/*! \brief Handles a "partition unmounted" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionUnmounted(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionUnmounted(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionInitialized
|
||||
/*! \brief Handles a "partition initialized" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionInitialized(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionInitialized(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionResized
|
||||
/*! \brief Handles a "partition resized" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionResized(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionResized(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionMoved
|
||||
/*! \brief Handles a "partition moved" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionMoved(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionMoved(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionCreated
|
||||
/*! \brief Handles a "partition created" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionCreated(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionCreated(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionDeleted
|
||||
/*! \brief Handles a "partition deleted" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionDeleted(BMessage *message)
|
||||
{
|
||||
if (BPartition *partition = _FindPartition(message)) {
|
||||
partition_id id = partition->ID();
|
||||
PartitionDeleted(partition, id);
|
||||
if (_UpdateDevice(message))
|
||||
PartitionDeleted(NULL, id);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionDefragmented
|
||||
/*! \brief Handles a "partition defragmented" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionDefragmented(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionDefragmented(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _PartitionRepaired
|
||||
/*! \brief Handles a "partition repaired" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_PartitionRepaired(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message)) {
|
||||
if (BPartition *partition = _FindPartition(message))
|
||||
PartitionRepaired(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// _MediaChanged
|
||||
/*! \brief Handles a "media changed" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_MediaChanged(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _UpdateDevice(message))
|
||||
MediaChanged(device);
|
||||
}
|
||||
|
||||
// _DeviceAdded
|
||||
/*! \brief Handles a "device added" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_DeviceAdded(BMessage *message)
|
||||
{
|
||||
int32 id;
|
||||
if (message->FindInt32("device_id", &id) == B_OK && !DeviceWithID(id)) {
|
||||
BDiskDevice *device = new(nothrow) BDiskDevice;
|
||||
if (BDiskDeviceRoster().GetDeviceWithID(id, device) == B_OK) {
|
||||
fDevices.AddItem(device);
|
||||
DeviceAdded(device);
|
||||
} else
|
||||
delete device;
|
||||
}
|
||||
}
|
||||
|
||||
// _DeviceRemoved
|
||||
/*! \brief Handles a "device removed" message.
|
||||
\param message The respective notification message.
|
||||
*/
|
||||
void
|
||||
BDiskDeviceList::_DeviceRemoved(BMessage *message)
|
||||
{
|
||||
if (BDiskDevice *device = _FindDevice(message)) {
|
||||
fDevices.RemoveItem(device, false);
|
||||
DeviceRemoved(device);
|
||||
delete device;
|
||||
}
|
||||
}
|
||||
|
||||
// _FindDevice
|
||||
/*! \brief Returns the device for the ID contained in a motification message.
|
||||
\param message The notification message.
|
||||
\return The device with the ID, or \c NULL, if the ID or the device could
|
||||
not be found.
|
||||
*/
|
||||
BDiskDevice *
|
||||
BDiskDeviceList::_FindDevice(BMessage *message)
|
||||
{
|
||||
BDiskDevice *device = NULL;
|
||||
int32 id;
|
||||
if (message->FindInt32("device_id", &id) == B_OK)
|
||||
device = DeviceWithID(id);
|
||||
return device;
|
||||
}
|
||||
|
||||
// _FindPartition
|
||||
/*! \brief Returns the partition for the ID contained in a motification
|
||||
message.
|
||||
\param message The notification message.
|
||||
\return The partition with the ID, or \c NULL, if the ID or the partition
|
||||
could not be found.*/
|
||||
BPartition *
|
||||
BDiskDeviceList::_FindPartition(BMessage *message)
|
||||
{
|
||||
BPartition *partition = NULL;
|
||||
int32 id;
|
||||
if (message->FindInt32("partition_id", &id) == B_OK)
|
||||
partition = PartitionWithID(id);
|
||||
return partition;
|
||||
}
|
||||
|
||||
// _UpdateDevice
|
||||
/*! \brief Finds the device for the ID contained in a motification message
|
||||
and updates it.
|
||||
\param message The notification message.
|
||||
\return The device with the ID, or \c NULL, if the ID or the device could
|
||||
not be found.
|
||||
*/
|
||||
BDiskDevice *
|
||||
BDiskDeviceList::_UpdateDevice(BMessage *message)
|
||||
{
|
||||
BDiskDevice *device = _FindDevice(message);
|
||||
if (device) {
|
||||
if (device->Update() != B_OK) {
|
||||
fDevices.RemoveItem(device);
|
||||
device = NULL;
|
||||
}
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <DiskDevicePrivate.h>
|
||||
#include <DiskDevice.h>
|
||||
#include <Partition.h>
|
||||
|
||||
// PartitionFilterVisitor
|
||||
|
||||
// constructor
|
||||
PartitionFilterVisitor::PartitionFilterVisitor(BDiskDeviceVisitor *visitor,
|
||||
PartitionFilter *filter)
|
||||
: BDiskDeviceVisitor(),
|
||||
fVisitor(visitor),
|
||||
fFilter(filter)
|
||||
{
|
||||
}
|
||||
|
||||
// Visit
|
||||
bool
|
||||
PartitionFilterVisitor::Visit(BDiskDevice *device)
|
||||
{
|
||||
if (fFilter->Filter(device, 0))
|
||||
return fVisitor->Visit(device);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Visit
|
||||
bool
|
||||
PartitionFilterVisitor::Visit(BPartition *partition, int32 level)
|
||||
{
|
||||
if (fFilter->Filter(partition, level))
|
||||
return fVisitor->Visit(partition, level);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// IDFinderVisitor
|
||||
|
||||
// constructor
|
||||
IDFinderVisitor::IDFinderVisitor(int32 id)
|
||||
: BDiskDeviceVisitor(),
|
||||
fID(id)
|
||||
{
|
||||
}
|
||||
|
||||
// Visit
|
||||
bool
|
||||
IDFinderVisitor::Visit(BDiskDevice *device)
|
||||
{
|
||||
return (device->ID() == fID);
|
||||
}
|
||||
|
||||
// Visit
|
||||
bool
|
||||
IDFinderVisitor::Visit(BPartition *partition, int32 level)
|
||||
{
|
||||
return (partition->ID() == fID);
|
||||
}
|
||||
|
|
@ -1,870 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <DiskDevice.h>
|
||||
#include <DiskDeviceJob.h>
|
||||
#include <DiskDevicePrivate.h>
|
||||
#include <DiskDeviceRoster.h>
|
||||
#include <DiskSystem.h>
|
||||
#include <Entry.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Message.h>
|
||||
#include <Partition.h>
|
||||
#include <Path.h>
|
||||
|
||||
//#include "AddOnImage.h"
|
||||
|
||||
/*! \class BDiskDeviceRoster
|
||||
\brief An interface for iterating through the disk devices known to the
|
||||
system and for a notification mechanism provided to listen to their
|
||||
changes.
|
||||
*/
|
||||
|
||||
/*! \brief find_directory constants of the add-on dirs to be searched. */
|
||||
static const directory_which kAddOnDirs[] = {
|
||||
B_USER_ADDONS_DIRECTORY,
|
||||
// B_COMMON_ADDONS_DIRECTORY,
|
||||
B_BEOS_ADDONS_DIRECTORY
|
||||
};
|
||||
/*! \brief Size of the kAddOnDirs array. */
|
||||
static const int32 kAddOnDirCount
|
||||
= sizeof(kAddOnDirs) / sizeof(directory_which);
|
||||
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates a BDiskDeviceRoster object.
|
||||
|
||||
The object is ready to be used after construction.
|
||||
*/
|
||||
BDiskDeviceRoster::BDiskDeviceRoster()
|
||||
: fDeviceCookie(0),
|
||||
fDiskSystemCookie(0),
|
||||
fJobCookie(0)
|
||||
// fPartitionAddOnDir(NULL),
|
||||
// fFSAddOnDir(NULL),
|
||||
// fPartitionAddOnDirIndex(0),
|
||||
// fFSAddOnDirIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with the object.
|
||||
*/
|
||||
BDiskDeviceRoster::~BDiskDeviceRoster()
|
||||
{
|
||||
// if (fPartitionAddOnDir)
|
||||
// delete fPartitionAddOnDir;
|
||||
// if (fFSAddOnDir)
|
||||
// delete fFSAddOnDir;
|
||||
}
|
||||
|
||||
// GetNextDevice
|
||||
/*! \brief Returns the next BDiskDevice.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized to
|
||||
represent the next device.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: The end of the list of devices had already been
|
||||
reached.
|
||||
- another error code
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::GetNextDevice(BDiskDevice *device)
|
||||
{
|
||||
if (!device)
|
||||
return B_BAD_VALUE;
|
||||
size_t neededSize = 0;
|
||||
partition_id id = _kern_get_next_disk_device_id(&fDeviceCookie,
|
||||
&neededSize);
|
||||
if (id < 0)
|
||||
return id;
|
||||
return device->_SetTo(id, true, false, neededSize);
|
||||
}
|
||||
|
||||
// RewindDevices
|
||||
/*! \brief Rewinds the device list iterator.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::RewindDevices()
|
||||
{
|
||||
fDeviceCookie = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// GetNextDiskSystem
|
||||
status_t
|
||||
BDiskDeviceRoster::GetNextDiskSystem(BDiskSystem *system)
|
||||
{
|
||||
if (!system)
|
||||
return B_BAD_VALUE;
|
||||
user_disk_system_info info;
|
||||
status_t error = _kern_get_next_disk_system_info(&fDiskSystemCookie,
|
||||
&info);
|
||||
if (error == B_OK)
|
||||
error = system->_SetTo(&info);
|
||||
return error;
|
||||
}
|
||||
|
||||
// RewindDiskSystems
|
||||
status_t
|
||||
BDiskDeviceRoster::RewindDiskSystems()
|
||||
{
|
||||
fDiskSystemCookie = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// GetNextActiveJob
|
||||
status_t
|
||||
BDiskDeviceRoster::GetNextActiveJob(BDiskDeviceJob *job)
|
||||
{
|
||||
if (!job)
|
||||
return B_BAD_VALUE;
|
||||
user_disk_device_job_info info;
|
||||
status_t error = _kern_get_next_disk_device_job_info(&fJobCookie, &info);
|
||||
if (error == B_OK)
|
||||
error = job->_SetTo(&info);
|
||||
return error;
|
||||
}
|
||||
|
||||
// RewindActiveJobs
|
||||
status_t
|
||||
BDiskDeviceRoster::RewindActiveJobs()
|
||||
{
|
||||
fJobCookie = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// RegisterFileDevice
|
||||
partition_id
|
||||
BDiskDeviceRoster::RegisterFileDevice(const char *filename)
|
||||
{
|
||||
if (!filename)
|
||||
return B_BAD_VALUE;
|
||||
return _kern_register_file_device(filename);
|
||||
}
|
||||
|
||||
// UnregisterFileDevice
|
||||
status_t
|
||||
BDiskDeviceRoster::UnregisterFileDevice(const char *filename)
|
||||
{
|
||||
if (!filename)
|
||||
return B_BAD_VALUE;
|
||||
return _kern_unregister_file_device(-1, filename);
|
||||
}
|
||||
|
||||
// UnregisterFileDevice
|
||||
status_t
|
||||
BDiskDeviceRoster::UnregisterFileDevice(partition_id device)
|
||||
{
|
||||
if (device < 0)
|
||||
return B_BAD_VALUE;
|
||||
return _kern_unregister_file_device(device, NULL);
|
||||
}
|
||||
|
||||
// VisitEachDevice
|
||||
/*! \brief Iterates through the all devices.
|
||||
|
||||
The supplied visitor's Visit(BDiskDevice*) is invoked for each device.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns \c true. If supplied, \a device is set to the concerned device.
|
||||
|
||||
\param visitor The visitor.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized
|
||||
to the device at which the iteration was terminated.
|
||||
May be \c NULL.
|
||||
\return \c true, if the iteration was terminated, \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDeviceRoster::VisitEachDevice(BDiskDeviceVisitor *visitor,
|
||||
BDiskDevice *device)
|
||||
{
|
||||
bool terminatedEarly = false;
|
||||
if (visitor) {
|
||||
int32 oldCookie = fDeviceCookie;
|
||||
fDeviceCookie = 0;
|
||||
BDiskDevice deviceOnStack;
|
||||
BDiskDevice *useDevice = (device ? device : &deviceOnStack);
|
||||
while (!terminatedEarly && GetNextDevice(useDevice) == B_OK)
|
||||
terminatedEarly = visitor->Visit(useDevice);
|
||||
fDeviceCookie = oldCookie;
|
||||
if (!terminatedEarly)
|
||||
useDevice->Unset();
|
||||
}
|
||||
return terminatedEarly;
|
||||
}
|
||||
|
||||
// VisitEachPartition
|
||||
/*! \brief Pre-order traverses the trees spanned by the BDiskDevices and their
|
||||
subobjects.
|
||||
|
||||
The supplied visitor's Visit(BDiskDevice*) method is invoked for each
|
||||
disk device and Visit(BPartition*) for each (non-disk device) partition.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns \c true. If supplied, \a device is set to the concerned device
|
||||
and in \a partition the pointer to the partition object is returned.
|
||||
|
||||
\param visitor The visitor.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized
|
||||
to the device at which the iteration was terminated.
|
||||
May be \c NULL.
|
||||
\param partition Pointer to a pre-allocated BPartition pointer to be set
|
||||
to the partition at which the iteration was terminated.
|
||||
May be \c NULL.
|
||||
\return \c true, if the iteration was terminated, \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDeviceRoster::VisitEachPartition(BDiskDeviceVisitor *visitor,
|
||||
BDiskDevice *device,
|
||||
BPartition **partition)
|
||||
{
|
||||
bool terminatedEarly = false;
|
||||
if (visitor) {
|
||||
int32 oldCookie = fDeviceCookie;
|
||||
fDeviceCookie = 0;
|
||||
BDiskDevice deviceOnStack;
|
||||
BDiskDevice *useDevice = (device ? device : &deviceOnStack);
|
||||
BPartition *foundPartition = NULL;
|
||||
while (!foundPartition && GetNextDevice(useDevice) == B_OK)
|
||||
foundPartition = useDevice->VisitEachDescendant(visitor);
|
||||
fDeviceCookie = oldCookie;
|
||||
if (!terminatedEarly)
|
||||
useDevice->Unset();
|
||||
else if (device && partition)
|
||||
*partition = foundPartition;
|
||||
}
|
||||
return terminatedEarly;
|
||||
}
|
||||
|
||||
// VisitEachMountedPartition
|
||||
/*! \brief Iterates through the all devices' partitions that are mounted.
|
||||
|
||||
The supplied visitor's Visit(BPartition*) is invoked for each mounted
|
||||
partition.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns \c true. If supplied, \a device is set to the concerned device
|
||||
and in \a partition the pointer to the partition object is returned.
|
||||
|
||||
\param visitor The visitor.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized
|
||||
to the device at which the iteration was terminated.
|
||||
May be \c NULL.
|
||||
\param partition Pointer to a pre-allocated BPartition pointer to be set
|
||||
to the partition at which the iteration was terminated.
|
||||
May be \c NULL.
|
||||
\return \c true, if the iteration was terminated, \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDeviceRoster::VisitEachMountedPartition(BDiskDeviceVisitor *visitor,
|
||||
BDiskDevice *device,
|
||||
BPartition **partition)
|
||||
{
|
||||
bool terminatedEarly = false;
|
||||
if (visitor) {
|
||||
struct MountedPartitionFilter : public PartitionFilter {
|
||||
virtual bool Filter(BPartition *partition, int32)
|
||||
{ return partition->IsMounted(); }
|
||||
} filter;
|
||||
PartitionFilterVisitor filterVisitor(visitor, &filter);
|
||||
terminatedEarly
|
||||
= VisitEachPartition(&filterVisitor, device, partition);
|
||||
}
|
||||
return terminatedEarly;
|
||||
}
|
||||
|
||||
// VisitEachMountablePartition
|
||||
/*! \brief Iterates through the all devices' partitions that are mountable.
|
||||
|
||||
The supplied visitor's Visit(BPartition*) is invoked for each mountable
|
||||
partition.
|
||||
If Visit() returns \c true, the iteration is terminated and this method
|
||||
returns \c true. If supplied, \a device is set to the concerned device
|
||||
and in \a partition the pointer to the partition object is returned.
|
||||
|
||||
\param visitor The visitor.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized
|
||||
to the device at which the iteration was terminated.
|
||||
May be \c NULL.
|
||||
\param partition Pointer to a pre-allocated BPartition pointer to be set
|
||||
to the partition at which the iteration was terminated.
|
||||
May be \c NULL.
|
||||
\return \c true, if the iteration was terminated, \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDeviceRoster::VisitEachMountablePartition(BDiskDeviceVisitor *visitor,
|
||||
BDiskDevice *device,
|
||||
BPartition **partition)
|
||||
{
|
||||
bool terminatedEarly = false;
|
||||
if (visitor) {
|
||||
struct MountablePartitionFilter : public PartitionFilter {
|
||||
virtual bool Filter(BPartition *partition, int32)
|
||||
{ return partition->ContainsFileSystem(); }
|
||||
} filter;
|
||||
PartitionFilterVisitor filterVisitor(visitor, &filter);
|
||||
terminatedEarly
|
||||
= VisitEachPartition(&filterVisitor, device, partition);
|
||||
}
|
||||
return terminatedEarly;
|
||||
}
|
||||
|
||||
// GetDeviceWithID
|
||||
/*! \brief Returns a BDiskDevice for a given ID.
|
||||
|
||||
The supplied \a device is initialized to the device identified by \a id.
|
||||
|
||||
\param id The ID of the device to be retrieved.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized
|
||||
to the device identified by \a id.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: A device with ID \a id could not be found.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::GetDeviceWithID(int32 id, BDiskDevice *device) const
|
||||
{
|
||||
if (!device)
|
||||
return B_BAD_VALUE;
|
||||
return device->_SetTo(id, true, false, 0);
|
||||
}
|
||||
|
||||
// GetPartitionWithID
|
||||
/*! \brief Returns a BPartition for a given ID.
|
||||
|
||||
The supplied \a device is initialized to the device the partition
|
||||
identified by \a id resides on, and \a partition is set to point to the
|
||||
respective BPartition.
|
||||
|
||||
\param id The ID of the partition to be retrieved.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized
|
||||
to the device the partition identified by \a id resides on.
|
||||
\param partition Pointer to a pre-allocated BPartition pointer to be set
|
||||
to the partition identified by \a id.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: A partition with ID \a id could not be found.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::GetPartitionWithID(int32 id, BDiskDevice *device,
|
||||
BPartition **partition) const
|
||||
{
|
||||
if (!device || !partition)
|
||||
return B_BAD_VALUE;
|
||||
// download the device data
|
||||
status_t error = device->_SetTo(id, false, false, 0);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// find the partition object
|
||||
*partition = device->FindDescendant(id);
|
||||
if (!*partition) // should never happen!
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// GetDeviceForPath
|
||||
status_t
|
||||
BDiskDeviceRoster::GetDeviceForPath(const char *filename, BDiskDevice *device)
|
||||
{
|
||||
if (!filename || !device)
|
||||
return B_BAD_VALUE;
|
||||
// get the device ID
|
||||
size_t neededSize = 0;
|
||||
partition_id id = _kern_find_disk_device(filename, &neededSize);
|
||||
if (id < 0)
|
||||
return id;
|
||||
// download the device data
|
||||
return device->_SetTo(id, true, false, neededSize);
|
||||
}
|
||||
|
||||
// GetPartitionForPath
|
||||
status_t
|
||||
BDiskDeviceRoster::GetPartitionForPath(const char *filename,
|
||||
BDiskDevice *device,
|
||||
BPartition **partition)
|
||||
{
|
||||
if (!filename || !device || !partition)
|
||||
return B_BAD_VALUE;
|
||||
// get the partition ID
|
||||
size_t neededSize = 0;
|
||||
partition_id id = _kern_find_partition(filename, &neededSize);
|
||||
if (id < 0)
|
||||
return id;
|
||||
// download the device data
|
||||
status_t error = device->_SetTo(id, false, false, neededSize);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// find the partition object
|
||||
*partition = device->FindDescendant(id);
|
||||
if (!*partition) // should never happen!
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// StartWatching
|
||||
/*! \brief Adds a target to the list of targets to be notified on disk device
|
||||
events.
|
||||
|
||||
\todo List the event mask flags, the events and describe the layout of the
|
||||
notification message.
|
||||
|
||||
If \a target is already listening to events, this method replaces the
|
||||
former event mask with \a eventMask.
|
||||
|
||||
\param target A BMessenger identifying the target to which the events
|
||||
shall be sent.
|
||||
\param eventMask A mask specifying on which events the target shall be
|
||||
notified.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::StartWatching(BMessenger target, uint32 eventMask)
|
||||
{
|
||||
/* status_t error = B_OK;
|
||||
// compose request message
|
||||
BMessage request(B_REG_DEVICE_START_WATCHING);
|
||||
if (error == B_OK)
|
||||
error = request.AddMessenger("target", target);
|
||||
if (error == B_OK)
|
||||
error = request.AddInt32("events", (int32)eventMask);
|
||||
// send request
|
||||
BMessage reply;
|
||||
if (error == B_OK)
|
||||
error = fManager.SendMessage(&request, &reply);
|
||||
// analyze reply
|
||||
if (error == B_OK) {
|
||||
// result
|
||||
status_t result = B_OK;
|
||||
error = reply.FindInt32("result", &result);
|
||||
if (error == B_OK)
|
||||
error = result;
|
||||
}
|
||||
return error;
|
||||
*/
|
||||
// not implemented
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// StartWatchingJob
|
||||
status_t
|
||||
BDiskDeviceRoster::StartWatchingJob(BDiskDeviceJob *job, BMessenger target,
|
||||
uint32 eventMask)
|
||||
{
|
||||
// not implemented
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// StopWatching
|
||||
/*! \brief Remove a target from the list of targets to be notified on disk
|
||||
device events.
|
||||
\param target A BMessenger identifying the target to which notfication
|
||||
message shall not longer be sent.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::StopWatching(BMessenger target)
|
||||
{
|
||||
/* status_t error = B_OK;
|
||||
// compose request message
|
||||
BMessage request(B_REG_DEVICE_STOP_WATCHING);
|
||||
if (error == B_OK)
|
||||
error = request.AddMessenger("target", target);
|
||||
// send request
|
||||
BMessage reply;
|
||||
if (error == B_OK)
|
||||
error = fManager.SendMessage(&request, &reply);
|
||||
// analyze reply
|
||||
if (error == B_OK) {
|
||||
// result
|
||||
status_t result = B_OK;
|
||||
error = reply.FindInt32("result", &result);
|
||||
if (error == B_OK)
|
||||
error = result;
|
||||
}
|
||||
return error;
|
||||
*/
|
||||
// not implemented
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
// GetNextPartitioningSystem
|
||||
/*! \brief Returns the next partitioning system capable of partitioning.
|
||||
|
||||
The returned \a shortName can be passed to BSession::Partition().
|
||||
|
||||
\param shortName Pointer to a pre-allocation char buffer, of size
|
||||
\c B_FILE_NAME_LENGTH or larger into which the short name of the
|
||||
partitioning system shall be written.
|
||||
\param longName Pointer to a pre-allocation char buffer, of size
|
||||
\c B_FILE_NAME_LENGTH or larger into which the long name of the
|
||||
partitioning system shall be written. May be \c NULL.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_BAD_VALUE: \c NULL \a shortName.
|
||||
- \c B_ENTRY_NOT_FOUND: End of the list has been reached.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::GetNextPartitioningSystem(char *shortName, char *longName)
|
||||
{
|
||||
status_t error = (shortName ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
// search until an add-on has been found or the end of all directories
|
||||
// has been reached
|
||||
bool found = false;
|
||||
do {
|
||||
// get the next add-on in the current dir
|
||||
AddOnImage image;
|
||||
error = _GetNextAddOn(fPartitionAddOnDir, &image);
|
||||
if (error == B_OK) {
|
||||
// add-on loaded: get the function that creates an add-on
|
||||
// object
|
||||
BDiskScannerPartitionAddOn *(*create_add_on)();
|
||||
if (get_image_symbol(image.ID(), "create_ds_partition_add_on",
|
||||
B_SYMBOL_TYPE_TEXT,
|
||||
(void**)&create_add_on) == B_OK) {
|
||||
// create the add-on object and copy the requested data
|
||||
if (BDiskScannerPartitionAddOn *addOn
|
||||
= (*create_add_on)()) {
|
||||
const char *addOnShortName = addOn->ShortName();
|
||||
const char *addOnLongName = addOn->LongName();
|
||||
if (addOnShortName && addOnLongName) {
|
||||
strcpy(shortName, addOnShortName);
|
||||
if (longName)
|
||||
strcpy(longName, addOnLongName);
|
||||
found = true;
|
||||
}
|
||||
delete addOn;
|
||||
}
|
||||
}
|
||||
} else if (error == B_ENTRY_NOT_FOUND) {
|
||||
// end of the current directory has been reached, try next dir
|
||||
error = _GetNextAddOnDir(&fPartitionAddOnDir,
|
||||
&fPartitionAddOnDirIndex,
|
||||
"partition");
|
||||
}
|
||||
} while (error == B_OK && !found);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// GetNextFileSystem
|
||||
/*! \brief Returns the next file system capable of initializing.
|
||||
|
||||
The returned \a shortName can be passed to BPartition::Initialize().
|
||||
|
||||
\param shortName Pointer to a pre-allocation char buffer, of size
|
||||
\c B_FILE_NAME_LENGTH or larger into which the short name of the
|
||||
file system shall be written.
|
||||
\param longName Pointer to a pre-allocation char buffer, of size
|
||||
\c B_FILE_NAME_LENGTH or larger into which the long name of the
|
||||
file system shall be written. May be \c NULL.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_BAD_VALUE: \c NULL \a shortName.
|
||||
- \c B_ENTRY_NOT_FOUND: End of the list has been reached.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::GetNextFileSystem(char *shortName, char *longName)
|
||||
{
|
||||
status_t error = (shortName ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
// search until an add-on has been found or the end of all directories
|
||||
// has been reached
|
||||
bool found = false;
|
||||
do {
|
||||
// get the next add-on in the current dir
|
||||
AddOnImage image;
|
||||
error = _GetNextAddOn(fFSAddOnDir, &image);
|
||||
if (error == B_OK) {
|
||||
// add-on loaded: get the function that creates an add-on
|
||||
// object
|
||||
BDiskScannerFSAddOn *(*create_add_on)();
|
||||
if (get_image_symbol(image.ID(), "create_ds_fs_add_on",
|
||||
B_SYMBOL_TYPE_TEXT,
|
||||
(void**)&create_add_on) == B_OK) {
|
||||
// create the add-on object and copy the requested data
|
||||
if (BDiskScannerFSAddOn *addOn = (*create_add_on)()) {
|
||||
const char *addOnShortName = addOn->ShortName();
|
||||
const char *addOnLongName = addOn->LongName();
|
||||
if (addOnShortName && addOnLongName) {
|
||||
strcpy(shortName, addOnShortName);
|
||||
if (longName)
|
||||
strcpy(longName, addOnLongName);
|
||||
found = true;
|
||||
}
|
||||
delete addOn;
|
||||
}
|
||||
}
|
||||
} else if (error == B_ENTRY_NOT_FOUND) {
|
||||
// end of the current directory has been reached, try next dir
|
||||
error = _GetNextAddOnDir(&fFSAddOnDir, &fFSAddOnDirIndex,
|
||||
"fs");
|
||||
}
|
||||
} while (error == B_OK && !found);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// RewindPartitiningSystems
|
||||
/*! \brief Rewinds the partitioning system list iterator.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::RewindPartitiningSystems()
|
||||
{
|
||||
if (fPartitionAddOnDir) {
|
||||
delete fPartitionAddOnDir;
|
||||
fPartitionAddOnDir = NULL;
|
||||
}
|
||||
fPartitionAddOnDirIndex = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// RewindFileSystems
|
||||
/*! \brief Rewinds the file system list iterator.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::RewindFileSystems()
|
||||
{
|
||||
if (fFSAddOnDir) {
|
||||
delete fFSAddOnDir;
|
||||
fFSAddOnDir = NULL;
|
||||
}
|
||||
fFSAddOnDirIndex = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _GetObjectWithID
|
||||
/*! \brief Returns a BDiskDevice for a given device, session or partition ID.
|
||||
|
||||
The supplied \a device is initialized to the device the object identified
|
||||
by \a id belongs to.
|
||||
|
||||
\param fieldName "device_id", "sesison_id" or "partition_id" according to
|
||||
the type of object the device shall be retrieved for.
|
||||
\param id The ID of the device, session or partition to be retrieved.
|
||||
\param device Pointer to a pre-allocated BDiskDevice to be initialized
|
||||
to the device to be retrieved.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: A device, session or partition respectively with
|
||||
ID \a id could not be found.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::_GetObjectWithID(const char *fieldName, int32 id,
|
||||
BDiskDevice *device) const
|
||||
{
|
||||
status_t error = (device ? B_OK : B_BAD_VALUE);
|
||||
// compose request message
|
||||
BMessage request(B_REG_GET_DISK_DEVICE);
|
||||
if (error == B_OK)
|
||||
error = request.AddInt32(fieldName, id);
|
||||
// send request
|
||||
BMessage reply;
|
||||
if (error == B_OK)
|
||||
error = fManager.SendMessage(&request, &reply);
|
||||
// analyze reply
|
||||
if (error == B_OK) {
|
||||
// result
|
||||
status_t result = B_OK;
|
||||
error = reply.FindInt32("result", &result);
|
||||
if (error == B_OK)
|
||||
error = result;
|
||||
// device
|
||||
BMessage archive;
|
||||
if (error == B_OK)
|
||||
error = reply.FindMessage("device", &archive);
|
||||
if (error == B_OK)
|
||||
error = device->_Unarchive(&archive);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// _GetNextAddOn
|
||||
/*! \brief Finds and loads the next add-on of an add-on subdirectory.
|
||||
\param directory The add-on directory.
|
||||
\param image Pointer to an image_id into which the image ID of the loaded
|
||||
add-on shall be written.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: End of directory.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::_GetNextAddOn(BDirectory **directory, int32 *index,
|
||||
const char *subdir, AddOnImage *image)
|
||||
{
|
||||
status_t error = (directory && index && subdir && image
|
||||
? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
// search until an add-on has been found or the end of all directories
|
||||
// has been reached
|
||||
bool found = false;
|
||||
do {
|
||||
// get the next add-on in the current dir
|
||||
error = _GetNextAddOn(*directory, image);
|
||||
if (error == B_OK) {
|
||||
found = true;
|
||||
} else if (error == B_ENTRY_NOT_FOUND) {
|
||||
// end of the current directory has been reached, try next dir
|
||||
error = _GetNextAddOnDir(directory, index, subdir);
|
||||
}
|
||||
} while (error == B_OK && !found);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _GetNextAddOn
|
||||
/*! \brief Finds and loads the next add-on of an add-on subdirectory.
|
||||
\param directory The add-on directory.
|
||||
\param image Pointer to an image_id into which the image ID of the loaded
|
||||
add-on shall be written.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: End of directory.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::_GetNextAddOn(BDirectory *directory, AddOnImage *image)
|
||||
{
|
||||
status_t error = (directory ? B_OK : B_ENTRY_NOT_FOUND);
|
||||
if (error == B_OK) {
|
||||
// iterate through the entry list and try to load the entries
|
||||
bool found = false;
|
||||
while (error == B_OK && !found) {
|
||||
BEntry entry;
|
||||
error = directory->GetNextEntry(&entry);
|
||||
BPath path;
|
||||
if (error == B_OK && entry.GetPath(&path) == B_OK)
|
||||
found = (image->Load(path.Path()) == B_OK);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _GetNextAddOnDir
|
||||
/*! \brief Gets the next add-on directory path.
|
||||
\param path Pointer to a BPath to be set to the found directory.
|
||||
\param index Pointer to an index into the kAddOnDirs array indicating
|
||||
which add-on dir shall be retrieved next.
|
||||
\param subdir Name of the subdirectory (in the "disk_scanner" subdirectory
|
||||
of the add-on directory) \a directory shall be set to.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: End of directory list.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::_GetNextAddOnDir(BPath *path, int32 *index,
|
||||
const char *subdir)
|
||||
{
|
||||
status_t error = (*index < kAddOnDirCount ? B_OK : B_ENTRY_NOT_FOUND);
|
||||
// get the add-on dir path
|
||||
if (error == B_OK) {
|
||||
error = find_directory(kAddOnDirs[*index], path);
|
||||
(*index)++;
|
||||
}
|
||||
// construct the subdirectory path
|
||||
if (error == B_OK) {
|
||||
error = path->Append("disk_scanner");
|
||||
if (error == B_OK)
|
||||
error = path->Append(subdir);
|
||||
}
|
||||
if (error == B_OK)
|
||||
printf(" next add-on dir: `%s'\n", path->Path());
|
||||
return error;
|
||||
}
|
||||
|
||||
// _GetNextAddOnDir
|
||||
/*! \brief Gets the next add-on directory.
|
||||
\param directory Pointer to a BDirectory* to be set to the found directory.
|
||||
\param index Pointer to an index into the kAddOnDirs array indicating
|
||||
which add-on dir shall be retrieved next.
|
||||
\param subdir Name of the subdirectory (in the "disk_scanner" subdirectory
|
||||
of the add-on directory) \a directory shall be set to.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ENTRY_NOT_FOUND: End of directory list.
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BDiskDeviceRoster::_GetNextAddOnDir(BDirectory **directory, int32 *index,
|
||||
const char *subdir)
|
||||
{
|
||||
BPath path;
|
||||
status_t error = _GetNextAddOnDir(&path, index, subdir);
|
||||
// create a BDirectory object, if there is none yet.
|
||||
if (error == B_OK && !*directory) {
|
||||
*directory = new BDirectory;
|
||||
if (!*directory)
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
// init the directory
|
||||
if (error == B_OK)
|
||||
error = (*directory)->SetTo(path.Path());
|
||||
// cleanup on error
|
||||
if (error != B_OK && *directory) {
|
||||
delete *directory;
|
||||
*directory = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _LoadPartitionAddOn
|
||||
status_t
|
||||
BDiskDeviceRoster::_LoadPartitionAddOn(const char *partitioningSystem,
|
||||
AddOnImage *image,
|
||||
BDiskScannerPartitionAddOn **_addOn)
|
||||
{
|
||||
status_t error = (partitioningSystem && image && _addOn
|
||||
? B_OK : B_BAD_VALUE);
|
||||
// load the image
|
||||
bool found = false;
|
||||
BPath path;
|
||||
BDirectory *directory = NULL;
|
||||
int32 index = 0;
|
||||
while (error == B_OK && !found) {
|
||||
error = _GetNextAddOn(&directory, &index, "partition", image);
|
||||
if (error == B_OK) {
|
||||
// add-on loaded: get the function that creates an add-on
|
||||
// object
|
||||
BDiskScannerPartitionAddOn *(*create_add_on)();
|
||||
if (get_image_symbol(image->ID(), "create_ds_partition_add_on",
|
||||
B_SYMBOL_TYPE_TEXT,
|
||||
(void**)&create_add_on) == B_OK) {
|
||||
// create the add-on object and copy the requested data
|
||||
if (BDiskScannerPartitionAddOn *addOn = (*create_add_on)()) {
|
||||
if (!strcmp(addOn->ShortName(), partitioningSystem)) {
|
||||
*_addOn = addOn;
|
||||
found = true;
|
||||
} else
|
||||
delete addOn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
if (directory)
|
||||
delete directory;
|
||||
if (error != B_OK && image)
|
||||
image->Unload();
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // 0
|
|
@ -1,41 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the Haiku distribution and is covered
|
||||
// by the MIT license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <DiskDeviceTypes.h>
|
||||
|
||||
// Device Types
|
||||
|
||||
const char *kDeviceTypeFloppyDisk = "Floppy Disk Media";
|
||||
const char *kDeviceTypeHardDisk = "Hard Disk Media";
|
||||
const char *kDeviceTypeOptical = "Optical Media";
|
||||
|
||||
// Partition types
|
||||
|
||||
const char *kPartitionTypeUnrecognized = "Unrecognized";
|
||||
|
||||
const char *kPartitionTypeMultisession = "Multisession Storage Device";
|
||||
|
||||
const char *kPartitionTypeAudioSession = "Audio Session";
|
||||
const char *kPartitionTypeDataSession = "Data Session";
|
||||
|
||||
const char *kPartitionTypeAmiga = "Amiga Partition Map";
|
||||
const char *kPartitionTypeApple = "Apple Partition Map";
|
||||
const char *kPartitionTypeIntel = "Intel Partition Map";
|
||||
|
||||
const char *kPartitionTypeIntelPrimary = "Intel Primary Partition";
|
||||
const char *kPartitionTypeIntelExtended = "Intel Extended Partition";
|
||||
const char *kPartitionTypeIntelLogical = "Intel Logical Partition";
|
||||
|
||||
const char *kPartitionTypeAmigaFFS = "AmigaFFS Filesystem";
|
||||
const char *kPartitionTypeBFS = "BFS Filesystem";
|
||||
const char *kPartitionTypeEXT2 = "EXT2 Filesystem";
|
||||
const char *kPartitionTypeEXT3 = "EXT3 Filesystem";
|
||||
const char *kPartitionTypeFAT12 = "FAT12 Filesystem";
|
||||
const char *kPartitionTypeFAT32 = "FAT32 Filesystem";
|
||||
const char *kPartitionTypeHFS = "HFS Filesystem";
|
||||
const char *kPartitionTypeHFSPlus = "HFS+ Filesystem";
|
||||
const char *kPartitionTypeISO9660 = "ISO9660 Filesystem";
|
||||
const char *kPartitionTypeReiser = "Reiser Filesystem";
|
||||
const char *kPartitionTypeUDF = "UDF Filesystem";
|
|
@ -1,74 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <DiskDeviceVisitor.h>
|
||||
|
||||
/*! \class BDiskDeviceVisitor
|
||||
\brief Base class of visitors used for BDiskDevice and
|
||||
BPartition iteration.
|
||||
|
||||
BDiskDeviceRoster and BDiskDevice provide iteration methods,
|
||||
that work together with an instance of a derived class of
|
||||
BDiskDeviceVisitor. For each encountered BDiskDevice and
|
||||
BPartition the respective Visit() method is invoked. The return value
|
||||
of that method specifies whether the iteration shall be terminated at
|
||||
that point.
|
||||
*/
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates a new disk device visitor.
|
||||
*/
|
||||
BDiskDeviceVisitor::BDiskDeviceVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Free all resources associated with this object.
|
||||
|
||||
Does nothing.
|
||||
*/
|
||||
BDiskDeviceVisitor::~BDiskDeviceVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
// Visit
|
||||
/*! \brief Invoked when a BDiskDevice is visited.
|
||||
|
||||
If the method returns \c true, the iteration is terminated at this point,
|
||||
on \c false continued.
|
||||
|
||||
Overridden by derived classes.
|
||||
This class' version does nothing and it returns \c false.
|
||||
|
||||
\param device The visited disk device.
|
||||
\return \c true, if the iteration shall be terminated at this point,
|
||||
\c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDeviceVisitor::Visit(BDiskDevice *device)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Visit
|
||||
/*! \brief Invoked when a BPartition is visited.
|
||||
|
||||
If the method returns \c true, the iteration is terminated at this point,
|
||||
on \c false continued.
|
||||
|
||||
Overridden by derived classes.
|
||||
This class' version does nothing and it returns \c false.
|
||||
|
||||
\param partition The visited partition.
|
||||
\param level The level of the partition in the partition tree.
|
||||
\return \c true, if the iteration shall be terminated at this point,
|
||||
\c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskDeviceVisitor::Visit(BPartition *partition, int32 level)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <DiskScannerAddOn.h>
|
||||
#include <String.h>
|
||||
|
||||
// BDiskScannerPartitionAddOn
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates a partition disk scanner add-on.
|
||||
*/
|
||||
BDiskScannerPartitionAddOn::BDiskScannerPartitionAddOn()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with this object.
|
||||
*/
|
||||
BDiskScannerPartitionAddOn::~BDiskScannerPartitionAddOn()
|
||||
{
|
||||
}
|
||||
|
||||
/*! \fn virtual const char *BDiskScannerPartitionAddOn::ShortName() = 0;
|
||||
\brief Returns a short name for the add-on.
|
||||
|
||||
To be implemented by derived classes.
|
||||
|
||||
The returned string identifies the respective partition kernel module is
|
||||
passed to partition_session().
|
||||
|
||||
\return A short name for the add-on.
|
||||
*/
|
||||
|
||||
/*! \fn virtual const char *BDiskScannerPartitionAddOn::LongName() = 0;
|
||||
\brief Returns a user-readable long name for the add-on.
|
||||
|
||||
To be implemented by derived classes.
|
||||
|
||||
\return A long name for the add-on.
|
||||
*/
|
||||
|
||||
/*! \fn virtual BDiskScannerPartitionAddOn::BDiskScannerParameterEditor *
|
||||
CreateEditor(const BSession *session, const char *parameters) = 0;
|
||||
\brief Creates and returns an editor for editing partitioning parameters
|
||||
for a specified session.
|
||||
|
||||
To be implemented by derived classes.
|
||||
|
||||
\param session The session to be partitioned.
|
||||
\param parameters Parameters retrieved from the partition module. Should
|
||||
initially be presented to the user.
|
||||
\return The newly created editor. \c NULL, if an error occurred.
|
||||
*/
|
||||
|
||||
// FBC
|
||||
void BDiskScannerPartitionAddOn::_ReservedDiskScannerPartitionAddOn1() {}
|
||||
void BDiskScannerPartitionAddOn::_ReservedDiskScannerPartitionAddOn2() {}
|
||||
void BDiskScannerPartitionAddOn::_ReservedDiskScannerPartitionAddOn3() {}
|
||||
void BDiskScannerPartitionAddOn::_ReservedDiskScannerPartitionAddOn4() {}
|
||||
void BDiskScannerPartitionAddOn::_ReservedDiskScannerPartitionAddOn5() {}
|
||||
|
||||
|
||||
// BDiskScannerFSAddOn
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates a FS disk scanner add-on.
|
||||
*/
|
||||
BDiskScannerFSAddOn::BDiskScannerFSAddOn()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with this object.
|
||||
*/
|
||||
BDiskScannerFSAddOn::~BDiskScannerFSAddOn()
|
||||
{
|
||||
}
|
||||
|
||||
/*! \fn virtual const char *BDiskScannerFSAddOn::ShortName() = 0;
|
||||
\brief Returns a short name for the add-on.
|
||||
|
||||
To be implemented by derived classes.
|
||||
|
||||
The returned name identifies the file system (the kernel add-on) and is
|
||||
passed to initialize_volume().
|
||||
|
||||
\return A short name for the add-on.
|
||||
*/
|
||||
|
||||
/*! \fn virtual const char *BDiskScannerFSAddOn::LongName() = 0;
|
||||
\brief Returns a user-readable long name for the add-on.
|
||||
|
||||
To be implemented by derived classes.
|
||||
|
||||
\return A long name for the add-on.
|
||||
*/
|
||||
|
||||
/*! \fn virtual BDiskScannerFSAddOn::BDiskScannerParameterEditor *CreateEditor(
|
||||
const BPartition *partition, const char *parameters) = 0;
|
||||
\brief Creates and returns an editor for editing initialization parameters
|
||||
for a specified partition.
|
||||
|
||||
To be implemented by derived classes.
|
||||
|
||||
\param partition The partition to be initialized.
|
||||
\param parameters Parameters retrieved from the kernel FS add-on. Should
|
||||
initially be presented to the user.
|
||||
\return The newly created editor. \c NULL, if the FS doesn't need any
|
||||
further parameters.
|
||||
*/
|
||||
|
||||
// FBC
|
||||
void BDiskScannerFSAddOn::_ReservedDiskScannerFSAddOn1() {}
|
||||
void BDiskScannerFSAddOn::_ReservedDiskScannerFSAddOn2() {}
|
||||
void BDiskScannerFSAddOn::_ReservedDiskScannerFSAddOn3() {}
|
||||
void BDiskScannerFSAddOn::_ReservedDiskScannerFSAddOn4() {}
|
||||
void BDiskScannerFSAddOn::_ReservedDiskScannerFSAddOn5() {}
|
||||
|
||||
|
||||
// BDiskScannerParameterEditor
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates a disk scanner parameter editor.
|
||||
*/
|
||||
BDiskScannerParameterEditor::BDiskScannerParameterEditor()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with this object.
|
||||
*/
|
||||
BDiskScannerParameterEditor::~BDiskScannerParameterEditor()
|
||||
{
|
||||
}
|
||||
|
||||
/*! \brief Returns a view containing the controls needed for editing the
|
||||
parameters.
|
||||
|
||||
To be overridden by derived classes.
|
||||
The base class version returns \c NULL.
|
||||
|
||||
The returned BView is added to a window occasionally and removed, when
|
||||
editing is done. The view belongs to the editor and needs to be deleted
|
||||
by it. Subsequent calls to this method may return the same view, or each
|
||||
time delete the old one and return a new one.
|
||||
|
||||
\return A view containing the controls needed for editing the parameters.
|
||||
\c NULL can be returned, if no parameters are needed.
|
||||
*/
|
||||
BView *
|
||||
BDiskScannerParameterEditor::View()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// EditingDone
|
||||
/*! \brief Called when the user finishes editing the parameters.
|
||||
|
||||
To be overridden by derived classes.
|
||||
The base class version returns \c true.
|
||||
|
||||
The method is supposed to check whether the parameters the user set,
|
||||
are valid, and, if so, return \c true. Otherwise an BAlert shall be
|
||||
shown, explaining the problem to the user and \c false being returned
|
||||
-- then the parameter dialog will not be closed.
|
||||
|
||||
\return \c true, if the current parameters are valid, \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
BDiskScannerParameterEditor::EditingDone()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \brief Returns the edited parameters.
|
||||
|
||||
To be overridden by derived classes.
|
||||
The base class version returns an empty string.
|
||||
|
||||
\param parameters A BString to be set to the edited parameters.
|
||||
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
BDiskScannerParameterEditor::GetParameters(BString *parameters)
|
||||
{
|
||||
status_t error = (parameters ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK)
|
||||
parameters->SetTo("");
|
||||
return error;
|
||||
}
|
||||
|
||||
// FBC
|
||||
void BDiskScannerParameterEditor::_ReservedDiskScannerParameterEditor1() {}
|
||||
void BDiskScannerParameterEditor::_ReservedDiskScannerParameterEditor2() {}
|
||||
void BDiskScannerParameterEditor::_ReservedDiskScannerParameterEditor3() {}
|
||||
void BDiskScannerParameterEditor::_ReservedDiskScannerParameterEditor4() {}
|
||||
void BDiskScannerParameterEditor::_ReservedDiskScannerParameterEditor5() {}
|
||||
|
||||
|
||||
/*! \fn BDiskScannerPartitionAddOn *create_ds_partition_add_on();
|
||||
\brief To be provided by partition add-ons to create an add-on object.
|
||||
\return A newly created BDiskScannerPartitionAddOn for this add-on.
|
||||
*/
|
||||
|
||||
/*! \fn BDiskScannerFSAddOn *create_ds_fs_add_on();
|
||||
\brief To be provided by FS add-ons to create an add-on object.
|
||||
\return A newly created BDiskScannerFSAddOn for this add-on.
|
||||
*/
|
||||
|
|
@ -1,306 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
#include <DiskSystem.h>
|
||||
#include <Partition.h>
|
||||
|
||||
// constructor
|
||||
BDiskSystem::BDiskSystem()
|
||||
: fID(B_NO_INIT),
|
||||
fName(),
|
||||
fPrettyName(),
|
||||
fFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
BDiskSystem::~BDiskSystem()
|
||||
{
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
BDiskSystem::InitCheck() const
|
||||
{
|
||||
return (fID > 0 ? B_OK : fID);
|
||||
}
|
||||
|
||||
// Name
|
||||
const char *
|
||||
BDiskSystem::Name() const
|
||||
{
|
||||
return fName.String();
|
||||
}
|
||||
|
||||
// PrettyName
|
||||
const char *
|
||||
BDiskSystem::PrettyName() const
|
||||
{
|
||||
return fPrettyName.String();
|
||||
}
|
||||
|
||||
// SupportsDefragmenting
|
||||
bool
|
||||
BDiskSystem::SupportsDefragmenting(bool *whileMounted) const
|
||||
{
|
||||
if (InitCheck() != B_OK
|
||||
|| !(fFlags & B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING)) {
|
||||
if (whileMounted)
|
||||
*whileMounted = false;
|
||||
return false;
|
||||
}
|
||||
if (whileMounted) {
|
||||
*whileMounted = (IsFileSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING_WHILE_MOUNTED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// SupportsRepairing
|
||||
bool
|
||||
BDiskSystem::SupportsRepairing(bool checkOnly, bool *whileMounted) const
|
||||
{
|
||||
uint32 mainBit = B_DISK_SYSTEM_SUPPORTS_REPAIRING;
|
||||
uint32 mountedBit = B_DISK_SYSTEM_SUPPORTS_REPAIRING_WHILE_MOUNTED;
|
||||
if (checkOnly) {
|
||||
mainBit = B_DISK_SYSTEM_SUPPORTS_CHECKING;
|
||||
mountedBit = B_DISK_SYSTEM_SUPPORTS_CHECKING_WHILE_MOUNTED;
|
||||
}
|
||||
if (InitCheck() != B_OK || !(fFlags & mainBit)) {
|
||||
if (whileMounted)
|
||||
*whileMounted = false;
|
||||
return false;
|
||||
}
|
||||
if (whileMounted)
|
||||
*whileMounted = (IsFileSystem() && (fFlags & mountedBit));
|
||||
return true;
|
||||
}
|
||||
|
||||
// SupportsResizing
|
||||
bool
|
||||
BDiskSystem::SupportsResizing(bool *whileMounted) const
|
||||
{
|
||||
if (InitCheck() != B_OK
|
||||
|| !(fFlags & B_DISK_SYSTEM_SUPPORTS_RESIZING)) {
|
||||
if (whileMounted)
|
||||
*whileMounted = false;
|
||||
return false;
|
||||
}
|
||||
if (whileMounted) {
|
||||
*whileMounted = (IsFileSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// SupportsResizingChild
|
||||
bool
|
||||
BDiskSystem::SupportsResizingChild() const
|
||||
{
|
||||
return (InitCheck() == B_OK && IsPartitioningSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD));
|
||||
}
|
||||
|
||||
// SupportsMoving
|
||||
bool
|
||||
BDiskSystem::SupportsMoving(bool *whileMounted) const
|
||||
{
|
||||
if (InitCheck() != B_OK
|
||||
|| !(fFlags & B_DISK_SYSTEM_SUPPORTS_MOVING)) {
|
||||
if (whileMounted)
|
||||
*whileMounted = false;
|
||||
return false;
|
||||
}
|
||||
if (whileMounted) {
|
||||
*whileMounted = (IsFileSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_MOVING_WHILE_MOUNTED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// SupportsMovingChild
|
||||
bool
|
||||
BDiskSystem::SupportsMovingChild() const
|
||||
{
|
||||
return (InitCheck() == B_OK && IsPartitioningSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD));
|
||||
}
|
||||
|
||||
// SupportsSettingName
|
||||
bool
|
||||
BDiskSystem::SupportsSettingName() const
|
||||
{
|
||||
return (InitCheck() == B_OK && IsPartitioningSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_SETTING_NAME));
|
||||
}
|
||||
|
||||
// SupportsSettingContentName
|
||||
bool
|
||||
BDiskSystem::SupportsSettingContentName(bool *whileMounted) const
|
||||
{
|
||||
if (InitCheck() != B_OK
|
||||
|| !(fFlags & B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME)) {
|
||||
if (whileMounted)
|
||||
*whileMounted = false;
|
||||
return false;
|
||||
}
|
||||
if (whileMounted) {
|
||||
*whileMounted = (IsFileSystem()
|
||||
&& (fFlags
|
||||
& B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME_WHILE_MOUNTED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// SupportsSettingType
|
||||
bool
|
||||
BDiskSystem::SupportsSettingType() const
|
||||
{
|
||||
return (InitCheck() == B_OK && IsPartitioningSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE));
|
||||
}
|
||||
|
||||
// SupportsSettingParameters
|
||||
bool
|
||||
BDiskSystem::SupportsSettingParameters() const
|
||||
{
|
||||
return (InitCheck() == B_OK && IsPartitioningSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS));
|
||||
}
|
||||
|
||||
// SupportsSettingContentParameters
|
||||
bool
|
||||
BDiskSystem::SupportsSettingContentParameters(bool *whileMounted) const
|
||||
{
|
||||
if (InitCheck() != B_OK
|
||||
|| !(fFlags & B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS)) {
|
||||
if (whileMounted)
|
||||
*whileMounted = false;
|
||||
return false;
|
||||
}
|
||||
if (whileMounted) {
|
||||
*whileMounted = (IsFileSystem()
|
||||
&& (fFlags
|
||||
& B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS_WHILE_MOUNTED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// SupportsCreatingChild
|
||||
bool
|
||||
BDiskSystem::SupportsCreatingChild() const
|
||||
{
|
||||
return (InitCheck() == B_OK && IsPartitioningSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD));
|
||||
}
|
||||
|
||||
// SupportsDeletingChild
|
||||
bool
|
||||
BDiskSystem::SupportsDeletingChild() const
|
||||
{
|
||||
return (InitCheck() == B_OK && IsPartitioningSystem()
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD));
|
||||
}
|
||||
|
||||
// SupportsInitializing
|
||||
bool
|
||||
BDiskSystem::SupportsInitializing() const
|
||||
{
|
||||
return (InitCheck() == B_OK
|
||||
&& (fFlags & B_DISK_SYSTEM_SUPPORTS_INITIALIZING));
|
||||
}
|
||||
|
||||
// GetNextSupportedType
|
||||
status_t
|
||||
BDiskSystem::GetNextSupportedType(BPartition *partition, int32 *cookie,
|
||||
char *type) const
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return InitCheck();
|
||||
if (!cookie || !type || !partition || !partition->_IsShadow()
|
||||
|| !partition->Parent() || partition->Parent()->_DiskSystem() != fID
|
||||
|| !IsPartitioningSystem()) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
return _kern_get_next_supported_partition_type(partition->_ShadowID(),
|
||||
partition->_ChangeCounter(),
|
||||
cookie, type);
|
||||
}
|
||||
|
||||
// GetTypeForContentType
|
||||
status_t
|
||||
BDiskSystem::GetTypeForContentType(const char *contentType, char *type) const
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return InitCheck();
|
||||
if (!contentType || !type || !IsPartitioningSystem())
|
||||
return B_BAD_VALUE;
|
||||
return _kern_get_partition_type_for_content_type(fID, contentType, type);
|
||||
}
|
||||
|
||||
// IsPartitioningSystem
|
||||
bool
|
||||
BDiskSystem::IsPartitioningSystem() const
|
||||
{
|
||||
return (InitCheck() == B_OK && !(fFlags & B_DISK_SYSTEM_IS_FILE_SYSTEM));
|
||||
}
|
||||
|
||||
// IsFileSystem
|
||||
bool
|
||||
BDiskSystem::IsFileSystem() const
|
||||
{
|
||||
return (InitCheck() == B_OK && (fFlags & B_DISK_SYSTEM_IS_FILE_SYSTEM));
|
||||
}
|
||||
|
||||
// IsSubSystemFor
|
||||
bool
|
||||
BDiskSystem::IsSubSystemFor(BPartition *parent) const
|
||||
{
|
||||
return (InitCheck() == B_OK
|
||||
&& parent && parent->_IsShadow()
|
||||
&& _kern_is_sub_disk_system_for(fID, parent->_ShadowID(),
|
||||
parent->_ChangeCounter()));
|
||||
}
|
||||
|
||||
// _SetTo
|
||||
status_t
|
||||
BDiskSystem::_SetTo(disk_system_id id)
|
||||
{
|
||||
_Unset();
|
||||
if (id < 0)
|
||||
return fID;
|
||||
user_disk_system_info info;
|
||||
status_t error = _kern_get_disk_system_info(id, &info);
|
||||
if (error != B_OK)
|
||||
return (fID = error);
|
||||
return _SetTo(&info);
|
||||
}
|
||||
|
||||
// _SetTo
|
||||
status_t
|
||||
BDiskSystem::_SetTo(user_disk_system_info *info)
|
||||
{
|
||||
_Unset();
|
||||
if (!info)
|
||||
return (fID = B_BAD_VALUE);
|
||||
fID = info->id;
|
||||
fName = info->name;
|
||||
fPrettyName = info->pretty_name;
|
||||
fFlags = info->flags;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _Unset
|
||||
void
|
||||
BDiskSystem::_Unset()
|
||||
{
|
||||
fID = B_NO_INIT;
|
||||
fName = (const char*)NULL;
|
||||
fPrettyName = (const char*)NULL;
|
||||
fFlags = 0;
|
||||
}
|
||||
|
|
@ -1,722 +0,0 @@
|
|||
// LibBeAdapter.cpp
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <fs_attr.h>
|
||||
#include <fs_query.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
|
||||
mode_t __gUmask = 022;
|
||||
// this is the standard umask and is used by BFile
|
||||
|
||||
enum {
|
||||
FD_TYPE_UNKNOWN,
|
||||
FD_TYPE_DIR,
|
||||
FD_TYPE_ATTR_DIR,
|
||||
FD_TYPE_QUERY,
|
||||
};
|
||||
|
||||
static const int kFDTableSlotCount = 1024;
|
||||
static uint8 sFDTable[kFDTableSlotCount];
|
||||
|
||||
static struct InitDirFDTable {
|
||||
InitDirFDTable()
|
||||
{
|
||||
memset(sFDTable, FD_TYPE_UNKNOWN, sizeof(sFDTable));
|
||||
}
|
||||
} sInitDirFDTable;
|
||||
|
||||
// _kern_entry_ref_to_path
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf,
|
||||
char *userPath, size_t pathLength)
|
||||
{
|
||||
// check buffer
|
||||
if (!userPath)
|
||||
return B_BAD_VALUE;
|
||||
// construct an entry_ref
|
||||
if (!leaf)
|
||||
leaf = ".";
|
||||
entry_ref ref(device, inode, leaf);
|
||||
// get the path
|
||||
BPath path;
|
||||
status_t error = path.SetTo(&ref);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// copy the path into the buffer
|
||||
if (strlcpy(userPath, path.Path(), pathLength) >= pathLength)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// Syscall mapping between R5 and us
|
||||
|
||||
// private libroot.so functions
|
||||
|
||||
extern "C" status_t _kclosedir_(int fd);
|
||||
|
||||
extern "C" status_t _kclose_attr_dir_(int fd);
|
||||
|
||||
extern "C" status_t _kclose_query_(int fd);
|
||||
|
||||
extern "C" ssize_t _kreadlink_(int fd, const char *path, char *buffer,
|
||||
size_t bufferSize);
|
||||
|
||||
extern "C" status_t _krstat_(int fd, const char *path, struct stat *st,
|
||||
int16 unknown);
|
||||
|
||||
extern "C" status_t _kwstat_(int fd, const char *path, const struct stat *st,
|
||||
uint32 mask, uint16 unknown);
|
||||
|
||||
extern "C" status_t _kwfsstat_(dev_t device, const struct fs_info *info,
|
||||
long mask);
|
||||
|
||||
extern "C" status_t _klock_node_(int fd);
|
||||
|
||||
extern "C" status_t _kunlock_node_(int fd);
|
||||
|
||||
extern "C" status_t _kstart_watching_vnode_(dev_t device, ino_t node,
|
||||
uint32 flags, port_id port,
|
||||
int32 handlerToken);
|
||||
|
||||
extern "C" status_t _kstop_watching_vnode_(dev_t device, ino_t node,
|
||||
port_id port, int32 handlerToken);
|
||||
|
||||
|
||||
extern "C" status_t _kstop_notifying_(port_id port, int32 handlerToken);
|
||||
|
||||
extern "C" status_t _kget_safemode_option_(const char *parameter, char *buffer, size_t *_bufferSize);
|
||||
|
||||
|
||||
status_t
|
||||
_kern_write_fs_info(dev_t device, const struct fs_info *info, int mask)
|
||||
{
|
||||
return _kwfsstat_(device, info, mask);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_kern_stop_notifying(port_id port, uint32 token)
|
||||
{
|
||||
return _kstop_notifying_(port, token);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_kern_start_watching(dev_t device, ino_t node, uint32 flags,
|
||||
port_id port, uint32 token)
|
||||
{
|
||||
return _kstart_watching_vnode_(device, node, flags, port, token);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_kern_stop_watching(dev_t device, ino_t node, uint32 flags,
|
||||
port_id port, uint32 token)
|
||||
{
|
||||
(void)flags;
|
||||
return _kstop_watching_vnode_(device, node, port, token);
|
||||
}
|
||||
|
||||
// init_dir
|
||||
static
|
||||
status_t
|
||||
init_dir(BDirectory &dir, int fd)
|
||||
{
|
||||
// get a node_ref for the dir
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0)
|
||||
return errno;
|
||||
node_ref ref;
|
||||
ref.device = st.st_dev;
|
||||
ref.node = st.st_ino;
|
||||
// init the dir
|
||||
return dir.SetTo(&ref);
|
||||
}
|
||||
|
||||
// open_dir_hack
|
||||
static
|
||||
int
|
||||
open_dir_hack(const char *path)
|
||||
{
|
||||
DIR *dirHandle = opendir(path);
|
||||
if (!dirHandle)
|
||||
return errno;
|
||||
int dirFD = dirHandle->fd;
|
||||
if (dirFD < 0 || dirFD >= kFDTableSlotCount) {
|
||||
closedir(dirHandle);
|
||||
return B_ERROR;
|
||||
}
|
||||
free(dirHandle);
|
||||
sFDTable[dirFD] = FD_TYPE_DIR;
|
||||
return dirFD;
|
||||
}
|
||||
|
||||
// get_path
|
||||
static
|
||||
int
|
||||
get_path(int fd, const char *relPath, BPath &path)
|
||||
{
|
||||
if (fd < 0 || relPath && relPath[0] == '/')
|
||||
return path.SetTo(relPath);
|
||||
BDirectory dir;
|
||||
status_t error = init_dir(dir, fd);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
return path.SetTo(&dir, relPath);
|
||||
}
|
||||
|
||||
// _kern_open
|
||||
extern "C"
|
||||
int
|
||||
_kern_open(int fd, const char *path, int omode, int permissions)
|
||||
{
|
||||
status_t error;
|
||||
BPath fullPath;
|
||||
if (!path)
|
||||
path = ".";
|
||||
if (fd >= 0) {
|
||||
// construct the full path
|
||||
error = get_path(fd, path, fullPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
path = fullPath.Path();
|
||||
}
|
||||
// open the file
|
||||
int result = open(path, omode, permissions);
|
||||
if (result < 0)
|
||||
return errno;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// _kern_open_entry_ref
|
||||
extern "C"
|
||||
int
|
||||
_kern_open_entry_ref(dev_t device, ino_t inode, const char *name, int omode,
|
||||
int permissions)
|
||||
{
|
||||
BPath fullPath;
|
||||
node_ref ref;
|
||||
ref.device = device;
|
||||
ref.node = inode;
|
||||
// init the dir and get the path
|
||||
BDirectory dir;
|
||||
status_t error = dir.SetTo(&ref);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
error = fullPath.SetTo(&dir, name);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// open the file
|
||||
int fd = open(fullPath.Path(), omode, permissions);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
return fd;
|
||||
}
|
||||
|
||||
// _kern_open_dir
|
||||
extern "C"
|
||||
int
|
||||
_kern_open_dir(int fd, const char *path)
|
||||
{
|
||||
status_t error;
|
||||
BPath fullPath;
|
||||
if (fd >= 0) {
|
||||
if (!path)
|
||||
return _kern_dup(fd);
|
||||
// construct the full path
|
||||
error = get_path(fd, path, fullPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
path = fullPath.Path();
|
||||
}
|
||||
// open the dir
|
||||
return open_dir_hack(path);
|
||||
}
|
||||
|
||||
// _kern_open_dir_entry_ref
|
||||
extern "C"
|
||||
int
|
||||
_kern_open_dir_entry_ref(dev_t device, ino_t inode, const char *path)
|
||||
{
|
||||
BPath fullPath;
|
||||
node_ref ref;
|
||||
ref.device = device;
|
||||
ref.node = inode;
|
||||
// init the dir and get the path
|
||||
BDirectory dir;
|
||||
status_t error = dir.SetTo(&ref);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
error = fullPath.SetTo(&dir, path);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
path = fullPath.Path();
|
||||
// open the dir
|
||||
return open_dir_hack(path);
|
||||
}
|
||||
|
||||
// _kern_open_parent_dir
|
||||
extern "C"
|
||||
int
|
||||
_kern_open_parent_dir(int fd, char *name, size_t pathLength)
|
||||
{
|
||||
if (fd < 0)
|
||||
return B_BAD_VALUE;
|
||||
// get the dir
|
||||
BDirectory dir;
|
||||
status_t error = init_dir(dir, fd);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// get an entry
|
||||
BEntry entry;
|
||||
error = entry.SetTo(&dir, NULL);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// copy back the path
|
||||
if (name) {
|
||||
char tmpName[B_FILE_NAME_LENGTH];
|
||||
error = entry.GetName(tmpName);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (strlcpy(name, tmpName, pathLength) >= pathLength)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
}
|
||||
// get the parent dir path
|
||||
BPath path;
|
||||
error = path.SetTo(&dir, "..");
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// open the dir
|
||||
return open_dir_hack(path.Path());
|
||||
}
|
||||
|
||||
// _kern_open_query
|
||||
extern "C"
|
||||
int
|
||||
_kern_open_query(dev_t device, const char *query, size_t queryLength, uint32 flags, port_id port,
|
||||
int32 token)
|
||||
{
|
||||
// check params
|
||||
if (!query || queryLength == 0 || device < 0)
|
||||
return B_BAD_VALUE;
|
||||
if (flags & B_LIVE_QUERY && port < 0)
|
||||
return B_BAD_VALUE;
|
||||
// open query
|
||||
DIR *dirHandle;
|
||||
if (flags & B_LIVE_QUERY)
|
||||
dirHandle = fs_open_live_query(device, query, flags, port, token);
|
||||
else
|
||||
dirHandle = fs_open_query(device, query, flags);
|
||||
if (!dirHandle)
|
||||
return errno;
|
||||
// get FD and return result
|
||||
int dirFD = dirHandle->fd;
|
||||
if (dirFD < 0 || dirFD >= kFDTableSlotCount) {
|
||||
fs_close_query(dirHandle);
|
||||
return B_ERROR;
|
||||
}
|
||||
free(dirHandle);
|
||||
sFDTable[dirFD] = FD_TYPE_QUERY;
|
||||
return dirFD;
|
||||
}
|
||||
|
||||
// _kern_create_dir
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_create_dir(int fd, const char *path, int perms)
|
||||
{
|
||||
if (!path)
|
||||
return B_BAD_VALUE;
|
||||
status_t error;
|
||||
BPath fullPath;
|
||||
if (fd >= 0) {
|
||||
// construct the full path
|
||||
error = get_path(fd, path, fullPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
path = fullPath.Path();
|
||||
}
|
||||
// create the dir
|
||||
return (mkdir(path, perms) < 0 ? errno : B_OK);
|
||||
}
|
||||
|
||||
// _kern_create_symlink
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_create_symlink(int fd, const char *path, const char *toPath, int mode)
|
||||
{
|
||||
(void)mode;
|
||||
if (!path)
|
||||
return B_BAD_VALUE;
|
||||
status_t error;
|
||||
BPath fullPath;
|
||||
if (fd >= 0) {
|
||||
// construct the full path
|
||||
error = get_path(fd, path, fullPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
path = fullPath.Path();
|
||||
}
|
||||
// create the symlink
|
||||
return (symlink(toPath, path) < 0 ? errno : B_OK);
|
||||
}
|
||||
|
||||
// _kern_close
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_close(int fd)
|
||||
{
|
||||
if (fd >= 0 && fd < kFDTableSlotCount && sFDTable[fd] != FD_TYPE_UNKNOWN) {
|
||||
status_t error;
|
||||
switch (sFDTable[fd]) {
|
||||
case FD_TYPE_DIR:
|
||||
error = _kclosedir_(fd);
|
||||
break;
|
||||
case FD_TYPE_ATTR_DIR:
|
||||
error = _kclose_attr_dir_(fd);
|
||||
break;
|
||||
case FD_TYPE_QUERY:
|
||||
error = _kclose_query_(fd);
|
||||
break;
|
||||
default:
|
||||
error = B_BAD_VALUE;
|
||||
break;
|
||||
}
|
||||
sFDTable[fd] = FD_TYPE_UNKNOWN;
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
} else if (close(fd) < 0)
|
||||
return errno;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _kern_dup
|
||||
extern "C"
|
||||
int
|
||||
_kern_dup(int fd)
|
||||
{
|
||||
int clonedFD = dup(fd);
|
||||
if (clonedFD < 0)
|
||||
return errno;
|
||||
if (fd >= 0 && fd < kFDTableSlotCount && sFDTable[fd] != FD_TYPE_UNKNOWN
|
||||
&& clonedFD >= 0 && clonedFD < kFDTableSlotCount) {
|
||||
sFDTable[clonedFD] = sFDTable[fd];
|
||||
}
|
||||
return clonedFD;
|
||||
}
|
||||
|
||||
// _kern_read
|
||||
extern "C"
|
||||
ssize_t
|
||||
_kern_read(int fd, off_t pos, void *buffer, size_t bufferSize)
|
||||
{
|
||||
if (!buffer)
|
||||
return B_BAD_VALUE;
|
||||
ssize_t result;
|
||||
if (pos == -1)
|
||||
result = read(fd, buffer, bufferSize);
|
||||
else
|
||||
result = read_pos(fd, pos, buffer, bufferSize);
|
||||
return (result < 0 ? errno : result);
|
||||
}
|
||||
|
||||
// _kern_write
|
||||
extern "C"
|
||||
ssize_t
|
||||
_kern_write(int fd, off_t pos, const void *buffer, size_t bufferSize)
|
||||
{
|
||||
if (!buffer)
|
||||
return B_BAD_VALUE;
|
||||
ssize_t result;
|
||||
if (pos == -1)
|
||||
result = write(fd, buffer, bufferSize);
|
||||
else
|
||||
result = write_pos(fd, pos, buffer, bufferSize);
|
||||
return (result < 0 ? errno : result);
|
||||
}
|
||||
|
||||
// _kern_seek
|
||||
extern "C"
|
||||
off_t
|
||||
_kern_seek(int fd, off_t pos, int seekType)
|
||||
{
|
||||
off_t result = lseek(fd, pos, seekType);
|
||||
return (result < 0 ? errno : result);
|
||||
}
|
||||
|
||||
// _kern_read_dir
|
||||
extern "C"
|
||||
ssize_t
|
||||
_kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize,
|
||||
uint32 maxCount)
|
||||
{
|
||||
if (fd < 0 || !buffer)
|
||||
return B_BAD_VALUE;
|
||||
if (fd >= kFDTableSlotCount || sFDTable[fd] == FD_TYPE_UNKNOWN)
|
||||
return B_BAD_VALUE;
|
||||
if (maxCount < 1)
|
||||
return 0;
|
||||
char tmpBuffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
|
||||
DIR *dirDir = (DIR*)tmpBuffer;
|
||||
dirDir->fd = fd;
|
||||
dirent *entry = NULL;
|
||||
switch (sFDTable[fd]) {
|
||||
case FD_TYPE_DIR:
|
||||
entry = readdir(dirDir);
|
||||
break;
|
||||
case FD_TYPE_ATTR_DIR:
|
||||
entry = fs_read_attr_dir(dirDir);
|
||||
break;
|
||||
case FD_TYPE_QUERY:
|
||||
entry = fs_read_query(dirDir);
|
||||
break;
|
||||
}
|
||||
if (!entry)
|
||||
return 0;
|
||||
// Don't trust entry->d_reclen.
|
||||
// Unlike stated in BeBook::BEntryList, the value is not the length
|
||||
// of the whole structure, but only of the name. Some FSs count
|
||||
// the terminating '\0', others don't.
|
||||
// So we calculate the size ourselves (including the '\0'):
|
||||
size_t entryLen = entry->d_name + strlen(entry->d_name) + 1
|
||||
- (char*)entry;
|
||||
if (bufferSize >= entryLen) {
|
||||
memcpy(buffer, entry, entryLen);
|
||||
return 1;
|
||||
} else // buffer too small
|
||||
return B_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
// _kern_rewind_dir
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_rewind_dir(int fd)
|
||||
{
|
||||
if (fd < 0 || fd >= kFDTableSlotCount || sFDTable[fd] == FD_TYPE_UNKNOWN)
|
||||
return B_BAD_VALUE;
|
||||
char tmpBuffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
|
||||
DIR *dirDir = (DIR*)tmpBuffer;
|
||||
dirDir->fd = fd;
|
||||
switch (sFDTable[fd]) {
|
||||
case FD_TYPE_DIR:
|
||||
rewinddir(dirDir);
|
||||
break;
|
||||
case FD_TYPE_ATTR_DIR:
|
||||
fs_rewind_attr_dir(dirDir);
|
||||
break;
|
||||
case FD_TYPE_QUERY:
|
||||
return B_BAD_VALUE;
|
||||
break;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _kern_read_link
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize)
|
||||
{
|
||||
ssize_t result = _kreadlink_(fd, path, buffer, *_bufferSize);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
buffer[result] = '\0';
|
||||
*_bufferSize = result;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _kern_unlink
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_unlink(int fd, const char *relPath)
|
||||
{
|
||||
BPath path;
|
||||
status_t error = get_path(fd, relPath, path);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (unlink(path.Path()) < 0) {
|
||||
error = errno;
|
||||
if (error == B_IS_A_DIRECTORY) {
|
||||
if (rmdir(path.Path()) < 0)
|
||||
return errno;
|
||||
} else
|
||||
return error;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _kern_rename
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_rename(int oldDir, const char *oldRelPath, int newDir,
|
||||
const char *newRelPath)
|
||||
{
|
||||
// get old path
|
||||
BPath oldPath;
|
||||
status_t error = get_path(oldDir, oldRelPath, oldPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// get new path
|
||||
BPath newPath;
|
||||
error = get_path(newDir, newRelPath, newPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// rename
|
||||
if (rename(oldPath.Path(), newPath.Path()) < 0)
|
||||
return errno;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// _kern_read_stat
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_read_stat(int fd, const char *path, bool traverseLink, struct stat *st,
|
||||
size_t statSize)
|
||||
{
|
||||
if (traverseLink)
|
||||
return B_ERROR; // unsupported
|
||||
return _krstat_(fd, path, st, 0);
|
||||
}
|
||||
|
||||
// _kern_write_stat
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_write_stat(int fd, const char *path, bool traverseLink,
|
||||
const struct stat *st, size_t statSize, int statMask)
|
||||
{
|
||||
if (traverseLink)
|
||||
return B_ERROR; // unsupported
|
||||
return _kwstat_(fd, path, st, statMask, 0);
|
||||
}
|
||||
|
||||
// _kern_lock_node
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_lock_node(int fd)
|
||||
{
|
||||
return _klock_node_(fd);
|
||||
}
|
||||
|
||||
// _kern_unlock_node
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_unlock_node(int fd)
|
||||
{
|
||||
return _kunlock_node_(fd);
|
||||
}
|
||||
|
||||
// _kern_fsync
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_fsync(int fd)
|
||||
{
|
||||
return (fsync(fd) < 0) ? errno : B_OK ;
|
||||
}
|
||||
|
||||
// _kern_open_attr_dir
|
||||
extern "C"
|
||||
int
|
||||
_kern_open_attr_dir(int fd, const char *path)
|
||||
{
|
||||
if (fd < 0 && !path)
|
||||
return B_BAD_VALUE;
|
||||
if (fd >= 0 && path)
|
||||
return B_ERROR; // unsupported
|
||||
DIR *dirHandle = (fd >= 0 ? fs_fopen_attr_dir(fd) : fs_open_attr_dir(path));
|
||||
if (!dirHandle)
|
||||
return errno;
|
||||
int dirFD = dirHandle->fd;
|
||||
if (dirFD < 0 || dirFD >= kFDTableSlotCount) {
|
||||
fs_close_attr_dir(dirHandle);
|
||||
return B_ERROR;
|
||||
}
|
||||
free(dirHandle);
|
||||
sFDTable[dirFD] = FD_TYPE_ATTR_DIR;
|
||||
return dirFD;
|
||||
}
|
||||
|
||||
// _kern_remove_attr
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_remove_attr(int fd, const char *name)
|
||||
{
|
||||
return fs_remove_attr(fd, name) == -1 ? errno : B_OK ;
|
||||
}
|
||||
|
||||
// _kern_rename_attr
|
||||
extern "C"
|
||||
status_t
|
||||
_kern_rename_attr(int fromFile, const char *fromName, int toFile,
|
||||
const char *toName)
|
||||
{
|
||||
status_t error = (fromName && toName ? B_OK : B_BAD_VALUE);
|
||||
// Figure out how much data there is
|
||||
attr_info info;
|
||||
if (error == B_OK) {
|
||||
if (fs_stat_attr(fromFile, fromName, &info) < 0)
|
||||
error = B_BAD_VALUE; // This is what R5::BNode returns...
|
||||
}
|
||||
// Alloc a buffer
|
||||
char *data = NULL;
|
||||
if (error == B_OK) {
|
||||
// alloc at least one byte
|
||||
data = new(nothrow) char[info.size >= 1 ? info.size : 1];
|
||||
if (data == NULL)
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
// Read in the data
|
||||
if (error == B_OK) {
|
||||
ssize_t size = fs_read_attr(fromFile, fromName, info.type, 0, data,
|
||||
info.size);
|
||||
if (size != info.size) {
|
||||
if (size < 0)
|
||||
error = errno;
|
||||
else
|
||||
error = B_ERROR;
|
||||
}
|
||||
}
|
||||
// Write it to the new attribute
|
||||
if (error == B_OK) {
|
||||
ssize_t size = 0;
|
||||
if (info.size > 0)
|
||||
size = fs_write_attr(toFile, toName, info.type, 0, data, info.size);
|
||||
if (size != info.size) {
|
||||
if (size < 0)
|
||||
error = errno;
|
||||
else
|
||||
error = B_ERROR;
|
||||
}
|
||||
}
|
||||
// free the buffer
|
||||
if (data)
|
||||
delete[] data;
|
||||
// Remove the old attribute
|
||||
if (error == B_OK)
|
||||
error = _kern_remove_attr(fromFile, fromName);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
extern "C" status_t
|
||||
_kern_get_safemode_option(const char *parameter, char *buffer, size_t *_bufferSize)
|
||||
{
|
||||
return _kget_safemode_option_(parameter, buffer, _bufferSize);
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
Notes concerning the OpenBeOS implementation of BNode:
|
||||
1. GetNextAttrName returns B_BAD_VALUE when passed a NULL pointer instead of crashing
|
||||
2. R5::BNode returns B_BAD_ADDRESS when RewindAttrs() fails (not B_FILE_ERROR as claimed in the BeBook). We currently follow suit.
|
||||
3. RenameAttr() actually works, whereas the R5 version doesn't (apparently because BFS doesn't implement it directly...).
|
||||
4. Write/ReadAttrString() functions need to be documented (they aren't in the R5 BeBook).
|
||||
5. ReadAttrString() adds an extra NULL char to the end of the string it reads as a precaution before handing it back to the BString result, since it's possible to read a non-NULL-terminated string of characters from an attribute.
|
||||
6. Write/ReadAttrString() can't be tested until we have an OpenBeOS implementation of BString.
|
||||
7. Dup() should be declared const, but it isn't by R5, so our implementation follows suit.
|
||||
8. Locking is not supported by the Posix implemention of OpenBeOS BNode, due to fcntl(fd, F_SETLK, ...) not being implemented in R5.
|
||||
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <AppMisc.h>
|
||||
#include <Looper.h>
|
||||
#include <Messenger.h>
|
||||
#include <NodeMonitor.h>
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
// TODO: Tests!
|
||||
|
||||
|
||||
// watch_node
|
||||
/*! \brief Subscribes a target to node and/or mount watching, or unsubscribes
|
||||
it from node watching.
|
||||
|
||||
Depending of \a flags the action performed by this function varies:
|
||||
- \a flags is \c 0: The target is unsubscribed from watching the node.
|
||||
\a node must not be \c NULL in this case.
|
||||
- \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount
|
||||
watching.
|
||||
- \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT,
|
||||
\c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to
|
||||
watching the specified aspects of the node. \a node must not be \c NULL
|
||||
in this case.
|
||||
|
||||
Note, that the latter two cases are not mutual exlusive, i.e. mount and
|
||||
node watching can be requested with a single call.
|
||||
|
||||
\param node node_ref referring to the node to be watched. May be \c NULL,
|
||||
if only mount watching is requested.
|
||||
\param flags Flags indicating the actions to be performed.
|
||||
\param target Messenger referring to the target. Must be valid.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
watch_node(const node_ref *node, uint32 flags, BMessenger target)
|
||||
{
|
||||
status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
BLooper *looper = NULL;
|
||||
BHandler *handler = target.Target(&looper);
|
||||
error = watch_node(node, flags, handler, looper);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// watch_node
|
||||
/*! \brief Subscribes a target to node and/or mount watching, or unsubscribes
|
||||
it from node watching.
|
||||
|
||||
Depending of \a flags the action performed by this function varies:
|
||||
- \a flags is \c 0: The target is unsubscribed from watching the node.
|
||||
\a node must not be \c NULL in this case.
|
||||
- \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount
|
||||
watching.
|
||||
- \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT,
|
||||
\c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to
|
||||
watching the specified aspects of the node. \a node must not be \c NULL
|
||||
in this case.
|
||||
|
||||
Note, that the latter two cases are not mutual exlusive, i.e. mount and
|
||||
node watching can be requested with a single call.
|
||||
|
||||
\param node node_ref referring to the node to be watched. May be \c NULL,
|
||||
if only mount watching is requested.
|
||||
\param flags Flags indicating the actions to be performed.
|
||||
\param handler The target handler. May be \c NULL, if \a looper is not
|
||||
\c NULL. Then the preferred handler of the looper is targeted.
|
||||
\param looper The target looper. May be \c NULL, if \a handler is not
|
||||
\c NULL. Then the handler's looper is the target looper.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
watch_node(const node_ref *node, uint32 flags, const BHandler *handler,
|
||||
const BLooper *looper)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// check looper and handler and get the handler token
|
||||
int32 handlerToken = -2;
|
||||
if (handler) {
|
||||
handlerToken = _get_object_token_(handler);
|
||||
if (looper) {
|
||||
if (looper != handler->Looper())
|
||||
error = B_BAD_VALUE;
|
||||
} else {
|
||||
looper = handler->Looper();
|
||||
if (!looper)
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
} else if (!looper)
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK) {
|
||||
port_id port = _get_looper_port_(looper);
|
||||
if (flags == B_STOP_WATCHING) {
|
||||
// unsubscribe from node node watching
|
||||
if (node)
|
||||
error = _kern_stop_watching(node->device, node->node, flags, port, handlerToken);
|
||||
else
|
||||
error = B_BAD_VALUE;
|
||||
} else {
|
||||
// subscribe to...
|
||||
// mount watching
|
||||
if (flags & B_WATCH_MOUNT) {
|
||||
error = _kern_start_watching((dev_t)-1, (ino_t)-1, 0, port, handlerToken);
|
||||
flags &= ~B_WATCH_MOUNT;
|
||||
}
|
||||
// node watching
|
||||
if (error == B_OK && flags)
|
||||
error = _kern_start_watching(node->device, node->node, flags, port, handlerToken);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// stop_watching
|
||||
/*! \brief Unsubscribes a target from node and mount monitoring.
|
||||
\param target Messenger referring to the target. Must be valid.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
stop_watching(BMessenger target)
|
||||
{
|
||||
status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
BLooper *looper = NULL;
|
||||
BHandler *handler = target.Target(&looper);
|
||||
error = stop_watching(handler, looper);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// stop_watching
|
||||
/*! \brief Unsubscribes a target from node and mount monitoring.
|
||||
\param handler The target handler. May be \c NULL, if \a looper is not
|
||||
\c NULL. Then the preferred handler of the looper is targeted.
|
||||
\param looper The target looper. May be \c NULL, if \a handler is not
|
||||
\c NULL. Then the handler's looper is the target looper.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
stop_watching(const BHandler *handler, const BLooper *looper)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// check looper and handler and get the handler token
|
||||
int32 handlerToken = -2;
|
||||
if (handler) {
|
||||
handlerToken = _get_object_token_(handler);
|
||||
if (looper) {
|
||||
if (looper != handler->Looper())
|
||||
error = B_BAD_VALUE;
|
||||
} else {
|
||||
looper = handler->Looper();
|
||||
if (!looper)
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
} else if (!looper)
|
||||
error = B_BAD_VALUE;
|
||||
// unsubscribe
|
||||
if (error == B_OK) {
|
||||
port_id port = _get_looper_port_(looper);
|
||||
error = _kern_stop_notifying(port, handlerToken);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
@ -1,250 +0,0 @@
|
|||
#include "NodeMonitorHandler.h"
|
||||
|
||||
/*
|
||||
* static util functions for the super lazy
|
||||
*/
|
||||
|
||||
|
||||
/* static */ status_t
|
||||
NodeMonitorHandler::make_entry_ref(dev_t device, ino_t directory,
|
||||
const char * name,
|
||||
entry_ref * ref)
|
||||
{
|
||||
ref->device = device;
|
||||
ref->directory = directory;
|
||||
return ref->set_name(name);
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
NodeMonitorHandler::make_node_ref(dev_t device, ino_t node, node_ref * ref)
|
||||
{
|
||||
ref->device = device;
|
||||
ref->node = node;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* public functions: constructor, destructor, MessageReceived
|
||||
*/
|
||||
|
||||
NodeMonitorHandler::NodeMonitorHandler(const char * name)
|
||||
: BHandler(name)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
NodeMonitorHandler::~NodeMonitorHandler()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::MessageReceived(BMessage * msg)
|
||||
{
|
||||
status_t status = B_MESSAGE_NOT_UNDERSTOOD;
|
||||
if (msg->what == B_NODE_MONITOR) {
|
||||
int32 opcode;
|
||||
if (msg->FindInt32("opcode", &opcode) == B_OK) {
|
||||
switch (opcode) {
|
||||
case B_ENTRY_CREATED:
|
||||
status = HandleEntryCreated(msg);
|
||||
break;
|
||||
case B_ENTRY_REMOVED:
|
||||
status = HandleEntryRemoved(msg);
|
||||
break;
|
||||
case B_ENTRY_MOVED:
|
||||
status = HandleEntryMoved(msg);
|
||||
break;
|
||||
case B_STAT_CHANGED:
|
||||
status = HandleStatChanged(msg);
|
||||
break;
|
||||
case B_ATTR_CHANGED:
|
||||
status = HandleAttrChanged(msg);
|
||||
break;
|
||||
case B_DEVICE_MOUNTED:
|
||||
status = HandleDeviceMounted(msg);
|
||||
break;
|
||||
case B_DEVICE_UNMOUNTED:
|
||||
status = HandleDeviceUnmounted(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status == B_MESSAGE_NOT_UNDERSTOOD) {
|
||||
inherited::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* default virtual functions do nothing
|
||||
*/
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::EntryCreated(const char *name, ino_t directory,
|
||||
dev_t device, ino_t node)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::EntryRemoved(ino_t directory, dev_t device, ino_t node)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::EntryMoved(const char *name, ino_t from_directory,
|
||||
ino_t to_directory, dev_t device, ino_t node)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::StatChanged(ino_t node, dev_t device)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::AttrChanged(ino_t node, dev_t device)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::DeviceMounted(dev_t new_device, dev_t device,
|
||||
ino_t directory)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void
|
||||
NodeMonitorHandler::DeviceUnmounted(dev_t new_device)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* private functions to rip apart the corresponding BMessage
|
||||
*/
|
||||
|
||||
status_t
|
||||
NodeMonitorHandler::HandleEntryCreated(BMessage * msg)
|
||||
{
|
||||
const char *name;
|
||||
ino_t directory;
|
||||
dev_t device;
|
||||
ino_t node;
|
||||
if ((msg->FindString("name", &name) != B_OK) ||
|
||||
(msg->FindInt64("directory", &directory) != B_OK) ||
|
||||
(msg->FindInt32("device", &device) != B_OK) ||
|
||||
(msg->FindInt64("node", &node) != B_OK)) {
|
||||
return B_MESSAGE_NOT_UNDERSTOOD;
|
||||
}
|
||||
EntryCreated(name, directory, device, node);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NodeMonitorHandler::HandleEntryRemoved(BMessage * msg)
|
||||
{
|
||||
ino_t directory;
|
||||
dev_t device;
|
||||
ino_t node;
|
||||
if ((msg->FindInt64("directory", &directory) != B_OK) ||
|
||||
(msg->FindInt32("device", &device) != B_OK) ||
|
||||
(msg->FindInt64("node", &node) != B_OK)) {
|
||||
return B_MESSAGE_NOT_UNDERSTOOD;
|
||||
}
|
||||
EntryRemoved(directory, device, node);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NodeMonitorHandler::HandleEntryMoved(BMessage * msg)
|
||||
{
|
||||
const char *name;
|
||||
ino_t from_directory;
|
||||
ino_t to_directory;
|
||||
dev_t device;
|
||||
ino_t node;
|
||||
if ((msg->FindString("name", &name) != B_OK) ||
|
||||
(msg->FindInt64("from directory", &from_directory) != B_OK) ||
|
||||
(msg->FindInt64("to directory", &to_directory) != B_OK) ||
|
||||
(msg->FindInt32("device", &device) != B_OK) ||
|
||||
(msg->FindInt64("node", &node) != B_OK)) {
|
||||
return B_MESSAGE_NOT_UNDERSTOOD;
|
||||
}
|
||||
EntryMoved(name, from_directory, to_directory, device, node);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NodeMonitorHandler::HandleStatChanged(BMessage * msg)
|
||||
{
|
||||
ino_t node;
|
||||
dev_t device;
|
||||
if ((msg->FindInt64("node", &node) != B_OK) ||
|
||||
(msg->FindInt32("device", &device) != B_OK)) {
|
||||
return B_MESSAGE_NOT_UNDERSTOOD;
|
||||
}
|
||||
StatChanged(node, device);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NodeMonitorHandler::HandleAttrChanged(BMessage * msg)
|
||||
{
|
||||
ino_t node;
|
||||
dev_t device;
|
||||
if ((msg->FindInt64("node", &node) != B_OK) ||
|
||||
(msg->FindInt32("device", &device) != B_OK)) {
|
||||
return B_MESSAGE_NOT_UNDERSTOOD;
|
||||
}
|
||||
AttrChanged(node, device);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NodeMonitorHandler::HandleDeviceMounted(BMessage * msg)
|
||||
{
|
||||
dev_t new_device;
|
||||
dev_t device;
|
||||
ino_t directory;
|
||||
if ((msg->FindInt32("new device", &new_device) != B_OK) ||
|
||||
(msg->FindInt32("device", &device) != B_OK) ||
|
||||
(msg->FindInt64("directory", &directory) != B_OK)) {
|
||||
return B_MESSAGE_NOT_UNDERSTOOD;
|
||||
}
|
||||
DeviceMounted(new_device, device, directory);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NodeMonitorHandler::HandleDeviceUnmounted(BMessage * msg)
|
||||
{
|
||||
dev_t new_device;
|
||||
if (msg->FindInt32("new device", &new_device) != B_OK) {
|
||||
return B_MESSAGE_NOT_UNDERSTOOD;
|
||||
}
|
||||
DeviceUnmounted(new_device);
|
||||
return B_OK;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,195 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <algobase.h>
|
||||
#include <new.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Button.h>
|
||||
#include <DiskScannerAddOn.h>
|
||||
#include <Screen.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "PartitioningDialog.h"
|
||||
|
||||
enum {
|
||||
MSG_OK = 'okay',
|
||||
MSG_CANCEL = 'cncl',
|
||||
};
|
||||
|
||||
// constructor
|
||||
PartitioningDialog::PartitioningDialog(BRect dialogCenter)
|
||||
: BWindow(BRect(100, 100, 100, 100), "Partitioning Parameters",
|
||||
B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE),
|
||||
fEditor(NULL),
|
||||
fEditorView(NULL),
|
||||
fBlocker(-1),
|
||||
fCancelled(NULL),
|
||||
fCenter()
|
||||
{
|
||||
fBlocker = create_sem(0, "partitioning dialog blocker");
|
||||
// calculate the dialog center point
|
||||
if (!dialogCenter.IsValid())
|
||||
dialogCenter = BScreen().Frame();
|
||||
fCenter = dialogCenter.LeftTop() + dialogCenter.RightBottom();
|
||||
fCenter.x /= 2;
|
||||
fCenter.y /= 2;
|
||||
}
|
||||
|
||||
// destructor
|
||||
PartitioningDialog::~PartitioningDialog()
|
||||
{
|
||||
if (fEditorView)
|
||||
fEditorView->RemoveSelf();
|
||||
if (fBlocker >= 0)
|
||||
delete_sem(fBlocker);
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
PartitioningDialog::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_OK:
|
||||
{
|
||||
if (fEditor->EditingDone()) {
|
||||
if (fCancelled)
|
||||
*fCancelled = false;
|
||||
Quit();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_CANCEL:
|
||||
if (fCancelled)
|
||||
*fCancelled = true;
|
||||
Quit();
|
||||
break;
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// QuitRequested
|
||||
bool
|
||||
PartitioningDialog::QuitRequested()
|
||||
{
|
||||
if (fCancelled)
|
||||
*fCancelled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Go
|
||||
status_t
|
||||
PartitioningDialog::Go(BDiskScannerParameterEditor *editor, bool *_cancelled)
|
||||
{
|
||||
status_t error = _Init(editor);
|
||||
bool wasRun = false;
|
||||
// fire up the window
|
||||
if (error == B_OK) {
|
||||
if (fBlocker >= 0) {
|
||||
sem_id blocker = fBlocker;
|
||||
bool cancelled = true;
|
||||
fCancelled = &cancelled;
|
||||
Show();
|
||||
wasRun = true;
|
||||
acquire_sem(blocker);
|
||||
if (cancelled)
|
||||
error = B_ERROR;
|
||||
if (_cancelled)
|
||||
*_cancelled = cancelled;
|
||||
} else
|
||||
error = fBlocker;
|
||||
}
|
||||
// delete the window if not run
|
||||
if (!wasRun)
|
||||
delete this;
|
||||
return error;
|
||||
}
|
||||
|
||||
// _Init
|
||||
status_t
|
||||
PartitioningDialog::_Init(BDiskScannerParameterEditor *editor)
|
||||
{
|
||||
status_t error = (editor ? B_OK : B_BAD_VALUE);
|
||||
// set the parameter editor and view
|
||||
if (error == B_OK) {
|
||||
fEditor = editor;
|
||||
fEditorView = editor->View();
|
||||
if (!fEditorView)
|
||||
error = B_ERROR;
|
||||
}
|
||||
// setup views
|
||||
if (error == B_OK) {
|
||||
BView *mainView = new(nothrow) BView(BRect(0, 0, 1, 1), "main",
|
||||
B_FOLLOW_ALL, 0);
|
||||
BMessage *okMessage = new BMessage(MSG_OK);
|
||||
BMessage *cancelMessage = new BMessage(MSG_CANCEL);
|
||||
BButton *okButton = new (nothrow) BButton(
|
||||
BRect(0, 0, 1, 1), "ok", "OK", okMessage,
|
||||
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
||||
BButton *cancelButton = new (nothrow) BButton(
|
||||
BRect(0, 0, 1, 1), "cancel", "Cancel", cancelMessage,
|
||||
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
||||
if (okMessage && cancelMessage && okButton && cancelButton) {
|
||||
// add the views to the hierarchy
|
||||
mainView->AddChild(fEditorView);
|
||||
mainView->AddChild(okButton);
|
||||
mainView->AddChild(cancelButton);
|
||||
AddChild(mainView);
|
||||
// set the buttons' preferred size
|
||||
float buttonWidth = 0;
|
||||
float buttonHeight = 0;
|
||||
okButton->GetPreferredSize(&buttonWidth, &buttonHeight);
|
||||
okButton->ResizeTo(buttonWidth, buttonHeight);
|
||||
cancelButton->GetPreferredSize(&buttonWidth, &buttonHeight);
|
||||
cancelButton->ResizeTo(buttonWidth, buttonHeight);
|
||||
// setup their positions and sizes
|
||||
int32 hSpacing = 10;
|
||||
int32 vSpacing = 10;
|
||||
BRect editorRect = fEditorView->Bounds();
|
||||
BRect okRect = okButton->Bounds();
|
||||
BRect cancelRect = cancelButton->Bounds();
|
||||
// compute width and size of the main view
|
||||
int32 width = max(editorRect.IntegerWidth() + 1,
|
||||
okRect.IntegerWidth() + 1 + hSpacing
|
||||
+ cancelRect.IntegerWidth() + 1)
|
||||
+ 2 * hSpacing;
|
||||
int32 height = editorRect.IntegerHeight() + 1
|
||||
+ max(okRect.IntegerHeight(),
|
||||
cancelRect.IntegerHeight()) + 1
|
||||
+ 3 * vSpacing;
|
||||
mainView->ResizeTo(width - 1, height -1);
|
||||
ResizeTo(width - 1, height -1);
|
||||
// set location of the editor view
|
||||
fEditorView->MoveTo((width - editorRect.IntegerWidth() - 1) / 2,
|
||||
vSpacing - 1);
|
||||
fEditorView->ResizeTo(editorRect.Width(), editorRect.Height());
|
||||
// set the location of the buttons
|
||||
float buttonTop = 2 * vSpacing + editorRect.IntegerHeight();
|
||||
float buttonLeft = width - hSpacing - okRect.IntegerWidth();
|
||||
okButton->MoveTo(buttonLeft, buttonTop);
|
||||
buttonLeft -= hSpacing + cancelRect.IntegerWidth();
|
||||
cancelButton->MoveTo(buttonLeft, buttonTop);
|
||||
} else {
|
||||
// cleanup on error
|
||||
error = B_NO_MEMORY;
|
||||
if (!okButton && okMessage)
|
||||
delete okMessage;
|
||||
if (!cancelButton && cancelMessage)
|
||||
delete cancelMessage;
|
||||
if (okButton)
|
||||
delete okButton;
|
||||
if (cancelButton)
|
||||
delete cancelButton;
|
||||
if (mainView)
|
||||
delete mainView;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#ifndef _PARTITIONING_DIALOG_H
|
||||
#define _PARTITIONING_DIALOG_H
|
||||
|
||||
#include <OS.h>
|
||||
#include <Window.h>
|
||||
|
||||
class BDiskScannerParameterEditor;
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
class PartitioningDialog : public BWindow {
|
||||
public:
|
||||
PartitioningDialog(BRect dialogCenter);
|
||||
virtual ~PartitioningDialog();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
status_t Go(BDiskScannerParameterEditor *editor, bool *cancelled);
|
||||
|
||||
private:
|
||||
status_t _Init(BDiskScannerParameterEditor *editor);
|
||||
|
||||
private:
|
||||
BDiskScannerParameterEditor *fEditor;
|
||||
BView *fEditorView;
|
||||
sem_id fBlocker;
|
||||
bool *fCancelled;
|
||||
BPoint fCenter;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
using BPrivate::PartitioningDialog;
|
||||
|
||||
#endif // _PARTITIONING_DIALOG_H
|
|
@ -1,96 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
#include <PartitioningInfo.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// constructor
|
||||
BPartitioningInfo::BPartitioningInfo()
|
||||
: fPartitionID(-1),
|
||||
fSpaces(NULL),
|
||||
fCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
BPartitioningInfo::~BPartitioningInfo()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
BPartitioningInfo::Unset()
|
||||
{
|
||||
delete[] fSpaces;
|
||||
fPartitionID = -1;
|
||||
fSpaces = NULL;
|
||||
fCount = 0;
|
||||
}
|
||||
|
||||
// PartitionID
|
||||
partition_id
|
||||
BPartitioningInfo::PartitionID() const
|
||||
{
|
||||
return fPartitionID;
|
||||
}
|
||||
|
||||
// GetPartitionableSpaceAt
|
||||
status_t
|
||||
BPartitioningInfo::GetPartitionableSpaceAt(int32 index, off_t *offset,
|
||||
off_t *size) const
|
||||
{
|
||||
if (!fSpaces || !offset || !size || index < 0 || index >= fCount)
|
||||
return B_BAD_VALUE;
|
||||
*offset = fSpaces[index].offset;
|
||||
*size = fSpaces[index].size;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// CountPartitionableSpaces
|
||||
int32
|
||||
BPartitioningInfo::CountPartitionableSpaces() const
|
||||
{
|
||||
return fCount;
|
||||
}
|
||||
|
||||
// _SetTo
|
||||
status_t
|
||||
BPartitioningInfo::_SetTo(partition_id partition, int32 changeCounter)
|
||||
{
|
||||
Unset();
|
||||
status_t error = B_OK;
|
||||
partitionable_space_data *buffer = NULL;
|
||||
int32 count = 0;
|
||||
int32 actualCount = 0;
|
||||
do {
|
||||
error = _kern_get_partitionable_spaces(partition, changeCounter,
|
||||
buffer, count, &actualCount);
|
||||
if (error == B_BUFFER_OVERFLOW) {
|
||||
// buffer to small re-allocate it
|
||||
if (buffer)
|
||||
delete[] buffer;
|
||||
buffer = new(nothrow) partitionable_space_data[actualCount];
|
||||
if (buffer)
|
||||
count = actualCount;
|
||||
else
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
} while (error == B_BUFFER_OVERFLOW);
|
||||
// set data / cleanup on failure
|
||||
if (error == B_OK) {
|
||||
fPartitionID = partition;
|
||||
fSpaces = buffer;
|
||||
fCount = actualCount;
|
||||
} else if (buffer)
|
||||
delete[] buffer;
|
||||
return error;
|
||||
}
|
||||
|
|
@ -1,776 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the Haiku distribution and is covered
|
||||
// by the MIT license.
|
||||
//---------------------------------------------------------------------
|
||||
/*!
|
||||
\file Query.cpp
|
||||
BQuery implementation.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <new>
|
||||
#include <parsedate.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <Entry.h>
|
||||
#include <fs_query.h>
|
||||
#include <Query.h>
|
||||
#include <Volume.h>
|
||||
|
||||
#include <MessengerPrivate.h>
|
||||
#include <syscalls.h>
|
||||
|
||||
#include "QueryPredicate.h"
|
||||
#include "storage_support.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace BPrivate::Storage;
|
||||
|
||||
// BQuery
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates an uninitialized BQuery.
|
||||
*/
|
||||
BQuery::BQuery()
|
||||
: BEntryList(),
|
||||
fStack(NULL),
|
||||
fPredicate(NULL),
|
||||
fDevice((dev_t)B_ERROR),
|
||||
fLive(false),
|
||||
fPort(B_ERROR),
|
||||
fToken(0),
|
||||
fQueryFd(-1)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with the object.
|
||||
*/
|
||||
BQuery::~BQuery()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
// Clear
|
||||
/*! \brief Resets the object to a uninitialized state.
|
||||
\return \c B_OK
|
||||
*/
|
||||
status_t
|
||||
BQuery::Clear()
|
||||
{
|
||||
// close the currently open query
|
||||
status_t error = B_OK;
|
||||
if (fQueryFd >= 0) {
|
||||
error = _kern_close(fQueryFd);
|
||||
fQueryFd = -1;
|
||||
}
|
||||
// delete the predicate stack and the predicate
|
||||
delete fStack;
|
||||
fStack = NULL;
|
||||
delete[] fPredicate;
|
||||
fPredicate = NULL;
|
||||
// reset the other parameters
|
||||
fDevice = (dev_t)B_ERROR;
|
||||
fLive = false;
|
||||
fPort = B_ERROR;
|
||||
fToken = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
// PushAttr
|
||||
/*! \brief Pushes an attribute name onto the BQuery's predicate stack.
|
||||
\param attrName the attribute name
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushAttribute() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushAttr(const char *attrName)
|
||||
{
|
||||
return _PushNode(new(nothrow) AttributeNode(attrName), true);
|
||||
}
|
||||
|
||||
// PushOp
|
||||
/*! \brief Pushes an operator onto the BQuery's predicate stack.
|
||||
\param op the code representing the operator
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushOp() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushOp(query_op op)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
switch (op) {
|
||||
case B_EQ:
|
||||
case B_GT:
|
||||
case B_GE:
|
||||
case B_LT:
|
||||
case B_LE:
|
||||
case B_NE:
|
||||
case B_CONTAINS:
|
||||
case B_BEGINS_WITH:
|
||||
case B_ENDS_WITH:
|
||||
case B_AND:
|
||||
case B_OR:
|
||||
error = _PushNode(new(nothrow) BinaryOpNode(op), true);
|
||||
break;
|
||||
case B_NOT:
|
||||
error = _PushNode(new(nothrow) UnaryOpNode(op), true);
|
||||
break;
|
||||
default:
|
||||
error = _PushNode(new(nothrow) SpecialOpNode(op), true);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// PushUInt32
|
||||
/*! \brief Pushes a uint32 value onto the BQuery's predicate stack.
|
||||
\param value the value
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushUInt32() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushUInt32(uint32 value)
|
||||
{
|
||||
return _PushNode(new(nothrow) UInt32ValueNode(value), true);
|
||||
}
|
||||
|
||||
// PushInt32
|
||||
/*! \brief Pushes an int32 value onto the BQuery's predicate stack.
|
||||
\param value the value
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushInt32() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushInt32(int32 value)
|
||||
{
|
||||
return _PushNode(new(nothrow) Int32ValueNode(value), true);
|
||||
}
|
||||
|
||||
// PushUInt64
|
||||
/*! \brief Pushes a uint64 value onto the BQuery's predicate stack.
|
||||
\param value the value
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushUInt64() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushUInt64(uint64 value)
|
||||
{
|
||||
return _PushNode(new(nothrow) UInt64ValueNode(value), true);
|
||||
}
|
||||
|
||||
// PushInt64
|
||||
/*! \brief Pushes an int64 value onto the BQuery's predicate stack.
|
||||
\param value the value
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushInt64() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushInt64(int64 value)
|
||||
{
|
||||
return _PushNode(new(nothrow) Int64ValueNode(value), true);
|
||||
}
|
||||
|
||||
// PushFloat
|
||||
/*! \brief Pushes a float value onto the BQuery's predicate stack.
|
||||
\param value the value
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushFloat() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushFloat(float value)
|
||||
{
|
||||
return _PushNode(new(nothrow) FloatValueNode(value), true);
|
||||
}
|
||||
|
||||
// PushDouble
|
||||
/*! \brief Pushes a double value onto the BQuery's predicate stack.
|
||||
\param value the value
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushDouble() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushDouble(double value)
|
||||
{
|
||||
return _PushNode(new(nothrow) DoubleValueNode(value), true);
|
||||
}
|
||||
|
||||
// PushString
|
||||
/*! \brief Pushes a string value onto the BQuery's predicate stack.
|
||||
\param value the value
|
||||
\param caseInsensitive \c true, if the case of the string should be
|
||||
ignored, \c false otherwise
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Not enough memory.
|
||||
- \c B_NOT_ALLOWED: PushString() was called after Fetch().
|
||||
\note In BeOS R5 this method returns \c void. That is checking the return
|
||||
value will render your code source and binary incompatible!
|
||||
Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushString(const char *value, bool caseInsensitive)
|
||||
{
|
||||
return _PushNode(new(nothrow) StringNode(value, caseInsensitive), true);
|
||||
}
|
||||
|
||||
// PushDate
|
||||
/*! \brief Pushes a date value onto the BQuery's predicate stack.
|
||||
The supplied date can be any string understood by the POSIX function
|
||||
parsedate().
|
||||
\param date the date string
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_ERROR: Error parsing the string.
|
||||
- \c B_NOT_ALLOWED: PushDate() was called after Fetch().
|
||||
\note Calling PushXYZ() after a Fetch() does change the predicate on R5,
|
||||
but it doesn't affect the active query and the newly created
|
||||
predicate can not even be used for the next query, since in order
|
||||
to be able to reuse the BQuery object for another query, Clear() has
|
||||
to be called and Clear() also deletes the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::PushDate(const char *date)
|
||||
{
|
||||
status_t error = (date ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
time_t t;
|
||||
time(&t);
|
||||
t = parsedate(date, t);
|
||||
if (t < 0)
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
if (error == B_OK)
|
||||
error = _PushNode(new(nothrow) DateNode(date), true);
|
||||
return error;
|
||||
}
|
||||
|
||||
// SetVolume
|
||||
/*! \brief Sets the BQuery's volume.
|
||||
A query is restricted to one volume. This method sets this volume. It
|
||||
fails, if called after Fetch(). To reuse a BQuery object it has to be
|
||||
reset via Clear().
|
||||
\param volume the volume
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NOT_ALLOWED: SetVolume() was called after Fetch().
|
||||
*/
|
||||
status_t
|
||||
BQuery::SetVolume(const BVolume *volume)
|
||||
{
|
||||
status_t error = (volume ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK && _HasFetched())
|
||||
error = B_NOT_ALLOWED;
|
||||
if (error == B_OK) {
|
||||
if (volume->InitCheck() == B_OK)
|
||||
fDevice = volume->Device();
|
||||
else
|
||||
fDevice = (dev_t)B_ERROR;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// SetPredicate
|
||||
/*! \brief Sets the BQuery's predicate.
|
||||
A predicate can be set either using this method or constructing one on
|
||||
the predicate stack. The two methods can not be mixed. The letter one
|
||||
has precedence over this one.
|
||||
The method fails, if called after Fetch(). To reuse a BQuery object it has
|
||||
to be reset via Clear().
|
||||
\param predicate the predicate string
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NOT_ALLOWED: SetPredicate() was called after Fetch().
|
||||
- \c B_NO_MEMORY: Insufficient memory to store the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::SetPredicate(const char *expression)
|
||||
{
|
||||
status_t error = (expression ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK && _HasFetched())
|
||||
error = B_NOT_ALLOWED;
|
||||
if (error == B_OK)
|
||||
error = _SetPredicate(expression);
|
||||
return error;
|
||||
}
|
||||
|
||||
// SetTarget
|
||||
/*! \brief Sets the BQuery's target and makes the query live.
|
||||
The query update messages are sent to the specified target. They might
|
||||
roll in immediately after calling Fetch().
|
||||
This methods fails, if called after Fetch(). To reuse a BQuery object it
|
||||
has to be reset via Clear().
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_BAD_VALUE: \a messenger was not properly initialized.
|
||||
- \c B_NOT_ALLOWED: SetTarget() was called after Fetch().
|
||||
*/
|
||||
status_t
|
||||
BQuery::SetTarget(BMessenger messenger)
|
||||
{
|
||||
status_t error = (messenger.IsValid() ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK && _HasFetched())
|
||||
error = B_NOT_ALLOWED;
|
||||
if (error == B_OK) {
|
||||
BMessenger::Private messengerPrivate(messenger);
|
||||
fPort = messengerPrivate.Port();
|
||||
fToken = (messengerPrivate.IsPreferredTarget()
|
||||
? -1 : messengerPrivate.Token());
|
||||
fLive = true;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// IsLive
|
||||
/*! \brief Returns whether the query associated with this object is live.
|
||||
\return \c true, if the query is live, \c false otherwise
|
||||
*/
|
||||
bool
|
||||
BQuery::IsLive() const
|
||||
{
|
||||
return fLive;
|
||||
}
|
||||
|
||||
// GetPredicate
|
||||
/*! \brief Returns the BQuery's predicate.
|
||||
Regardless of whether the predicate has been constructed using the
|
||||
predicate stack or set via SetPredicate(), this method returns a
|
||||
string representation.
|
||||
\param buffer a pointer to a buffer into which the predicate shall be
|
||||
written
|
||||
\param length the size of the provided buffer
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_INIT: The predicate isn't set.
|
||||
- \c B_BAD_VALUE: \a buffer is \c NULL or too short.
|
||||
\note This method causes the predicate stack to be evaluated and cleared.
|
||||
You can't interleave Push*() and GetPredicate() calls.
|
||||
*/
|
||||
status_t
|
||||
BQuery::GetPredicate(char *buffer, size_t length)
|
||||
{
|
||||
status_t error = (buffer ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK)
|
||||
_EvaluateStack();
|
||||
if (error == B_OK && !fPredicate)
|
||||
error = B_NO_INIT;
|
||||
if (error == B_OK && length <= strlen(fPredicate))
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK)
|
||||
strcpy(buffer, fPredicate);
|
||||
return error;
|
||||
}
|
||||
|
||||
// GetPredicate
|
||||
/*! \brief Returns the BQuery's predicate.
|
||||
Regardless of whether the predicate has been constructed using the
|
||||
predicate stack or set via SetPredicate(), this method returns a
|
||||
string representation.
|
||||
\param predicate a pointer to a BString which shall be set to the
|
||||
predicate string
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_INIT: The predicate isn't set.
|
||||
- \c B_BAD_VALUE: \c NULL \a predicate.
|
||||
\note This method causes the predicate stack to be evaluated and cleared.
|
||||
You can't interleave Push*() and GetPredicate() calls.
|
||||
*/
|
||||
status_t
|
||||
BQuery::GetPredicate(BString *predicate)
|
||||
{
|
||||
status_t error = (predicate ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK)
|
||||
_EvaluateStack();
|
||||
if (error == B_OK && !fPredicate)
|
||||
error = B_NO_INIT;
|
||||
if (error == B_OK)
|
||||
predicate->SetTo(fPredicate);
|
||||
return error;
|
||||
}
|
||||
|
||||
// PredicateLength
|
||||
/*! \brief Returns the length of the BQuery's predicate string.
|
||||
Regardless of whether the predicate has been constructed using the
|
||||
predicate stack or set via SetPredicate(), this method returns the length
|
||||
of its string representation (counting the terminating null).
|
||||
\return
|
||||
- the length of the predicate string (counting the terminating null) or
|
||||
- 0, if an error occured
|
||||
\note This method causes the predicate stack to be evaluated and cleared.
|
||||
You can't interleave Push*() and PredicateLength() calls.
|
||||
*/
|
||||
size_t
|
||||
BQuery::PredicateLength()
|
||||
{
|
||||
status_t error = _EvaluateStack();
|
||||
if (error == B_OK && !fPredicate)
|
||||
error = B_NO_INIT;
|
||||
size_t size = 0;
|
||||
if (error == B_OK)
|
||||
size = strlen(fPredicate) + 1;
|
||||
return size;
|
||||
}
|
||||
|
||||
// TargetDevice
|
||||
/*! \brief Returns the device ID identifying the BQuery's volume.
|
||||
\return the device ID of the BQuery's volume or \c B_NO_INIT, if the
|
||||
volume isn't set.
|
||||
|
||||
*/
|
||||
dev_t
|
||||
BQuery::TargetDevice() const
|
||||
{
|
||||
return fDevice;
|
||||
}
|
||||
|
||||
// Fetch
|
||||
/*! \brief Tells the BQuery to start fetching entries satisfying the predicate.
|
||||
After Fetch() has been called GetNextEntry(), GetNextRef() and
|
||||
GetNextDirents() can be used to retrieve the enties. Live query updates
|
||||
may be sent immediately after this method has been called.
|
||||
Fetch() fails, if it has already been called. To reuse a BQuery object it
|
||||
has to be reset via Clear().
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_INIT: The predicate or the volume aren't set.
|
||||
- \c B_BAD_VALUE: The predicate is invalid.
|
||||
- \c B_NOT_ALLOWED: Fetch() has already been called.
|
||||
*/
|
||||
status_t
|
||||
BQuery::Fetch()
|
||||
{
|
||||
if (_HasFetched())
|
||||
return B_NOT_ALLOWED;
|
||||
|
||||
_EvaluateStack();
|
||||
|
||||
if (!fPredicate || fDevice < 0)
|
||||
return B_NO_INIT;
|
||||
|
||||
fQueryFd = _kern_open_query(fDevice, fPredicate, strlen(fPredicate),
|
||||
fLive ? B_LIVE_QUERY : 0, fPort, fToken);
|
||||
if (fQueryFd < 0)
|
||||
return fQueryFd;
|
||||
|
||||
// set close on exec flag
|
||||
fcntl(fQueryFd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// BEntryList interface
|
||||
|
||||
// GetNextEntry
|
||||
/*! \brief Returns the BQuery's next entry as a BEntry.
|
||||
Places the next entry in the list in \a entry, traversing symlinks if
|
||||
\a traverse is \c true.
|
||||
\param entry a pointer to a BEntry to be initialized with the found entry
|
||||
\param traverse specifies whether to follow it, if the found entry
|
||||
is a symbolic link.
|
||||
\note The iterator used by this method is the same one used by
|
||||
GetNextRef() and GetNextDirents().
|
||||
\return
|
||||
- \c B_OK if successful,
|
||||
- \c B_ENTRY_NOT_FOUND when at the end of the list,
|
||||
- \c B_BAD_VALUE: The queries predicate includes unindexed attributes.
|
||||
- \c B_FILE_ERROR: Fetch() has not been called before.
|
||||
*/
|
||||
status_t
|
||||
BQuery::GetNextEntry(BEntry *entry, bool traverse)
|
||||
{
|
||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
entry_ref ref;
|
||||
error = GetNextRef(&ref);
|
||||
if (error == B_OK)
|
||||
error = entry->SetTo(&ref, traverse);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// GetNextRef
|
||||
/*! \brief Returns the BQuery's next entry as an entry_ref.
|
||||
Places an entry_ref to the next entry in the list into \a ref.
|
||||
\param ref a pointer to an entry_ref to be filled in with the data of the
|
||||
found entry
|
||||
\note The iterator used by this method is the same one used by
|
||||
GetNextEntry() and GetNextDirents().
|
||||
\return
|
||||
- \c B_OK if successful,
|
||||
- \c B_ENTRY_NOT_FOUND when at the end of the list,
|
||||
- \c B_BAD_VALUE: The queries predicate includes unindexed attributes.
|
||||
- \c B_FILE_ERROR: Fetch() has not been called before.
|
||||
*/
|
||||
status_t
|
||||
BQuery::GetNextRef(entry_ref *ref)
|
||||
{
|
||||
status_t error = (ref ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK && !_HasFetched())
|
||||
error = B_FILE_ERROR;
|
||||
if (error == B_OK) {
|
||||
BPrivate::Storage::LongDirEntry entry;
|
||||
bool next = true;
|
||||
while (error == B_OK && next) {
|
||||
if (GetNextDirents(&entry, sizeof(entry), 1) != 1) {
|
||||
error = B_ENTRY_NOT_FOUND;
|
||||
} else {
|
||||
next = (!strcmp(entry.d_name, ".")
|
||||
|| !strcmp(entry.d_name, ".."));
|
||||
}
|
||||
}
|
||||
if (error == B_OK) {
|
||||
ref->device = entry.d_pdev;
|
||||
ref->directory = entry.d_pino;
|
||||
error = ref->set_name(entry.d_name);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// GetNextDirents
|
||||
/*! \brief Returns the BQuery's next entries as dirent structures.
|
||||
Reads a number of entries into the array of dirent structures pointed to by
|
||||
\a buf. Reads as many but no more than \a count entries, as many entries as
|
||||
remain, or as many entries as will fit into the array at \a buf with given
|
||||
length \a length (in bytes), whichever is smallest.
|
||||
\param buf a pointer to a buffer to be filled with dirent structures of
|
||||
the found entries
|
||||
\param length the maximal number of entries to be read.
|
||||
\note The iterator used by this method is the same one used by
|
||||
GetNextEntry() and GetNextRef().
|
||||
\return
|
||||
- The number of dirent structures stored in the buffer, 0 when there are
|
||||
no more entries to be read.
|
||||
- \c B_BAD_VALUE: The queries predicate includes unindexed attributes.
|
||||
- \c B_FILE_ERROR: Fetch() has not been called before.
|
||||
*/
|
||||
int32
|
||||
BQuery::GetNextDirents(struct dirent *buf, size_t length, int32 count)
|
||||
{
|
||||
if (!buf)
|
||||
return B_BAD_VALUE;
|
||||
if (!_HasFetched())
|
||||
return B_FILE_ERROR;
|
||||
return _kern_read_dir(fQueryFd, buf, length, count);
|
||||
}
|
||||
|
||||
// Rewind
|
||||
/*! \brief Rewinds the entry list back to the first entry.
|
||||
|
||||
Unlike R5 Haiku implements this method for BQuery.
|
||||
|
||||
\return
|
||||
- \c B_OK on success,
|
||||
- \c B_FILE_ERROR, if Fetch() has not yet been called.
|
||||
*/
|
||||
status_t
|
||||
BQuery::Rewind()
|
||||
{
|
||||
if (!_HasFetched())
|
||||
return B_FILE_ERROR;
|
||||
return _kern_rewind_dir(fQueryFd);
|
||||
}
|
||||
|
||||
// CountEntries
|
||||
/*! \brief Unimplemented method of the BEntryList interface.
|
||||
\return 0.
|
||||
*/
|
||||
int32
|
||||
BQuery::CountEntries()
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// _HasFetched
|
||||
/*! Returns whether Fetch() has already been called on this object.
|
||||
\return \c true, if Fetch() has successfully been invoked, \c false
|
||||
otherwise.
|
||||
*/
|
||||
bool
|
||||
BQuery::_HasFetched() const
|
||||
{
|
||||
return (fQueryFd >= 0);
|
||||
}
|
||||
|
||||
// _PushNode
|
||||
/*! \brief Pushs a node onto the predicate stack.
|
||||
If the stack has not been allocate until this time, this method does
|
||||
allocate it.
|
||||
If the supplied node is \c NULL, it is assumed that there was not enough
|
||||
memory to allocate the node and thus \c B_NO_MEMORY is returned.
|
||||
In case the method fails, the caller retains the ownership of the supplied
|
||||
node and thus is responsible for deleting it, if \a deleteOnError is
|
||||
\c false. If it is \c true, the node is deleted, if an error occurs.
|
||||
\param node the node to be pushed
|
||||
\param deleteOnError
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: \c NULL \a node or insuffient memory to allocate the
|
||||
predicate stack or push the node.
|
||||
- \c B_NOT_ALLOWED: _PushNode() was called after Fetch().
|
||||
*/
|
||||
status_t
|
||||
BQuery::_PushNode(QueryNode *node, bool deleteOnError)
|
||||
{
|
||||
status_t error = (node ? B_OK : B_NO_MEMORY);
|
||||
if (error == B_OK && _HasFetched())
|
||||
error = B_NOT_ALLOWED;
|
||||
// allocate the stack, if necessary
|
||||
if (error == B_OK && !fStack) {
|
||||
fStack = new(nothrow) QueryStack;
|
||||
if (!fStack)
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
if (error == B_OK)
|
||||
error = fStack->PushNode(node);
|
||||
if (error != B_OK && deleteOnError)
|
||||
delete node;
|
||||
return error;
|
||||
}
|
||||
|
||||
// _SetPredicate
|
||||
/*! \brief Helper method to set the BQuery's predicate.
|
||||
It is not checked whether Fetch() has already been invoked.
|
||||
\param predicate the predicate string
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Insufficient memory to store the predicate.
|
||||
*/
|
||||
status_t
|
||||
BQuery::_SetPredicate(const char *expression)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// unset the old predicate
|
||||
delete[] fPredicate;
|
||||
fPredicate = NULL;
|
||||
// set the new one
|
||||
if (expression) {
|
||||
fPredicate = new(nothrow) char[strlen(expression) + 1];
|
||||
if (fPredicate)
|
||||
strcpy(fPredicate, expression);
|
||||
else
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _EvaluateStack
|
||||
/*! Evaluates the query's predicate stack.
|
||||
The method does nothing (and returns \c B_OK), if the stack is \c NULL.
|
||||
If the stack is non-null and Fetch() has already been called, the method
|
||||
fails.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_NO_MEMORY: Insufficient memory.
|
||||
- \c B_NOT_ALLOWED: _EvaluateStack() was called after Fetch().
|
||||
- another error code
|
||||
*/
|
||||
status_t
|
||||
BQuery::_EvaluateStack()
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (fStack) {
|
||||
_SetPredicate(NULL);
|
||||
if (_HasFetched())
|
||||
error = B_NOT_ALLOWED;
|
||||
// convert the stack to a tree and evaluate it
|
||||
QueryNode *node = NULL;
|
||||
if (error == B_OK)
|
||||
error = fStack->ConvertToTree(node);
|
||||
BString predicate;
|
||||
if (error == B_OK)
|
||||
error = node->GetString(predicate);
|
||||
if (error == B_OK)
|
||||
error = _SetPredicate(predicate.String());
|
||||
delete fStack;
|
||||
fStack = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// FBC
|
||||
void BQuery::_QwertyQuery1() {}
|
||||
void BQuery::_QwertyQuery2() {}
|
||||
void BQuery::_QwertyQuery3() {}
|
||||
void BQuery::_QwertyQuery4() {}
|
||||
void BQuery::_QwertyQuery5() {}
|
||||
void BQuery::_QwertyQuery6() {}
|
||||
|
|
@ -1,490 +0,0 @@
|
|||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
/*!
|
||||
\file QueryPredicate.cpp
|
||||
BQuery predicate helper classes implementation.
|
||||
*/
|
||||
#include "QueryPredicate.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Storage {
|
||||
|
||||
// QueryNode
|
||||
|
||||
// constructor
|
||||
QueryNode::QueryNode()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
QueryNode::~QueryNode()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// LeafNode
|
||||
|
||||
// constructor
|
||||
LeafNode::LeafNode()
|
||||
: QueryNode()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
LeafNode::~LeafNode()
|
||||
{
|
||||
}
|
||||
|
||||
// Arity
|
||||
uint32
|
||||
LeafNode::Arity() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// SetChildAt
|
||||
status_t
|
||||
LeafNode::SetChildAt(QueryNode *child, int32 index)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// ChildAt
|
||||
QueryNode *
|
||||
LeafNode::ChildAt(int32 index)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// UnaryNode
|
||||
|
||||
// constructor
|
||||
UnaryNode::UnaryNode()
|
||||
: QueryNode(),
|
||||
fChild(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
UnaryNode::~UnaryNode()
|
||||
{
|
||||
delete fChild;
|
||||
}
|
||||
|
||||
// Arity
|
||||
uint32
|
||||
UnaryNode::Arity() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// SetChildAt
|
||||
status_t
|
||||
UnaryNode::SetChildAt(QueryNode *child, int32 index)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (index == 0) {
|
||||
delete fChild;
|
||||
fChild = child;
|
||||
} else
|
||||
error = B_BAD_VALUE;
|
||||
return error;
|
||||
}
|
||||
|
||||
// ChildAt
|
||||
QueryNode *
|
||||
UnaryNode::ChildAt(int32 index)
|
||||
{
|
||||
QueryNode *result = NULL;
|
||||
if (index == 0)
|
||||
result = fChild;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// BinaryNode
|
||||
|
||||
// constructor
|
||||
BinaryNode::BinaryNode()
|
||||
: QueryNode(),
|
||||
fChild1(NULL),
|
||||
fChild2(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
BinaryNode::~BinaryNode()
|
||||
{
|
||||
delete fChild1;
|
||||
delete fChild2;
|
||||
}
|
||||
|
||||
// Arity
|
||||
uint32
|
||||
BinaryNode::Arity() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// SetChildAt
|
||||
status_t
|
||||
BinaryNode::SetChildAt(QueryNode *child, int32 index)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (index == 0) {
|
||||
delete fChild1;
|
||||
fChild1 = child;
|
||||
} else if (index == 1) {
|
||||
delete fChild2;
|
||||
fChild2 = child;
|
||||
} else
|
||||
error = B_BAD_VALUE;
|
||||
return error;
|
||||
}
|
||||
|
||||
// ChildAt
|
||||
QueryNode *
|
||||
BinaryNode::ChildAt(int32 index)
|
||||
{
|
||||
QueryNode *result = NULL;
|
||||
if (index == 0)
|
||||
result = fChild1;
|
||||
else if (index == 1)
|
||||
result = fChild2;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// AttributeNode
|
||||
|
||||
// constructor
|
||||
AttributeNode::AttributeNode(const char *attribute)
|
||||
: LeafNode(),
|
||||
fAttribute(attribute)
|
||||
{
|
||||
}
|
||||
|
||||
// GetString
|
||||
status_t
|
||||
AttributeNode::GetString(BString &predicate)
|
||||
{
|
||||
predicate.SetTo(fAttribute);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// StringNode
|
||||
|
||||
// constructor
|
||||
StringNode::StringNode(const char *value, bool caseInsensitive)
|
||||
: LeafNode(),
|
||||
fValue()
|
||||
{
|
||||
if (value) {
|
||||
if (caseInsensitive) {
|
||||
int32 len = strlen(value);
|
||||
for (int32 i = 0; i < len; i++) {
|
||||
char c = value[i];
|
||||
if (isalpha(c)) {
|
||||
int lower = tolower(c);
|
||||
int upper = toupper(c);
|
||||
if (lower < 0 || upper < 0)
|
||||
fValue << c;
|
||||
else
|
||||
fValue << "[" << (char)lower << (char)upper << "]";
|
||||
} else
|
||||
fValue << c;
|
||||
}
|
||||
} else
|
||||
fValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
// GetString
|
||||
status_t
|
||||
StringNode::GetString(BString &predicate)
|
||||
{
|
||||
BString escaped(fValue);
|
||||
escaped.CharacterEscape("\"\\'", '\\');
|
||||
predicate.SetTo("");
|
||||
predicate << "\"" << escaped << "\"";
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// DateNode
|
||||
|
||||
// constructor
|
||||
DateNode::DateNode(const char *value)
|
||||
: LeafNode(),
|
||||
fValue(value)
|
||||
{
|
||||
}
|
||||
|
||||
// GetString
|
||||
status_t
|
||||
DateNode::GetString(BString &predicate)
|
||||
{
|
||||
BString escaped(fValue);
|
||||
escaped.CharacterEscape("%\"\\'", '\\');
|
||||
predicate.SetTo("");
|
||||
predicate << "%" << escaped << "%";
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// ValueNode
|
||||
|
||||
// GetString
|
||||
//
|
||||
// float specialization
|
||||
template<>
|
||||
status_t
|
||||
ValueNode<float>::GetString(BString &predicate)
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf(buffer, "0x%08lx", *(int32*)&fValue);
|
||||
predicate.SetTo(buffer);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// GetString
|
||||
//
|
||||
// double specialization
|
||||
template<>
|
||||
status_t
|
||||
ValueNode<double>::GetString(BString &predicate)
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf(buffer, "0x%016Lx", *(int64*)&fValue);
|
||||
predicate.SetTo(buffer);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// SpecialOpNode
|
||||
|
||||
// constructor
|
||||
SpecialOpNode::SpecialOpNode(query_op op)
|
||||
: LeafNode(),
|
||||
fOp(op)
|
||||
{
|
||||
}
|
||||
|
||||
// GetString
|
||||
status_t
|
||||
SpecialOpNode::GetString(BString &predicate)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
// UnaryOpNode
|
||||
|
||||
// constructor
|
||||
UnaryOpNode::UnaryOpNode(query_op op)
|
||||
: UnaryNode(),
|
||||
fOp(op)
|
||||
{
|
||||
}
|
||||
|
||||
// GetString
|
||||
status_t
|
||||
UnaryOpNode::GetString(BString &predicate)
|
||||
{
|
||||
status_t error = (fChild ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
if (fOp == B_NOT) {
|
||||
BString childString;
|
||||
error = fChild->GetString(childString);
|
||||
predicate.SetTo("(!");
|
||||
predicate << childString << ")";
|
||||
} else
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// BinaryOpNode
|
||||
|
||||
// constructor
|
||||
BinaryOpNode::BinaryOpNode(query_op op)
|
||||
: BinaryNode(),
|
||||
fOp(op)
|
||||
{
|
||||
}
|
||||
|
||||
// GetString
|
||||
status_t
|
||||
BinaryOpNode::GetString(BString &predicate)
|
||||
{
|
||||
status_t error = (fChild1 && fChild2 ? B_OK : B_BAD_VALUE);
|
||||
BString childString1;
|
||||
BString childString2;
|
||||
if (error == B_OK)
|
||||
error = fChild1->GetString(childString1);
|
||||
if (error == B_OK)
|
||||
error = fChild2->GetString(childString2);
|
||||
predicate.SetTo("");
|
||||
if (error == B_OK) {
|
||||
switch (fOp) {
|
||||
case B_EQ:
|
||||
predicate << "(" << childString1 << "=="
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
case B_GT:
|
||||
predicate << "(" << childString1 << ">"
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
case B_GE:
|
||||
predicate << "(" << childString1 << ">="
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
case B_LT:
|
||||
predicate << "(" << childString1 << "<"
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
case B_LE:
|
||||
predicate << "(" << childString1 << "<="
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
case B_NE:
|
||||
predicate << "(" << childString1 << "!="
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
case B_CONTAINS:
|
||||
if (StringNode *strNode = dynamic_cast<StringNode*>(fChild2)) {
|
||||
BString value;
|
||||
value << "*" << strNode->Value() << "*";
|
||||
error = StringNode(value.String()).GetString(childString2);
|
||||
}
|
||||
if (error == B_OK) {
|
||||
predicate << "(" << childString1 << "=="
|
||||
<< childString2 << ")";
|
||||
}
|
||||
break;
|
||||
case B_BEGINS_WITH:
|
||||
if (StringNode *strNode = dynamic_cast<StringNode*>(fChild2)) {
|
||||
BString value;
|
||||
value << strNode->Value() << "*";
|
||||
error = StringNode(value.String()).GetString(childString2);
|
||||
}
|
||||
if (error == B_OK) {
|
||||
predicate << "(" << childString1 << "=="
|
||||
<< childString2 << ")";
|
||||
}
|
||||
break;
|
||||
case B_ENDS_WITH:
|
||||
if (StringNode *strNode = dynamic_cast<StringNode*>(fChild2)) {
|
||||
BString value;
|
||||
value << "*" << strNode->Value();
|
||||
error = StringNode(value.String()).GetString(childString2);
|
||||
}
|
||||
if (error == B_OK) {
|
||||
predicate << "(" << childString1 << "=="
|
||||
<< childString2 << ")";
|
||||
}
|
||||
break;
|
||||
case B_AND:
|
||||
predicate << "(" << childString1 << "&&"
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
case B_OR:
|
||||
predicate << "(" << childString1 << "||"
|
||||
<< childString2 << ")";
|
||||
break;
|
||||
default:
|
||||
error = B_BAD_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// QueryStack
|
||||
|
||||
// constructor
|
||||
QueryStack::QueryStack()
|
||||
: fNodes()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
QueryStack::~QueryStack()
|
||||
{
|
||||
for (int32 i = 0; QueryNode *node = (QueryNode*)fNodes.ItemAt(i); i++)
|
||||
delete node;
|
||||
}
|
||||
|
||||
// PushNode
|
||||
status_t
|
||||
QueryStack::PushNode(QueryNode *node)
|
||||
{
|
||||
status_t error = (node ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
if (!fNodes.AddItem(node))
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// PopNode
|
||||
QueryNode *
|
||||
QueryStack::PopNode()
|
||||
{
|
||||
return (QueryNode*)fNodes.RemoveItem(fNodes.CountItems() - 1);
|
||||
}
|
||||
|
||||
// ConvertToTree
|
||||
status_t
|
||||
QueryStack::ConvertToTree(QueryNode *&rootNode)
|
||||
{
|
||||
status_t error = _GetSubTree(rootNode);
|
||||
if (error == B_OK && !fNodes.IsEmpty()) {
|
||||
error = B_BAD_VALUE;
|
||||
delete rootNode;
|
||||
rootNode = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// _GetSubTree
|
||||
status_t
|
||||
QueryStack::_GetSubTree(QueryNode *&rootNode)
|
||||
{
|
||||
QueryNode *node = PopNode();
|
||||
status_t error = (node ? B_OK : B_BAD_VALUE);
|
||||
if (error == B_OK) {
|
||||
uint32 arity = node->Arity();
|
||||
for (int32 i = (int32)arity - 1; error == B_OK && i >= 0; i--) {
|
||||
QueryNode *child = NULL;
|
||||
error = _GetSubTree(child);
|
||||
if (error == B_OK) {
|
||||
error = node->SetChildAt(child, i);
|
||||
if (error != B_OK)
|
||||
delete child;
|
||||
}
|
||||
}
|
||||
}
|
||||
// clean up, if something went wrong
|
||||
if (error != B_OK && node) {
|
||||
delete node;
|
||||
node = NULL;
|
||||
}
|
||||
rootNode = node;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
}; // namespace Storage
|
||||
}; // namespace BPrivate
|
||||
|
||||
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
// ----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// File Name: VolumeRoster.cpp
|
||||
//
|
||||
// Description: BVolumeRoster class
|
||||
// ----------------------------------------------------------------------
|
||||
/*!
|
||||
\file VolumeRoster.cpp
|
||||
BVolumeRoster implementation.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <new>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Directory.h>
|
||||
#include <fs_info.h>
|
||||
#include <Node.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <VolumeRoster.h>
|
||||
|
||||
static const char kBootVolumePath[] = "/boot";
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef USE_OPENBEOS_NAMESPACE
|
||||
namespace OpenBeOS {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\class BVolumeRoster
|
||||
\brief A roster of all volumes available in the system
|
||||
|
||||
Provides an interface for iterating through the volumes available in
|
||||
the system and watching volume mounting/unmounting.
|
||||
|
||||
The class wraps the next_dev() function for iterating through the
|
||||
volume list and the watch_node()/stop_watching() for the watching
|
||||
features.
|
||||
|
||||
\author Vincent Dominguez
|
||||
\author <a href='mailto:bonefish@users.sf.net'>Ingo Weinhold</a>
|
||||
|
||||
\version 0.0.0
|
||||
*/
|
||||
|
||||
/*! \var dev_t BVolumeRoster::fCookie
|
||||
\brief The iteration cookie for next_dev(). Initialized with 0.
|
||||
*/
|
||||
|
||||
/*! \var dev_t BVolumeRoster::fTarget
|
||||
\brief BMessenger referring to the target to which the watching
|
||||
notification messages are sent.
|
||||
|
||||
The object is allocated and owned by the roster. \c NULL, if not watching.
|
||||
*/
|
||||
|
||||
// constructor
|
||||
/*! \brief Creates a new BVolumeRoster.
|
||||
|
||||
The object is ready to be used.
|
||||
*/
|
||||
BVolumeRoster::BVolumeRoster()
|
||||
: fCookie(0),
|
||||
fTarget(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
/*! \brief Frees all resources associated with this object.
|
||||
|
||||
If a watching was activated on (StartWatching()), it is deactived.
|
||||
*/
|
||||
BVolumeRoster::~BVolumeRoster()
|
||||
{
|
||||
StopWatching();
|
||||
}
|
||||
|
||||
// GetNextVolume
|
||||
/*! \brief Returns the next volume in the list of available volumes.
|
||||
\param volume A pointer to a pre-allocated BVolume to be initialized to
|
||||
refer to the next volume in the list of available volumes.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_BAD_VALUE: The last volume in the list has already been returned.
|
||||
*/
|
||||
status_t
|
||||
BVolumeRoster::GetNextVolume(BVolume *volume)
|
||||
{
|
||||
// check parameter
|
||||
status_t error = (volume ? B_OK : B_BAD_VALUE);
|
||||
// get next device
|
||||
dev_t device;
|
||||
if (error == B_OK) {
|
||||
device = next_dev(&fCookie);
|
||||
if (device < 0)
|
||||
error = device;
|
||||
}
|
||||
// init volume
|
||||
if (error == B_OK)
|
||||
error = volume->SetTo(device);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Rewind
|
||||
/*! \brief Rewinds the list of available volumes such that the next call to
|
||||
GetNextVolume() will return the first element in the list.
|
||||
*/
|
||||
void
|
||||
BVolumeRoster::Rewind()
|
||||
{
|
||||
fCookie = 0;
|
||||
}
|
||||
|
||||
// GetBootVolume
|
||||
/*! \brief Returns the boot volume.
|
||||
|
||||
Currently, this function looks for the volume that is mounted at "/boot".
|
||||
The only way to fool the system into thinking that there is not a boot
|
||||
volume is to rename "/boot" -- but, please refrain from doing so...(:o(
|
||||
|
||||
\param volume A pointer to a pre-allocated BVolume to be initialized to
|
||||
refer to the boot volume.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- an error code otherwise
|
||||
*/
|
||||
status_t
|
||||
BVolumeRoster::GetBootVolume(BVolume *volume)
|
||||
{
|
||||
// check parameter
|
||||
status_t error = (volume ? B_OK : B_BAD_VALUE);
|
||||
// get device
|
||||
dev_t device;
|
||||
if (error == B_OK) {
|
||||
device = dev_for_path(kBootVolumePath);
|
||||
if (device < 0)
|
||||
error = device;
|
||||
}
|
||||
// init volume
|
||||
if (error == B_OK)
|
||||
error = volume->SetTo(device);
|
||||
return error;
|
||||
}
|
||||
|
||||
// StartWatching
|
||||
/*! \brief Starts watching the list of volumes available in the system.
|
||||
|
||||
Notifications are sent to the specified target whenever a volume is
|
||||
mounted or unmounted. The format of the notification messages is
|
||||
described under watch_node(). Actually BVolumeRoster just provides a
|
||||
more convenient interface for it.
|
||||
|
||||
If StartWatching() has been called before with another target and no
|
||||
StopWatching() since, StopWatching() is called first, so that the former
|
||||
target won't receive any notifications anymore.
|
||||
|
||||
When the object is destroyed all watching has an end as well.
|
||||
|
||||
\param messenger The target to which the notification messages shall be
|
||||
sent.
|
||||
\return
|
||||
- \c B_OK: Everything went fine.
|
||||
- \c B_BAD_VALUE: The supplied BMessenger is invalid.
|
||||
- \c B_NO_MEMORY: Insufficient memory to carry out this operation.
|
||||
*/
|
||||
status_t
|
||||
BVolumeRoster::StartWatching(BMessenger messenger)
|
||||
{
|
||||
StopWatching();
|
||||
status_t error = (messenger.IsValid() ? B_OK : B_ERROR);
|
||||
// clone messenger
|
||||
if (error == B_OK) {
|
||||
fTarget = new(nothrow) BMessenger(messenger);
|
||||
if (!fTarget)
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
// start watching
|
||||
if (error == B_OK)
|
||||
error = watch_node(NULL, B_WATCH_MOUNT, messenger);
|
||||
// cleanup on failure
|
||||
if (error != B_OK && fTarget) {
|
||||
delete fTarget;
|
||||
fTarget = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// StopWatching
|
||||
/*! \brief Stops volume watching initiated with StartWatching() before.
|
||||
*/
|
||||
void
|
||||
BVolumeRoster::StopWatching()
|
||||
{
|
||||
if (fTarget) {
|
||||
stop_watching(*fTarget);
|
||||
delete fTarget;
|
||||
fTarget = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Messenger
|
||||
/*! \brief Returns a messenger to the target currently watching the volume
|
||||
list.
|
||||
\return A messenger to the target currently watching the volume list, or
|
||||
an invalid messenger, if noone is currently watching.
|
||||
*/
|
||||
BMessenger
|
||||
BVolumeRoster::Messenger() const
|
||||
{
|
||||
return (fTarget ? *fTarget : BMessenger());
|
||||
}
|
||||
|
||||
// FBC
|
||||
void BVolumeRoster::_SeveredVRoster1() {}
|
||||
void BVolumeRoster::_SeveredVRoster2() {}
|
||||
|
||||
#ifdef USE_OPENBEOS_NAMESPACE
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue