Added public and private methods for dealing with partition and FS add-ons.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2799 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2003-02-22 23:50:14 +00:00
parent 8b56dae30c
commit 6ba9af5a46
2 changed files with 384 additions and 2 deletions

View File

@ -6,14 +6,22 @@
#ifndef _DISK_DEVICE_ROSTER_H
#define _DISK_DEVICE_ROSTER_H
#include <image.h>
#include <DiskDeviceVisitor.h>
#include <Messenger.h>
#include <SupportDefs.h>
class BDirectory;
class BDiskDevice;
class BDiskScannerPartitionAddOn;
class BPartition;
class BSession;
namespace BPrivate {
class AddOnImage;
}
// watchable events
enum {
B_DEVICE_REQUEST_MOUNT_POINT = 0x01, // mount point changes
@ -99,13 +107,41 @@ public:
uint32 eventMask = B_DEVICE_REQUEST_ALL);
status_t StopWatching(BMessenger target);
// partition and FS add-ons
status_t GetNextPartitioningSystem(char *shortName, char *longName = NULL);
status_t GetNextFileSystem(char *shortName, char *longName = NULL);
status_t RewindPartitiningSystems();
status_t RewindFileSystems();
private:
status_t _GetObjectWithID(const char *fieldName, int32 id,
BDiskDevice *device) const;
// TODO: Introduce iterators instead of these functions.
static status_t _GetNextAddOn(BDirectory **directory, int32 *index,
const char *subdir,
BPrivate::AddOnImage *image);
static status_t _GetNextAddOn(BDirectory *directory,
BPrivate::AddOnImage *image);
static status_t _GetNextAddOnDir(BPath *path, int32 *index,
const char *subdir);
static status_t _GetNextAddOnDir(BDirectory **directory, int32 *index,
const char *subdir);
static status_t _LoadPartitionAddOn(const char *partitioningSystem,
BPrivate::AddOnImage *image,
BDiskScannerPartitionAddOn **addOn);
private:
friend class BSession;
BMessenger fManager;
int32 fCookie;
BDirectory *fPartitionAddOnDir;
BDirectory *fFSAddOnDir;
int32 fPartitionAddOnDirIndex;
int32 fFSAddOnDirIndex;
};
#endif // _DISK_DEVICE_ROSTER_H

View File

@ -5,21 +5,39 @@
#include <new.h>
#include <DiskDeviceRoster.h>
#include <Directory.h>
#include <DiskDevice.h>
#include <DiskDevicePrivate.h>
#include <DiskDeviceRoster.h>
#include <DiskScannerAddOn.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <Message.h>
#include <Partition.h>
#include <Path.h>
#include <RegistrarDefs.h>
#include <RosterPrivate.h>
#include <Session.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.
@ -27,7 +45,11 @@
*/
BDiskDeviceRoster::BDiskDeviceRoster()
: fManager(),
fCookie(0)
fCookie(0),
fPartitionAddOnDir(NULL),
fFSAddOnDir(NULL),
fPartitionAddOnDirIndex(0),
fFSAddOnDirIndex(0)
{
get_disk_device_messenger(&fManager);
}
@ -37,6 +59,10 @@ BDiskDeviceRoster::BDiskDeviceRoster()
*/
BDiskDeviceRoster::~BDiskDeviceRoster()
{
if (fPartitionAddOnDir)
delete fPartitionAddOnDir;
if (fFSAddOnDir)
delete fFSAddOnDir;
}
// GetNextDevice
@ -494,6 +520,156 @@ BDiskDeviceRoster::StopWatching(BMessenger target)
return error;
}
// 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.
@ -541,3 +717,173 @@ BDiskDeviceRoster::_GetObjectWithID(const char *fieldName, int32 id,
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);
}
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;
}