11da9f5ceSAxel Dörfler/*
277e9b775SAxel Dörfler * Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
31da9f5ceSAxel Dörfler * Distributed under the terms of the MIT License.
41da9f5ceSAxel Dörfler *
51da9f5ceSAxel Dörfler * Authors:
61da9f5ceSAxel Dörfler *		Ingo Weinhold, bonefish@cs.tu-berlin.de
71da9f5ceSAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
81da9f5ceSAxel Dörfler */
93e19fccbSIngo Weinhold
1077e9b775SAxel Dörfler#include <DiskDeviceRoster.h>
1177e9b775SAxel Dörfler
125c7270efSIngo Weinhold#include <new>
13b11d9a08SIngo Weinhold
146ba9af5aSIngo Weinhold#include <Directory.h>
15b11d9a08SIngo Weinhold#include <DiskDevice.h>
1603fa4a4fSIngo Weinhold#include <DiskDevicePrivate.h>
178bb74546SIngo Weinhold#include <DiskSystem.h>
186ba9af5aSIngo Weinhold#include <Entry.h>
196ba9af5aSIngo Weinhold#include <FindDirectory.h>
20b11d9a08SIngo Weinhold#include <Message.h>
21b11d9a08SIngo Weinhold#include <Partition.h>
226ba9af5aSIngo Weinhold#include <Path.h>
23a58e2ed8SAxel Dörfler#include <Volume.h>
249ca9a5bbSIngo Weinhold
253f78b216SAxel Dörfler#include <MessengerPrivate.h>
263f78b216SAxel Dörfler
27ca9e5772SIngo Weinhold#include <syscalls.h>
286b202f4eSIngo Weinhold#include <ddm_userland_interface_defs.h>
29ca9e5772SIngo Weinhold
309ca9a5bbSIngo Weinhold
317c2e411dSIngo Weinhold/*!	\class BDiskDeviceRoster
327c2e411dSIngo Weinhold	\brief An interface for iterating through the disk devices known to the
337c2e411dSIngo Weinhold		   system and for a notification mechanism provided to listen to their
347c2e411dSIngo Weinhold		   changes.
357c2e411dSIngo Weinhold*/
367c2e411dSIngo Weinhold
376ba9af5aSIngo Weinhold/*!	\brief find_directory constants of the add-on dirs to be searched. */
386ba9af5aSIngo Weinholdstatic const directory_which kAddOnDirs[] = {
393dfd9cb9SOliver Tappe	B_USER_NONPACKAGED_ADDONS_DIRECTORY,
406ba9af5aSIngo Weinhold	B_USER_ADDONS_DIRECTORY,
414b7e2196SIngo Weinhold	B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
423dfd9cb9SOliver Tappe	B_SYSTEM_ADDONS_DIRECTORY,
436ba9af5aSIngo Weinhold};
446ba9af5aSIngo Weinhold/*!	\brief Size of the kAddOnDirs array. */
456ba9af5aSIngo Weinholdstatic const int32 kAddOnDirCount
466ba9af5aSIngo Weinhold	= sizeof(kAddOnDirs) / sizeof(directory_which);
476ba9af5aSIngo Weinhold
486ba9af5aSIngo Weinhold
497c2e411dSIngo Weinhold/*!	\brief Creates a BDiskDeviceRoster object.
507c2e411dSIngo Weinhold
517c2e411dSIngo Weinhold	The object is ready to be used after construction.
527c2e411dSIngo Weinhold*/
533e19fccbSIngo WeinholdBDiskDeviceRoster::BDiskDeviceRoster()
548bb74546SIngo Weinhold	: fDeviceCookie(0),
55eceac61bSIngo Weinhold	  fDiskSystemCookie(0),
56eceac61bSIngo Weinhold	  fJobCookie(0)
575c7270efSIngo Weinhold//	  fPartitionAddOnDir(NULL),
585c7270efSIngo Weinhold//	  fFSAddOnDir(NULL),
595c7270efSIngo Weinhold//	  fPartitionAddOnDirIndex(0),
605c7270efSIngo Weinhold//	  fFSAddOnDirIndex(0)
613e19fccbSIngo Weinhold{
623e19fccbSIngo Weinhold}
633e19fccbSIngo Weinhold
6477e9b775SAxel Dörfler
657c2e411dSIngo Weinhold/*!	\brief Frees all resources associated with the object.
667c2e411dSIngo Weinhold*/
673e19fccbSIngo WeinholdBDiskDeviceRoster::~BDiskDeviceRoster()
683e19fccbSIngo Weinhold{
695c7270efSIngo Weinhold//	if (fPartitionAddOnDir)
705c7270efSIngo Weinhold//		delete fPartitionAddOnDir;
715c7270efSIngo Weinhold//	if (fFSAddOnDir)
725c7270efSIngo Weinhold//		delete fFSAddOnDir;
733e19fccbSIngo Weinhold}
743e19fccbSIngo Weinhold
7577e9b775SAxel Dörfler
767c2e411dSIngo Weinhold/*!	\brief Returns the next BDiskDevice.
777c2e411dSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized to
787c2e411dSIngo Weinhold		   represent the next device.
797c2e411dSIngo Weinhold	\return
807c2e411dSIngo Weinhold	- \c B_OK: Everything went fine.
817c2e411dSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The end of the list of devices had already been
827c2e411dSIngo Weinhold	  reached.
837c2e411dSIngo Weinhold	- another error code
847c2e411dSIngo Weinhold*/
853e19fccbSIngo Weinholdstatus_t
8677e9b775SAxel DörflerBDiskDeviceRoster::GetNextDevice(BDiskDevice* device)
873e19fccbSIngo Weinhold{
885c7270efSIngo Weinhold	if (!device)
895c7270efSIngo Weinhold		return B_BAD_VALUE;
9077e9b775SAxel Dörfler
915c7270efSIngo Weinhold	size_t neededSize = 0;
928bb74546SIngo Weinhold	partition_id id = _kern_get_next_disk_device_id(&fDeviceCookie,
931da9f5ceSAxel Dörfler		&neededSize);
945c7270efSIngo Weinhold	if (id < 0)
955c7270efSIngo Weinhold		return id;
9677e9b775SAxel Dörfler
971573b626SIngo Weinhold	return device->_SetTo(id, true, neededSize);
983e19fccbSIngo Weinhold}
993e19fccbSIngo Weinhold
10077e9b775SAxel Dörfler
1017c2e411dSIngo Weinhold/*!	\brief Rewinds the device list iterator.
1027c2e411dSIngo Weinhold	\return \c B_OK, if everything went fine, another error code otherwise.
1037c2e411dSIngo Weinhold*/
1043e19fccbSIngo Weinholdstatus_t
1055c7270efSIngo WeinholdBDiskDeviceRoster::RewindDevices()
1063e19fccbSIngo Weinhold{
1078bb74546SIngo Weinhold	fDeviceCookie = 0;
108b11d9a08SIngo Weinhold	return B_OK;
1093e19fccbSIngo Weinhold}
1103e19fccbSIngo Weinhold
1111da9f5ceSAxel Dörfler
1125c7270efSIngo Weinholdstatus_t
1131da9f5ceSAxel DörflerBDiskDeviceRoster::GetNextDiskSystem(BDiskSystem* system)
1145c7270efSIngo Weinhold{
1158bb74546SIngo Weinhold	if (!system)
1168bb74546SIngo Weinhold		return B_BAD_VALUE;
1178bb74546SIngo Weinhold	user_disk_system_info info;
1188bb74546SIngo Weinhold	status_t error = _kern_get_next_disk_system_info(&fDiskSystemCookie,
1191da9f5ceSAxel Dörfler		&info);
1208bb74546SIngo Weinhold	if (error == B_OK)
1218bb74546SIngo Weinhold		error = system->_SetTo(&info);
1228bb74546SIngo Weinhold	return error;
1235c7270efSIngo Weinhold}
1245c7270efSIngo Weinhold
1251da9f5ceSAxel Dörfler
1265c7270efSIngo Weinholdstatus_t
1275c7270efSIngo WeinholdBDiskDeviceRoster::RewindDiskSystems()
1285c7270efSIngo Weinhold{
1298bb74546SIngo Weinhold	fDiskSystemCookie = 0;
1308bb74546SIngo Weinhold	return B_OK;
1315c7270efSIngo Weinhold}
1325c7270efSIngo Weinhold
1335c7270efSIngo Weinhold
1341da9f5ceSAxel Dörflerstatus_t
1351da9f5ceSAxel DörflerBDiskDeviceRoster::GetDiskSystem(BDiskSystem* system, const char* name)
1361da9f5ceSAxel Dörfler{
1371da9f5ceSAxel Dörfler	if (!system)
1381da9f5ceSAxel Dörfler		return B_BAD_VALUE;
1391da9f5ceSAxel Dörfler
1401da9f5ceSAxel Dörfler	int32 cookie = 0;
1411da9f5ceSAxel Dörfler	user_disk_system_info info;
142fe760203SStephan Aßmus	while (_kern_get_next_disk_system_info(&cookie, &info) == B_OK) {
1431da9f5ceSAxel Dörfler		if (!strcmp(name, info.name)
1441da9f5ceSAxel Dörfler			|| !strcmp(name, info.short_name)
1451da9f5ceSAxel Dörfler			|| !strcmp(name, info.pretty_name))
1461da9f5ceSAxel Dörfler			return system->_SetTo(&info);
1471da9f5ceSAxel Dörfler	}
1481da9f5ceSAxel Dörfler
1491da9f5ceSAxel Dörfler	return B_ENTRY_NOT_FOUND;
1501da9f5ceSAxel Dörfler}
1511da9f5ceSAxel Dörfler
1521da9f5ceSAxel Dörfler
1535c7270efSIngo Weinholdpartition_id
15477e9b775SAxel DörflerBDiskDeviceRoster::RegisterFileDevice(const char* filename)
1555c7270efSIngo Weinhold{
156dd3be089SIngo Weinhold	if (!filename)
157dd3be089SIngo Weinhold		return B_BAD_VALUE;
158dd3be089SIngo Weinhold	return _kern_register_file_device(filename);
1595c7270efSIngo Weinhold}
1605c7270efSIngo Weinhold
16177e9b775SAxel Dörfler
1625c7270efSIngo Weinholdstatus_t
16377e9b775SAxel DörflerBDiskDeviceRoster::UnregisterFileDevice(const char* filename)
1645c7270efSIngo Weinhold{
165dd3be089SIngo Weinhold	if (!filename)
166dd3be089SIngo Weinhold		return B_BAD_VALUE;
167dd3be089SIngo Weinhold	return _kern_unregister_file_device(-1, filename);
1685c7270efSIngo Weinhold}
1695c7270efSIngo Weinhold
17077e9b775SAxel Dörfler
1715c7270efSIngo Weinholdstatus_t
1725c7270efSIngo WeinholdBDiskDeviceRoster::UnregisterFileDevice(partition_id device)
1735c7270efSIngo Weinhold{
174dd3be089SIngo Weinhold	if (device < 0)
175dd3be089SIngo Weinhold		return B_BAD_VALUE;
176dd3be089SIngo Weinhold	return _kern_unregister_file_device(device, NULL);
1775c7270efSIngo Weinhold}
1785c7270efSIngo Weinhold
17977e9b775SAxel Dörfler
1807c2e411dSIngo Weinhold/*!	\brief Iterates through the all devices.
1817c2e411dSIngo Weinhold
1827c2e411dSIngo Weinhold	The supplied visitor's Visit(BDiskDevice*) is invoked for each device.
1837c2e411dSIngo Weinhold	If Visit() returns \c true, the iteration is terminated and this method
1847c2e411dSIngo Weinhold	returns \c true. If supplied, \a device is set to the concerned device.
1857c2e411dSIngo Weinhold
1867c2e411dSIngo Weinhold	\param visitor The visitor.
1877c2e411dSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized
1887c2e411dSIngo Weinhold		   to the device at which the iteration was terminated.
1897c2e411dSIngo Weinhold		   May be \c NULL.
1907c2e411dSIngo Weinhold	\return \c true, if the iteration was terminated, \c false otherwise.
1917c2e411dSIngo Weinhold*/
1923e19fccbSIngo Weinholdbool
19377e9b775SAxel DörflerBDiskDeviceRoster::VisitEachDevice(BDiskDeviceVisitor* visitor,
19477e9b775SAxel Dörfler	BDiskDevice* device)
1953e19fccbSIngo Weinhold{
19603fa4a4fSIngo Weinhold	bool terminatedEarly = false;
19703fa4a4fSIngo Weinhold	if (visitor) {
1988bb74546SIngo Weinhold		int32 oldCookie = fDeviceCookie;
1998bb74546SIngo Weinhold		fDeviceCookie = 0;
20003fa4a4fSIngo Weinhold		BDiskDevice deviceOnStack;
20177e9b775SAxel Dörfler		BDiskDevice* useDevice = device ? device : &deviceOnStack;
20203fa4a4fSIngo Weinhold		while (!terminatedEarly && GetNextDevice(useDevice) == B_OK)
20303fa4a4fSIngo Weinhold			terminatedEarly = visitor->Visit(useDevice);
2048bb74546SIngo Weinhold		fDeviceCookie = oldCookie;
20503fa4a4fSIngo Weinhold		if (!terminatedEarly)
20603fa4a4fSIngo Weinhold			useDevice->Unset();
20703fa4a4fSIngo Weinhold	}
20803fa4a4fSIngo Weinhold	return terminatedEarly;
20903fa4a4fSIngo Weinhold}
21003fa4a4fSIngo Weinhold
21177e9b775SAxel Dörfler
21208387795SIngo Weinhold/*!	\brief Pre-order traverses the trees spanned by the BDiskDevices and their
21308387795SIngo Weinhold		   subobjects.
2147c2e411dSIngo Weinhold
21508387795SIngo Weinhold	The supplied visitor's Visit(BDiskDevice*) method is invoked for each
21608387795SIngo Weinhold	disk device and Visit(BPartition*) for each (non-disk device) partition.
2177c2e411dSIngo Weinhold	If Visit() returns \c true, the iteration is terminated and this method
2187c2e411dSIngo Weinhold	returns \c true. If supplied, \a device is set to the concerned device
2197c2e411dSIngo Weinhold	and in \a partition the pointer to the partition object is returned.
2207c2e411dSIngo Weinhold
2217c2e411dSIngo Weinhold	\param visitor The visitor.
2227c2e411dSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized
2237c2e411dSIngo Weinhold		   to the device at which the iteration was terminated.
2247c2e411dSIngo Weinhold		   May be \c NULL.
2257c2e411dSIngo Weinhold	\param partition Pointer to a pre-allocated BPartition pointer to be set
2267c2e411dSIngo Weinhold		   to the partition at which the iteration was terminated.
2277c2e411dSIngo Weinhold		   May be \c NULL.
2287c2e411dSIngo Weinhold	\return \c true, if the iteration was terminated, \c false otherwise.
2297c2e411dSIngo Weinhold*/
2303e19fccbSIngo Weinholdbool
23177e9b775SAxel DörflerBDiskDeviceRoster::VisitEachPartition(BDiskDeviceVisitor* visitor,
23277e9b775SAxel Dörfler	BDiskDevice* device, BPartition** partition)
2333e19fccbSIngo Weinhold{
23403fa4a4fSIngo Weinhold	bool terminatedEarly = false;
23503fa4a4fSIngo Weinhold	if (visitor) {
2368bb74546SIngo Weinhold		int32 oldCookie = fDeviceCookie;
2378bb74546SIngo Weinhold		fDeviceCookie = 0;
23803fa4a4fSIngo Weinhold		BDiskDevice deviceOnStack;
23977e9b775SAxel Dörfler		BDiskDevice* useDevice = device ? device : &deviceOnStack;
24077e9b775SAxel Dörfler		BPartition* foundPartition = NULL;
24127872144SStephan Aßmus		while (GetNextDevice(useDevice) == B_OK) {
242671a7455SIngo Weinhold			foundPartition = useDevice->VisitEachDescendant(visitor);
24327872144SStephan Aßmus			if (foundPartition) {
24427872144SStephan Aßmus				terminatedEarly = true;
24527872144SStephan Aßmus				break;
24627872144SStephan Aßmus			}
24727872144SStephan Aßmus		}
2488bb74546SIngo Weinhold		fDeviceCookie = oldCookie;
24903fa4a4fSIngo Weinhold		if (!terminatedEarly)
25003fa4a4fSIngo Weinhold			useDevice->Unset();
25103fa4a4fSIngo Weinhold		else if (device && partition)
25203fa4a4fSIngo Weinhold			*partition = foundPartition;
25303fa4a4fSIngo Weinhold	}
25403fa4a4fSIngo Weinhold	return terminatedEarly;
2553e19fccbSIngo Weinhold}
2563e19fccbSIngo Weinhold
25777e9b775SAxel Dörfler
2587c2e411dSIngo Weinhold/*!	\brief Iterates through the all devices' partitions that are mounted.
2597c2e411dSIngo Weinhold
2607c2e411dSIngo Weinhold	The supplied visitor's Visit(BPartition*) is invoked for each mounted
2617c2e411dSIngo Weinhold	partition.
2627c2e411dSIngo Weinhold	If Visit() returns \c true, the iteration is terminated and this method
2637c2e411dSIngo Weinhold	returns \c true. If supplied, \a device is set to the concerned device
2647c2e411dSIngo Weinhold	and in \a partition the pointer to the partition object is returned.
2657c2e411dSIngo Weinhold
2667c2e411dSIngo Weinhold	\param visitor The visitor.
2677c2e411dSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized
2687c2e411dSIngo Weinhold		   to the device at which the iteration was terminated.
2697c2e411dSIngo Weinhold		   May be \c NULL.
2707c2e411dSIngo Weinhold	\param partition Pointer to a pre-allocated BPartition pointer to be set
2717c2e411dSIngo Weinhold		   to the partition at which the iteration was terminated.
2727c2e411dSIngo Weinhold		   May be \c NULL.
2737c2e411dSIngo Weinhold	\return \c true, if the iteration was terminated, \c false otherwise.
2747c2e411dSIngo Weinhold*/
2753e19fccbSIngo Weinholdbool
27677e9b775SAxel DörflerBDiskDeviceRoster::VisitEachMountedPartition(BDiskDeviceVisitor* visitor,
27777e9b775SAxel Dörfler	BDiskDevice* device, BPartition** partition)
2783e19fccbSIngo Weinhold{
27903fa4a4fSIngo Weinhold	bool terminatedEarly = false;
28003fa4a4fSIngo Weinhold	if (visitor) {
28103fa4a4fSIngo Weinhold		struct MountedPartitionFilter : public PartitionFilter {
282671a7455SIngo Weinhold			virtual bool Filter(BPartition *partition, int32)
28303fa4a4fSIngo Weinhold				{ return partition->IsMounted(); }
28403fa4a4fSIngo Weinhold		} filter;
28503fa4a4fSIngo Weinhold		PartitionFilterVisitor filterVisitor(visitor, &filter);
28603fa4a4fSIngo Weinhold		terminatedEarly
28703fa4a4fSIngo Weinhold			= VisitEachPartition(&filterVisitor, device, partition);
28803fa4a4fSIngo Weinhold	}
28903fa4a4fSIngo Weinhold	return terminatedEarly;
2903e19fccbSIngo Weinhold}
2913e19fccbSIngo Weinhold
29277e9b775SAxel Dörfler
2937c2e411dSIngo Weinhold/*!	\brief Iterates through the all devices' partitions that are mountable.
2947c2e411dSIngo Weinhold
2957c2e411dSIngo Weinhold	The supplied visitor's Visit(BPartition*) is invoked for each mountable
2967c2e411dSIngo Weinhold	partition.
2977c2e411dSIngo Weinhold	If Visit() returns \c true, the iteration is terminated and this method
2987c2e411dSIngo Weinhold	returns \c true. If supplied, \a device is set to the concerned device
2997c2e411dSIngo Weinhold	and in \a partition the pointer to the partition object is returned.
3007c2e411dSIngo Weinhold
3017c2e411dSIngo Weinhold	\param visitor The visitor.
3027c2e411dSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized
3037c2e411dSIngo Weinhold		   to the device at which the iteration was terminated.
3047c2e411dSIngo Weinhold		   May be \c NULL.
3057c2e411dSIngo Weinhold	\param partition Pointer to a pre-allocated BPartition pointer to be set
3067c2e411dSIngo Weinhold		   to the partition at which the iteration was terminated.
3077c2e411dSIngo Weinhold		   May be \c NULL.
3087c2e411dSIngo Weinhold	\return \c true, if the iteration was terminated, \c false otherwise.
3097c2e411dSIngo Weinhold*/
3103e19fccbSIngo Weinholdbool
31177e9b775SAxel DörflerBDiskDeviceRoster::VisitEachMountablePartition(BDiskDeviceVisitor* visitor,
31277e9b775SAxel Dörfler	BDiskDevice* device, BPartition** partition)
3133e19fccbSIngo Weinhold{
31403fa4a4fSIngo Weinhold	bool terminatedEarly = false;
31503fa4a4fSIngo Weinhold	if (visitor) {
31603fa4a4fSIngo Weinhold		struct MountablePartitionFilter : public PartitionFilter {
317671a7455SIngo Weinhold			virtual bool Filter(BPartition *partition, int32)
318c54d68a8SIngo Weinhold				{ return partition->ContainsFileSystem(); }
31903fa4a4fSIngo Weinhold		} filter;
32003fa4a4fSIngo Weinhold		PartitionFilterVisitor filterVisitor(visitor, &filter);
32103fa4a4fSIngo Weinhold		terminatedEarly
32203fa4a4fSIngo Weinhold			= VisitEachPartition(&filterVisitor, device, partition);
32303fa4a4fSIngo Weinhold	}
32403fa4a4fSIngo Weinhold	return terminatedEarly;
3253e19fccbSIngo Weinhold}
3263e19fccbSIngo Weinhold
327a58e2ed8SAxel Dörfler
328a58e2ed8SAxel Dörfler/*!	\brief Finds a BPartition by BVolume.
329a58e2ed8SAxel Dörfler*/
330a58e2ed8SAxel Dörflerstatus_t
331acc632c7SStephan AßmusBDiskDeviceRoster::FindPartitionByVolume(const BVolume& volume,
332acc632c7SStephan Aßmus	BDiskDevice* device, BPartition** _partition)
333a58e2ed8SAxel Dörfler{
334a58e2ed8SAxel Dörfler	class FindPartitionVisitor : public BDiskDeviceVisitor {
335a58e2ed8SAxel Dörfler	public:
336a58e2ed8SAxel Dörfler		FindPartitionVisitor(dev_t volume)
337a58e2ed8SAxel Dörfler			:
338a58e2ed8SAxel Dörfler			fVolume(volume)
339a58e2ed8SAxel Dörfler		{
340a58e2ed8SAxel Dörfler		}
341a58e2ed8SAxel Dörfler
342a58e2ed8SAxel Dörfler		virtual bool Visit(BDiskDevice* device)
343a58e2ed8SAxel Dörfler		{
344a58e2ed8SAxel Dörfler			return Visit(device, 0);
345a58e2ed8SAxel Dörfler		}
346a58e2ed8SAxel Dörfler
347a58e2ed8SAxel Dörfler		virtual bool Visit(BPartition* partition, int32 level)
348a58e2ed8SAxel Dörfler		{
349a58e2ed8SAxel Dörfler			BVolume volume;
350a58e2ed8SAxel Dörfler			return partition->GetVolume(&volume) == B_OK
351a58e2ed8SAxel Dörfler				&& volume.Device() == fVolume;
352a58e2ed8SAxel Dörfler		}
353a58e2ed8SAxel Dörfler
354a58e2ed8SAxel Dörfler	private:
355a58e2ed8SAxel Dörfler		dev_t	fVolume;
356acc632c7SStephan Aßmus	} visitor(volume.Device());
357a58e2ed8SAxel Dörfler
358a58e2ed8SAxel Dörfler	if (VisitEachMountedPartition(&visitor, device, _partition))
359a58e2ed8SAxel Dörfler		return B_OK;
360a58e2ed8SAxel Dörfler
361a58e2ed8SAxel Dörfler	return B_ENTRY_NOT_FOUND;
362a58e2ed8SAxel Dörfler}
363a58e2ed8SAxel Dörfler
364a58e2ed8SAxel Dörfler
365a58e2ed8SAxel Dörfler/*!	\brief Finds a BPartition by mount path.
366a58e2ed8SAxel Dörfler*/
367a58e2ed8SAxel Dörflerstatus_t
368a58e2ed8SAxel DörflerBDiskDeviceRoster::FindPartitionByMountPoint(const char* mountPoint,
369a58e2ed8SAxel Dörfler	BDiskDevice* device, BPartition** _partition)
370a58e2ed8SAxel Dörfler{
371a58e2ed8SAxel Dörfler	BVolume volume(dev_for_path(mountPoint));
372a58e2ed8SAxel Dörfler	if (volume.InitCheck() == B_OK
373acc632c7SStephan Aßmus		&& FindPartitionByVolume(volume, device, _partition))
374a58e2ed8SAxel Dörfler		return B_OK;
375a58e2ed8SAxel Dörfler
376a58e2ed8SAxel Dörfler	return B_ENTRY_NOT_FOUND;
377a58e2ed8SAxel Dörfler}
378a58e2ed8SAxel Dörfler
379a58e2ed8SAxel Dörfler
3807c2e411dSIngo Weinhold/*!	\brief Returns a BDiskDevice for a given ID.
3817c2e411dSIngo Weinhold
3827c2e411dSIngo Weinhold	The supplied \a device is initialized to the device identified by \a id.
3837c2e411dSIngo Weinhold
3847c2e411dSIngo Weinhold	\param id The ID of the device to be retrieved.
3857c2e411dSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized
3867c2e411dSIngo Weinhold		   to the device identified by \a id.
3877c2e411dSIngo Weinhold	\return
3887c2e411dSIngo Weinhold	- \c B_OK: Everything went fine.
3897c2e411dSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: A device with ID \a id could not be found.
3907c2e411dSIngo Weinhold	- other error codes
3917c2e411dSIngo Weinhold*/
3923e19fccbSIngo Weinholdstatus_t
39377e9b775SAxel DörflerBDiskDeviceRoster::GetDeviceWithID(int32 id, BDiskDevice* device) const
3943e19fccbSIngo Weinhold{
395dd3be089SIngo Weinhold	if (!device)
396dd3be089SIngo Weinhold		return B_BAD_VALUE;
3971573b626SIngo Weinhold	return device->_SetTo(id, true, 0);
3983e19fccbSIngo Weinhold}
3993e19fccbSIngo Weinhold
40077e9b775SAxel Dörfler
4017c2e411dSIngo Weinhold/*!	\brief Returns a BPartition for a given ID.
4027c2e411dSIngo Weinhold
4037c2e411dSIngo Weinhold	The supplied \a device is initialized to the device the partition
4047c2e411dSIngo Weinhold	identified by \a id resides on, and \a partition is set to point to the
4057c2e411dSIngo Weinhold	respective BPartition.
4067c2e411dSIngo Weinhold
4077c2e411dSIngo Weinhold	\param id The ID of the partition to be retrieved.
4087c2e411dSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized
4097c2e411dSIngo Weinhold		   to the device the partition identified by \a id resides on.
4107c2e411dSIngo Weinhold	\param partition Pointer to a pre-allocated BPartition pointer to be set
4117c2e411dSIngo Weinhold		   to the partition identified by \a id.
4127c2e411dSIngo Weinhold	\return
4137c2e411dSIngo Weinhold	- \c B_OK: Everything went fine.
4147c2e411dSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: A partition with ID \a id could not be found.
4157c2e411dSIngo Weinhold	- other error codes
4167c2e411dSIngo Weinhold*/
4173e19fccbSIngo Weinholdstatus_t
41877e9b775SAxel DörflerBDiskDeviceRoster::GetPartitionWithID(int32 id, BDiskDevice* device,
41977e9b775SAxel Dörfler	BPartition** partition) const
4203e19fccbSIngo Weinhold{
421dd3be089SIngo Weinhold	if (!device || !partition)
422dd3be089SIngo Weinhold		return B_BAD_VALUE;
42377e9b775SAxel Dörfler
42477e9b775SAxel Dörfler	// retrieve the device data
4251573b626SIngo Weinhold	status_t error = device->_SetTo(id, false, 0);
426dd3be089SIngo Weinhold	if (error != B_OK)
427dd3be089SIngo Weinhold		return error;
42877e9b775SAxel Dörfler
429dd3be089SIngo Weinhold	// find the partition object
430dd3be089SIngo Weinhold	*partition = device->FindDescendant(id);
431dd3be089SIngo Weinhold	if (!*partition)	// should never happen!
432dd3be089SIngo Weinhold		return B_ENTRY_NOT_FOUND;
43377e9b775SAxel Dörfler
434dd3be089SIngo Weinhold	return B_OK;
4355c7270efSIngo Weinhold}
4365c7270efSIngo Weinhold
43738bbc957SAxel Dörfler
438dd3be089SIngo Weinholdstatus_t
43977e9b775SAxel DörflerBDiskDeviceRoster::GetDeviceForPath(const char* filename, BDiskDevice* device)
4405c7270efSIngo Weinhold{
441dd3be089SIngo Weinhold	if (!filename || !device)
442dd3be089SIngo Weinhold		return B_BAD_VALUE;
44377e9b775SAxel Dörfler
444dd3be089SIngo Weinhold	// get the device ID
445dd3be089SIngo Weinhold	size_t neededSize = 0;
446dd3be089SIngo Weinhold	partition_id id = _kern_find_disk_device(filename, &neededSize);
447dd3be089SIngo Weinhold	if (id < 0)
448dd3be089SIngo Weinhold		return id;
44977e9b775SAxel Dörfler
45077e9b775SAxel Dörfler	// retrieve the device data
4511573b626SIngo Weinhold	return device->_SetTo(id, true, neededSize);
4525c7270efSIngo Weinhold}
4535c7270efSIngo Weinhold
45438bbc957SAxel Dörfler
455dd3be089SIngo Weinholdstatus_t
45677e9b775SAxel DörflerBDiskDeviceRoster::GetPartitionForPath(const char* filename,
45777e9b775SAxel Dörfler	BDiskDevice* device, BPartition** partition)
4585c7270efSIngo Weinhold{
459dd3be089SIngo Weinhold	if (!filename || !device || !partition)
460dd3be089SIngo Weinhold		return B_BAD_VALUE;
46177e9b775SAxel Dörfler
462dd3be089SIngo Weinhold	// get the partition ID
463dd3be089SIngo Weinhold	size_t neededSize = 0;
464dd3be089SIngo Weinhold	partition_id id = _kern_find_partition(filename, &neededSize);
465dd3be089SIngo Weinhold	if (id < 0)
466dd3be089SIngo Weinhold		return id;
46777e9b775SAxel Dörfler
46877e9b775SAxel Dörfler	// retrieve the device data
4691573b626SIngo Weinhold	status_t error = device->_SetTo(id, false, neededSize);
470dd3be089SIngo Weinhold	if (error != B_OK)
471dd3be089SIngo Weinhold		return error;
47277e9b775SAxel Dörfler
473dd3be089SIngo Weinhold	// find the partition object
474dd3be089SIngo Weinhold	*partition = device->FindDescendant(id);
475dd3be089SIngo Weinhold	if (!*partition)	// should never happen!
476dd3be089SIngo Weinhold		return B_ENTRY_NOT_FOUND;
477dd3be089SIngo Weinhold	return B_OK;
4783e19fccbSIngo Weinhold}
4793e19fccbSIngo Weinhold
48038bbc957SAxel Dörfler
48138bbc957SAxel Dörflerstatus_t
48277e9b775SAxel DörflerBDiskDeviceRoster::GetFileDeviceForPath(const char* filename,
48377e9b775SAxel Dörfler	BDiskDevice* device)
48438bbc957SAxel Dörfler{
48538bbc957SAxel Dörfler	if (!filename || !device)
48638bbc957SAxel Dörfler		return B_BAD_VALUE;
48738bbc957SAxel Dörfler
48838bbc957SAxel Dörfler	// get the device ID
48938bbc957SAxel Dörfler	size_t neededSize = 0;
49038bbc957SAxel Dörfler	partition_id id = _kern_find_file_disk_device(filename, &neededSize);
49138bbc957SAxel Dörfler	if (id < 0)
49238bbc957SAxel Dörfler		return id;
49338bbc957SAxel Dörfler
49477e9b775SAxel Dörfler	// retrieve the device data
49538bbc957SAxel Dörfler	return device->_SetTo(id, true, neededSize);
49638bbc957SAxel Dörfler}
49738bbc957SAxel Dörfler
49838bbc957SAxel Dörfler
4997c2e411dSIngo Weinhold/*!	\brief Adds a target to the list of targets to be notified on disk device
5007c2e411dSIngo Weinhold		   events.
5017c2e411dSIngo Weinhold
5027c2e411dSIngo Weinhold	\todo List the event mask flags, the events and describe the layout of the
5037c2e411dSIngo Weinhold		  notification message.
5047c2e411dSIngo Weinhold
5057c2e411dSIngo Weinhold	If \a target is already listening to events, this method replaces the
5067c2e411dSIngo Weinhold	former event mask with \a eventMask.
5077c2e411dSIngo Weinhold
5087c2e411dSIngo Weinhold	\param target A BMessenger identifying the target to which the events
5097c2e411dSIngo Weinhold		   shall be sent.
5107c2e411dSIngo Weinhold	\param eventMask A mask specifying on which events the target shall be
5117c2e411dSIngo Weinhold		   notified.
5127c2e411dSIngo Weinhold	\return \c B_OK, if everything went fine, another error code otherwise.
5137c2e411dSIngo Weinhold*/
5143e19fccbSIngo Weinholdstatus_t
5153e19fccbSIngo WeinholdBDiskDeviceRoster::StartWatching(BMessenger target, uint32 eventMask)
5163e19fccbSIngo Weinhold{
5173f78b216SAxel Dörfler	if (eventMask == 0)
5183f78b216SAxel Dörfler		return B_BAD_VALUE;
5193f78b216SAxel Dörfler
5203f78b216SAxel Dörfler	BMessenger::Private messengerPrivate(target);
5213f78b216SAxel Dörfler	port_id port = messengerPrivate.Port();
5223f78b216SAxel Dörfler	int32 token = messengerPrivate.Token();
5233f78b216SAxel Dörfler
5243f78b216SAxel Dörfler	return _kern_start_watching_disks(eventMask, port, token);
5255c7270efSIngo Weinhold}
5265c7270efSIngo Weinhold
5273e19fccbSIngo Weinhold
5287c2e411dSIngo Weinhold/*!	\brief Remove a target from the list of targets to be notified on disk
5297c2e411dSIngo Weinhold		   device events.
5307c2e411dSIngo Weinhold	\param target A BMessenger identifying the target to which notfication
5317c2e411dSIngo Weinhold		   message shall not longer be sent.
5327c2e411dSIngo Weinhold	\return \c B_OK, if everything went fine, another error code otherwise.
5337c2e411dSIngo Weinhold*/
5343e19fccbSIngo Weinholdstatus_t
5353e19fccbSIngo WeinholdBDiskDeviceRoster::StopWatching(BMessenger target)
5363e19fccbSIngo Weinhold{
5373f78b216SAxel Dörfler	BMessenger::Private messengerPrivate(target);
5383f78b216SAxel Dörfler	port_id port = messengerPrivate.Port();
5393f78b216SAxel Dörfler	int32 token = messengerPrivate.Token();
5403f78b216SAxel Dörfler
5413f78b216SAxel Dörfler	return _kern_stop_watching_disks(port, token);
5423e19fccbSIngo Weinhold}
5433e19fccbSIngo Weinhold
5445c7270efSIngo Weinhold#if 0
5455c7270efSIngo Weinhold
5466ba9af5aSIngo Weinhold/*!	\brief Returns the next partitioning system capable of partitioning.
5476ba9af5aSIngo Weinhold
5486ba9af5aSIngo Weinhold	The returned \a shortName can be passed to BSession::Partition().
5496ba9af5aSIngo Weinhold
5506ba9af5aSIngo Weinhold	\param shortName Pointer to a pre-allocation char buffer, of size
5516ba9af5aSIngo Weinhold		   \c B_FILE_NAME_LENGTH or larger into which the short name of the
5526ba9af5aSIngo Weinhold		   partitioning system shall be written.
5536ba9af5aSIngo Weinhold	\param longName Pointer to a pre-allocation char buffer, of size
5546ba9af5aSIngo Weinhold		   \c B_FILE_NAME_LENGTH or larger into which the long name of the
5556ba9af5aSIngo Weinhold		   partitioning system shall be written. May be \c NULL.
5566ba9af5aSIngo Weinhold	\return
5576ba9af5aSIngo Weinhold	- \c B_OK: Everything went fine.
5586ba9af5aSIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a shortName.
5596ba9af5aSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: End of the list has been reached.
5606ba9af5aSIngo Weinhold	- other error codes
5616ba9af5aSIngo Weinhold*/
5626ba9af5aSIngo Weinholdstatus_t
5636ba9af5aSIngo WeinholdBDiskDeviceRoster::GetNextPartitioningSystem(char *shortName, char *longName)
5646ba9af5aSIngo Weinhold{
5656ba9af5aSIngo Weinhold	status_t error = (shortName ? B_OK : B_BAD_VALUE);
5666ba9af5aSIngo Weinhold	if (error == B_OK) {
5676ba9af5aSIngo Weinhold		// search until an add-on has been found or the end of all directories
5686ba9af5aSIngo Weinhold		// has been reached
5696ba9af5aSIngo Weinhold		bool found = false;
5706ba9af5aSIngo Weinhold		do {
5716ba9af5aSIngo Weinhold			// get the next add-on in the current dir
5726ba9af5aSIngo Weinhold			AddOnImage image;
5736ba9af5aSIngo Weinhold			error = _GetNextAddOn(fPartitionAddOnDir, &image);
5746ba9af5aSIngo Weinhold			if (error == B_OK) {
5756ba9af5aSIngo Weinhold				// add-on loaded: get the function that creates an add-on
5766ba9af5aSIngo Weinhold				// object
5776ba9af5aSIngo Weinhold				BDiskScannerPartitionAddOn *(*create_add_on)();
5786ba9af5aSIngo Weinhold				if (get_image_symbol(image.ID(), "create_ds_partition_add_on",
5796ba9af5aSIngo Weinhold									 B_SYMBOL_TYPE_TEXT,
5806ba9af5aSIngo Weinhold									 (void**)&create_add_on) == B_OK) {
5816ba9af5aSIngo Weinhold					// create the add-on object and copy the requested data
5826ba9af5aSIngo Weinhold					if (BDiskScannerPartitionAddOn *addOn
5836ba9af5aSIngo Weinhold						= (*create_add_on)()) {
5846ba9af5aSIngo Weinhold						const char *addOnShortName = addOn->ShortName();
5856ba9af5aSIngo Weinhold						const char *addOnLongName = addOn->LongName();
5866ba9af5aSIngo Weinhold						if (addOnShortName && addOnLongName) {
5876ba9af5aSIngo Weinhold							strcpy(shortName, addOnShortName);
5886ba9af5aSIngo Weinhold							if (longName)
5896ba9af5aSIngo Weinhold								strcpy(longName, addOnLongName);
5906ba9af5aSIngo Weinhold							found = true;
5916ba9af5aSIngo Weinhold						}
5926ba9af5aSIngo Weinhold						delete addOn;
5936ba9af5aSIngo Weinhold					}
5946ba9af5aSIngo Weinhold				}
5956ba9af5aSIngo Weinhold			} else if (error == B_ENTRY_NOT_FOUND) {
5966ba9af5aSIngo Weinhold				// end of the current directory has been reached, try next dir
5976ba9af5aSIngo Weinhold				error = _GetNextAddOnDir(&fPartitionAddOnDir,
5986ba9af5aSIngo Weinhold										 &fPartitionAddOnDirIndex,
5996ba9af5aSIngo Weinhold										 "partition");
6006ba9af5aSIngo Weinhold			}
6016ba9af5aSIngo Weinhold		} while (error == B_OK && !found);
6026ba9af5aSIngo Weinhold	}
6036ba9af5aSIngo Weinhold	return error;
6046ba9af5aSIngo Weinhold}
6056ba9af5aSIngo Weinhold
60677e9b775SAxel Dörfler
6076ba9af5aSIngo Weinhold/*!	\brief Returns the next file system capable of initializing.
6086ba9af5aSIngo Weinhold
6096ba9af5aSIngo Weinhold	The returned \a shortName can be passed to BPartition::Initialize().
6106ba9af5aSIngo Weinhold
6116ba9af5aSIngo Weinhold	\param shortName Pointer to a pre-allocation char buffer, of size
6126ba9af5aSIngo Weinhold		   \c B_FILE_NAME_LENGTH or larger into which the short name of the
6136ba9af5aSIngo Weinhold		   file system shall be written.
6146ba9af5aSIngo Weinhold	\param longName Pointer to a pre-allocation char buffer, of size
6156ba9af5aSIngo Weinhold		   \c B_FILE_NAME_LENGTH or larger into which the long name of the
6166ba9af5aSIngo Weinhold		   file system shall be written. May be \c NULL.
6176ba9af5aSIngo Weinhold	\return
6186ba9af5aSIngo Weinhold	- \c B_OK: Everything went fine.
6196ba9af5aSIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a shortName.
6206ba9af5aSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: End of the list has been reached.
6216ba9af5aSIngo Weinhold	- other error codes
6226ba9af5aSIngo Weinhold*/
6236ba9af5aSIngo Weinholdstatus_t
6246ba9af5aSIngo WeinholdBDiskDeviceRoster::GetNextFileSystem(char *shortName, char *longName)
6256ba9af5aSIngo Weinhold{
6266ba9af5aSIngo Weinhold	status_t error = (shortName ? B_OK : B_BAD_VALUE);
6276ba9af5aSIngo Weinhold	if (error == B_OK) {
6286ba9af5aSIngo Weinhold		// search until an add-on has been found or the end of all directories
6296ba9af5aSIngo Weinhold		// has been reached
6306ba9af5aSIngo Weinhold		bool found = false;
6316ba9af5aSIngo Weinhold		do {
6326ba9af5aSIngo Weinhold			// get the next add-on in the current dir
6336ba9af5aSIngo Weinhold			AddOnImage image;
6346ba9af5aSIngo Weinhold			error = _GetNextAddOn(fFSAddOnDir, &image);
6356ba9af5aSIngo Weinhold			if (error == B_OK) {
6366ba9af5aSIngo Weinhold				// add-on loaded: get the function that creates an add-on
6376ba9af5aSIngo Weinhold				// object
6386ba9af5aSIngo Weinhold				BDiskScannerFSAddOn *(*create_add_on)();
6396ba9af5aSIngo Weinhold				if (get_image_symbol(image.ID(), "create_ds_fs_add_on",
6406ba9af5aSIngo Weinhold									 B_SYMBOL_TYPE_TEXT,
6416ba9af5aSIngo Weinhold									 (void**)&create_add_on) == B_OK) {
6426ba9af5aSIngo Weinhold					// create the add-on object and copy the requested data
6436ba9af5aSIngo Weinhold					if (BDiskScannerFSAddOn *addOn = (*create_add_on)()) {
6446ba9af5aSIngo Weinhold						const char *addOnShortName = addOn->ShortName();
6456ba9af5aSIngo Weinhold						const char *addOnLongName = addOn->LongName();
6466ba9af5aSIngo Weinhold						if (addOnShortName && addOnLongName) {
6476ba9af5aSIngo Weinhold							strcpy(shortName, addOnShortName);
6486ba9af5aSIngo Weinhold							if (longName)
6496ba9af5aSIngo Weinhold								strcpy(longName, addOnLongName);
6506ba9af5aSIngo Weinhold							found = true;
6516ba9af5aSIngo Weinhold						}
6526ba9af5aSIngo Weinhold						delete addOn;
6536ba9af5aSIngo Weinhold					}
6546ba9af5aSIngo Weinhold				}
6556ba9af5aSIngo Weinhold			} else if (error == B_ENTRY_NOT_FOUND) {
6566ba9af5aSIngo Weinhold				// end of the current directory has been reached, try next dir
6576ba9af5aSIngo Weinhold				error = _GetNextAddOnDir(&fFSAddOnDir, &fFSAddOnDirIndex,
6586ba9af5aSIngo Weinhold										 "fs");
6596ba9af5aSIngo Weinhold			}
6606ba9af5aSIngo Weinhold		} while (error == B_OK && !found);
6616ba9af5aSIngo Weinhold	}
6626ba9af5aSIngo Weinhold	return error;
6636ba9af5aSIngo Weinhold}
6646ba9af5aSIngo Weinhold
66577e9b775SAxel Dörfler
6666ba9af5aSIngo Weinhold/*!	\brief Rewinds the partitioning system list iterator.
6676ba9af5aSIngo Weinhold	\return \c B_OK, if everything went fine, another error code otherwise.
6686ba9af5aSIngo Weinhold*/
6696ba9af5aSIngo Weinholdstatus_t
6706ba9af5aSIngo WeinholdBDiskDeviceRoster::RewindPartitiningSystems()
6716ba9af5aSIngo Weinhold{
6726ba9af5aSIngo Weinhold	if (fPartitionAddOnDir) {
6736ba9af5aSIngo Weinhold		delete fPartitionAddOnDir;
6746ba9af5aSIngo Weinhold		fPartitionAddOnDir = NULL;
6756ba9af5aSIngo Weinhold	}
6766ba9af5aSIngo Weinhold	fPartitionAddOnDirIndex = 0;
6776ba9af5aSIngo Weinhold	return B_OK;
6786ba9af5aSIngo Weinhold}
6796ba9af5aSIngo Weinhold
68077e9b775SAxel Dörfler
6816ba9af5aSIngo Weinhold/*!	\brief Rewinds the file system list iterator.
6826ba9af5aSIngo Weinhold	\return \c B_OK, if everything went fine, another error code otherwise.
6836ba9af5aSIngo Weinhold*/
6846ba9af5aSIngo Weinholdstatus_t
6856ba9af5aSIngo WeinholdBDiskDeviceRoster::RewindFileSystems()
6866ba9af5aSIngo Weinhold{
6876ba9af5aSIngo Weinhold	if (fFSAddOnDir) {
6886ba9af5aSIngo Weinhold		delete fFSAddOnDir;
6896ba9af5aSIngo Weinhold		fFSAddOnDir = NULL;
6906ba9af5aSIngo Weinhold	}
6916ba9af5aSIngo Weinhold	fFSAddOnDirIndex = 0;
6926ba9af5aSIngo Weinhold	return B_OK;
6936ba9af5aSIngo Weinhold}
6946ba9af5aSIngo Weinhold
69577e9b775SAxel Dörfler
69603fa4a4fSIngo Weinhold/*!	\brief Returns a BDiskDevice for a given device, session or partition ID.
69703fa4a4fSIngo Weinhold
69803fa4a4fSIngo Weinhold	The supplied \a device is initialized to the device the object identified
69903fa4a4fSIngo Weinhold	by \a id belongs to.
70003fa4a4fSIngo Weinhold
70103fa4a4fSIngo Weinhold	\param fieldName "device_id", "sesison_id" or "partition_id" according to
70203fa4a4fSIngo Weinhold		   the type of object the device shall be retrieved for.
70303fa4a4fSIngo Weinhold	\param id The ID of the device, session or partition to be retrieved.
70403fa4a4fSIngo Weinhold	\param device Pointer to a pre-allocated BDiskDevice to be initialized
70503fa4a4fSIngo Weinhold		   to the device to be retrieved.
70603fa4a4fSIngo Weinhold	\return
70703fa4a4fSIngo Weinhold	- \c B_OK: Everything went fine.
70803fa4a4fSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: A device, session or partition respectively with
70903fa4a4fSIngo Weinhold		 ID \a id could not be found.
71003fa4a4fSIngo Weinhold	- other error codes
71103fa4a4fSIngo Weinhold*/
71203fa4a4fSIngo Weinholdstatus_t
71303fa4a4fSIngo WeinholdBDiskDeviceRoster::_GetObjectWithID(const char *fieldName, int32 id,
71477e9b775SAxel Dörfler	BDiskDevice *device) const
71503fa4a4fSIngo Weinhold{
71603fa4a4fSIngo Weinhold	status_t error = (device ? B_OK : B_BAD_VALUE);
71703fa4a4fSIngo Weinhold	// compose request message
71803fa4a4fSIngo Weinhold	BMessage request(B_REG_GET_DISK_DEVICE);
71903fa4a4fSIngo Weinhold	if (error == B_OK)
72003fa4a4fSIngo Weinhold		error = request.AddInt32(fieldName, id);
72103fa4a4fSIngo Weinhold	// send request
72203fa4a4fSIngo Weinhold	BMessage reply;
72303fa4a4fSIngo Weinhold	if (error == B_OK)
72403fa4a4fSIngo Weinhold		error = fManager.SendMessage(&request, &reply);
72503fa4a4fSIngo Weinhold	// analyze reply
72603fa4a4fSIngo Weinhold	if (error == B_OK) {
72703fa4a4fSIngo Weinhold		// result
72803fa4a4fSIngo Weinhold		status_t result = B_OK;
72903fa4a4fSIngo Weinhold		error = reply.FindInt32("result", &result);
73003fa4a4fSIngo Weinhold		if (error == B_OK)
73103fa4a4fSIngo Weinhold			error = result;
73203fa4a4fSIngo Weinhold		// device
73303fa4a4fSIngo Weinhold		BMessage archive;
73403fa4a4fSIngo Weinhold		if (error == B_OK)
73503fa4a4fSIngo Weinhold			error = reply.FindMessage("device", &archive);
73603fa4a4fSIngo Weinhold		if (error == B_OK)
73703fa4a4fSIngo Weinhold			error = device->_Unarchive(&archive);
73803fa4a4fSIngo Weinhold	}
73903fa4a4fSIngo Weinhold	return error;
74003fa4a4fSIngo Weinhold}
74103fa4a4fSIngo Weinhold
7426ba9af5aSIngo Weinhold
7436ba9af5aSIngo Weinhold/*!	\brief Finds and loads the next add-on of an add-on subdirectory.
7446ba9af5aSIngo Weinhold	\param directory The add-on directory.
7456ba9af5aSIngo Weinhold	\param image Pointer to an image_id into which the image ID of the loaded
7466ba9af5aSIngo Weinhold		   add-on shall be written.
7476ba9af5aSIngo Weinhold	\return
7486ba9af5aSIngo Weinhold	- \c B_OK: Everything went fine.
7496ba9af5aSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: End of directory.
7506ba9af5aSIngo Weinhold	- other error codes
7516ba9af5aSIngo Weinhold*/
7526ba9af5aSIngo Weinholdstatus_t
7536ba9af5aSIngo WeinholdBDiskDeviceRoster::_GetNextAddOn(BDirectory **directory, int32 *index,
75477e9b775SAxel Dörfler	const char *subdir, AddOnImage *image)
7556ba9af5aSIngo Weinhold{
7566ba9af5aSIngo Weinhold	status_t error = (directory && index && subdir && image
7576ba9af5aSIngo Weinhold					  ? B_OK : B_BAD_VALUE);
7586ba9af5aSIngo Weinhold	if (error == B_OK) {
7596ba9af5aSIngo Weinhold		// search until an add-on has been found or the end of all directories
7606ba9af5aSIngo Weinhold		// has been reached
7616ba9af5aSIngo Weinhold		bool found = false;
7626ba9af5aSIngo Weinhold		do {
7636ba9af5aSIngo Weinhold			// get the next add-on in the current dir
7646ba9af5aSIngo Weinhold			error = _GetNextAddOn(*directory, image);
7656ba9af5aSIngo Weinhold			if (error == B_OK) {
7666ba9af5aSIngo Weinhold				found = true;
7676ba9af5aSIngo Weinhold			} else if (error == B_ENTRY_NOT_FOUND) {
7686ba9af5aSIngo Weinhold				// end of the current directory has been reached, try next dir
7696ba9af5aSIngo Weinhold				error = _GetNextAddOnDir(directory, index, subdir);
7706ba9af5aSIngo Weinhold			}
7716ba9af5aSIngo Weinhold		} while (error == B_OK && !found);
7726ba9af5aSIngo Weinhold	}
7736ba9af5aSIngo Weinhold	return error;
7746ba9af5aSIngo Weinhold}
7756ba9af5aSIngo Weinhold
77677e9b775SAxel Dörfler
7776ba9af5aSIngo Weinhold/*!	\brief Finds and loads the next add-on of an add-on subdirectory.
7786ba9af5aSIngo Weinhold	\param directory The add-on directory.
7796ba9af5aSIngo Weinhold	\param image Pointer to an image_id into which the image ID of the loaded
7806ba9af5aSIngo Weinhold		   add-on shall be written.
7816ba9af5aSIngo Weinhold	\return
7826ba9af5aSIngo Weinhold	- \c B_OK: Everything went fine.
7836ba9af5aSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: End of directory.
7846ba9af5aSIngo Weinhold	- other error codes
7856ba9af5aSIngo Weinhold*/
7866ba9af5aSIngo Weinholdstatus_t
7876ba9af5aSIngo WeinholdBDiskDeviceRoster::_GetNextAddOn(BDirectory *directory, AddOnImage *image)
7886ba9af5aSIngo Weinhold{
7896ba9af5aSIngo Weinhold	status_t error = (directory ? B_OK : B_ENTRY_NOT_FOUND);
7906ba9af5aSIngo Weinhold	if (error == B_OK) {
7916ba9af5aSIngo Weinhold		// iterate through the entry list and try to load the entries
7926ba9af5aSIngo Weinhold		bool found = false;
7936ba9af5aSIngo Weinhold		while (error == B_OK && !found) {
7946ba9af5aSIngo Weinhold			BEntry entry;
7956ba9af5aSIngo Weinhold			error = directory->GetNextEntry(&entry);
7966ba9af5aSIngo Weinhold			BPath path;
7976ba9af5aSIngo Weinhold			if (error == B_OK && entry.GetPath(&path) == B_OK)
7986ba9af5aSIngo Weinhold				found = (image->Load(path.Path()) == B_OK);
7996ba9af5aSIngo Weinhold		}
8006ba9af5aSIngo Weinhold	}
8016ba9af5aSIngo Weinhold	return error;
8026ba9af5aSIngo Weinhold}
8036ba9af5aSIngo Weinhold
80477e9b775SAxel Dörfler
8056ba9af5aSIngo Weinhold/*!	\brief Gets the next add-on directory path.
8066ba9af5aSIngo Weinhold	\param path Pointer to a BPath to be set to the found directory.
8076ba9af5aSIngo Weinhold	\param index Pointer to an index into the kAddOnDirs array indicating
8086ba9af5aSIngo Weinhold		   which add-on dir shall be retrieved next.
8096ba9af5aSIngo Weinhold	\param subdir Name of the subdirectory (in the "disk_scanner" subdirectory
8106ba9af5aSIngo Weinhold		   of the add-on directory) \a directory shall be set to.
8116ba9af5aSIngo Weinhold	\return
8126ba9af5aSIngo Weinhold	- \c B_OK: Everything went fine.
8136ba9af5aSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: End of directory list.
8146ba9af5aSIngo Weinhold	- other error codes
8156ba9af5aSIngo Weinhold*/
8166ba9af5aSIngo Weinholdstatus_t
8176ba9af5aSIngo WeinholdBDiskDeviceRoster::_GetNextAddOnDir(BPath *path, int32 *index,
81877e9b775SAxel Dörfler	const char *subdir)
8196ba9af5aSIngo Weinhold{
8206ba9af5aSIngo Weinhold	status_t error = (*index < kAddOnDirCount ? B_OK : B_ENTRY_NOT_FOUND);
8216ba9af5aSIngo Weinhold	// get the add-on dir path
8226ba9af5aSIngo Weinhold	if (error == B_OK) {
8236ba9af5aSIngo Weinhold		error = find_directory(kAddOnDirs[*index], path);
8246ba9af5aSIngo Weinhold		(*index)++;
8256ba9af5aSIngo Weinhold	}
8266ba9af5aSIngo Weinhold	// construct the subdirectory path
8276ba9af5aSIngo Weinhold	if (error == B_OK) {
8286ba9af5aSIngo Weinhold		error = path->Append("disk_scanner");
8296ba9af5aSIngo Weinhold		if (error == B_OK)
8306ba9af5aSIngo Weinhold			error = path->Append(subdir);
8316ba9af5aSIngo Weinhold	}
8329ca9a5bbSIngo Weinholdif (error == B_OK)
8339ca9a5bbSIngo Weinholdprintf("  next add-on dir: `%s'\n", path->Path());
8346ba9af5aSIngo Weinhold	return error;
8356ba9af5aSIngo Weinhold}
8366ba9af5aSIngo Weinhold
83777e9b775SAxel Dörfler
8386ba9af5aSIngo Weinhold/*!	\brief Gets the next add-on directory.
8396ba9af5aSIngo Weinhold	\param directory Pointer to a BDirectory* to be set to the found directory.
8406ba9af5aSIngo Weinhold	\param index Pointer to an index into the kAddOnDirs array indicating
8416ba9af5aSIngo Weinhold		   which add-on dir shall be retrieved next.
8426ba9af5aSIngo Weinhold	\param subdir Name of the subdirectory (in the "disk_scanner" subdirectory
8436ba9af5aSIngo Weinhold		   of the add-on directory) \a directory shall be set to.
8446ba9af5aSIngo Weinhold	\return
8456ba9af5aSIngo Weinhold	- \c B_OK: Everything went fine.
8466ba9af5aSIngo Weinhold	- \c B_ENTRY_NOT_FOUND: End of directory list.
8476ba9af5aSIngo Weinhold	- other error codes
8486ba9af5aSIngo Weinhold*/
8496ba9af5aSIngo Weinholdstatus_t
8506ba9af5aSIngo WeinholdBDiskDeviceRoster::_GetNextAddOnDir(BDirectory **directory, int32 *index,
85177e9b775SAxel Dörfler	const char *subdir)
8526ba9af5aSIngo Weinhold{
8536ba9af5aSIngo Weinhold	BPath path;
8546ba9af5aSIngo Weinhold	status_t error = _GetNextAddOnDir(&path, index, subdir);
8556ba9af5aSIngo Weinhold	// create a BDirectory object, if there is none yet.
8566ba9af5aSIngo Weinhold	if (error == B_OK && !*directory) {
8576ba9af5aSIngo Weinhold		*directory = new BDirectory;
8586ba9af5aSIngo Weinhold		if (!*directory)
8596ba9af5aSIngo Weinhold			error = B_NO_MEMORY;
8606ba9af5aSIngo Weinhold	}
8616ba9af5aSIngo Weinhold	// init the directory
8626ba9af5aSIngo Weinhold	if (error == B_OK)
8636ba9af5aSIngo Weinhold		error = (*directory)->SetTo(path.Path());
8646ba9af5aSIngo Weinhold	// cleanup on error
8656ba9af5aSIngo Weinhold	if (error != B_OK && *directory) {
8666ba9af5aSIngo Weinhold		delete *directory;
8676ba9af5aSIngo Weinhold		*directory = NULL;
8686ba9af5aSIngo Weinhold	}
8696ba9af5aSIngo Weinhold	return error;
8706ba9af5aSIngo Weinhold}
8716ba9af5aSIngo Weinhold
87277e9b775SAxel Dörfler
8736ba9af5aSIngo Weinholdstatus_t
8746ba9af5aSIngo WeinholdBDiskDeviceRoster::_LoadPartitionAddOn(const char *partitioningSystem,
87577e9b775SAxel Dörfler	AddOnImage *image, BDiskScannerPartitionAddOn **_addOn)
8766ba9af5aSIngo Weinhold{
87777e9b775SAxel Dörfler	status_t error = partitioningSystem && image && _addOn
87877e9b775SAxel Dörfler		? B_OK : B_BAD_VALUE;
87977e9b775SAxel Dörfler
8806ba9af5aSIngo Weinhold	// load the image
8816ba9af5aSIngo Weinhold	bool found = false;
8826ba9af5aSIngo Weinhold	BPath path;
8836ba9af5aSIngo Weinhold	BDirectory *directory = NULL;
8846ba9af5aSIngo Weinhold	int32 index = 0;
8856ba9af5aSIngo Weinhold	while (error == B_OK && !found) {
8866ba9af5aSIngo Weinhold		error = _GetNextAddOn(&directory, &index, "partition", image);
8876ba9af5aSIngo Weinhold		if (error == B_OK) {
8886ba9af5aSIngo Weinhold			// add-on loaded: get the function that creates an add-on
8896ba9af5aSIngo Weinhold			// object
8906ba9af5aSIngo Weinhold			BDiskScannerPartitionAddOn *(*create_add_on)();
8916ba9af5aSIngo Weinhold			if (get_image_symbol(image->ID(), "create_ds_partition_add_on",
8926ba9af5aSIngo Weinhold								 B_SYMBOL_TYPE_TEXT,
8936ba9af5aSIngo Weinhold								 (void**)&create_add_on) == B_OK) {
8946ba9af5aSIngo Weinhold				// create the add-on object and copy the requested data
8956ba9af5aSIngo Weinhold				if (BDiskScannerPartitionAddOn *addOn = (*create_add_on)()) {
8966ba9af5aSIngo Weinhold					if (!strcmp(addOn->ShortName(), partitioningSystem)) {
8976ba9af5aSIngo Weinhold						*_addOn = addOn;
8986ba9af5aSIngo Weinhold						found = true;
8996ba9af5aSIngo Weinhold					} else
9006ba9af5aSIngo Weinhold						delete addOn;
9016ba9af5aSIngo Weinhold				}
9026ba9af5aSIngo Weinhold			}
9036ba9af5aSIngo Weinhold		}
9046ba9af5aSIngo Weinhold	}
9056ba9af5aSIngo Weinhold	// cleanup
9066ba9af5aSIngo Weinhold	if (directory)
9076ba9af5aSIngo Weinhold		delete directory;
9086ba9af5aSIngo Weinhold	if (error != B_OK && image)
9096ba9af5aSIngo Weinhold		image->Unload();
9106ba9af5aSIngo Weinhold	return error;
9116ba9af5aSIngo Weinhold}
9126ba9af5aSIngo Weinhold
9135c7270efSIngo Weinhold#endif	// 0
914