1// ----------------------------------------------------------------------
2//  This software is part of the OpenBeOS distribution and is covered
3//  by the OpenBeOS license.
4//
5//  File Name:		VolumeRoster.cpp
6//
7//	Description:	BVolumeRoster class
8// ----------------------------------------------------------------------
9/*!
10	\file VolumeRoster.cpp
11	BVolumeRoster implementation.
12*/
13
14#include <errno.h>
15#include <new>
16
17#include <Bitmap.h>
18#include <Directory.h>
19#include <fs_info.h>
20#include <Node.h>
21#include <NodeMonitor.h>
22#include <VolumeRoster.h>
23
24static const char kBootVolumePath[] = "/boot";
25
26using namespace std;
27
28#ifdef USE_OPENBEOS_NAMESPACE
29namespace OpenBeOS {
30#endif
31
32/*!
33	\class BVolumeRoster
34	\brief A roster of all volumes available in the system
35
36	Provides an interface for iterating through the volumes available in
37	the system and watching volume mounting/unmounting.
38
39	The class wraps the next_dev() function for iterating through the
40	volume list and the watch_node()/stop_watching() for the watching
41	features.
42
43	\author Vincent Dominguez
44	\author <a href='mailto:bonefish@users.sf.net'>Ingo Weinhold</a>
45
46	\version 0.0.0
47*/
48
49/*!	\var dev_t BVolumeRoster::fCookie
50	\brief The iteration cookie for next_dev(). Initialized with 0.
51*/
52
53/*!	\var dev_t BVolumeRoster::fTarget
54	\brief BMessenger referring to the target to which the watching
55		   notification messages are sent.
56
57	The object is allocated and owned by the roster. \c NULL, if not watching.
58*/
59
60// constructor
61/*!	\brief Creates a new BVolumeRoster.
62
63	The object is ready to be used.
64*/
65BVolumeRoster::BVolumeRoster()
66	: fCookie(0),
67	  fTarget(NULL)
68{
69}
70
71// destructor
72/*!	\brief Frees all resources associated with this object.
73
74	If a watching was activated on (StartWatching()), it is deactived.
75*/
76BVolumeRoster::~BVolumeRoster()
77{
78	StopWatching();
79}
80
81// GetNextVolume
82/*!	\brief Returns the next volume in the list of available volumes.
83	\param volume A pointer to a pre-allocated BVolume to be initialized to
84		   refer to the next volume in the list of available volumes.
85	\return
86	- \c B_OK: Everything went fine.
87	- \c B_BAD_VALUE: The last volume in the list has already been returned.
88*/
89status_t
90BVolumeRoster::GetNextVolume(BVolume *volume)
91{
92	// check parameter
93	status_t error = (volume ? B_OK : B_BAD_VALUE);
94	// get next device
95	dev_t device;
96	if (error == B_OK) {
97		device = next_dev(&fCookie);
98		if (device < 0)
99			error = device;
100	}
101	// init volume
102	if (error == B_OK)
103		error = volume->SetTo(device);
104	return error;
105}
106
107// Rewind
108/*! \brief Rewinds the list of available volumes such that the next call to
109		   GetNextVolume() will return the first element in the list.
110*/
111void
112BVolumeRoster::Rewind()
113{
114	fCookie = 0;
115}
116
117// GetBootVolume
118/*!	\brief Returns the boot volume.
119
120	Currently, this function looks for the volume that is mounted at "/boot".
121	The only way to fool the system into thinking that there is not a boot
122	volume is to rename "/boot" -- but, please refrain from doing so...(:o(
123
124	\param volume A pointer to a pre-allocated BVolume to be initialized to
125		   refer to the boot volume.
126	\return
127	- \c B_OK: Everything went fine.
128	- an error code otherwise
129*/
130status_t
131BVolumeRoster::GetBootVolume(BVolume *volume)
132{
133	// check parameter
134	status_t error = (volume ? B_OK : B_BAD_VALUE);
135	// get device
136	dev_t device;
137	if (error == B_OK) {
138		device = dev_for_path(kBootVolumePath);
139		if (device < 0)
140			error = device;
141	}
142	// init volume
143	if (error == B_OK)
144		error = volume->SetTo(device);
145	return error;
146}
147
148// StartWatching
149/*!	\brief Starts watching the list of volumes available in the system.
150
151	Notifications are sent to the specified target whenever a volume is
152	mounted or unmounted. The format of the notification messages is
153	described under watch_node(). Actually BVolumeRoster just provides a
154	more convenient interface for it.
155
156	If StartWatching() has been called before with another target and no
157	StopWatching() since, StopWatching() is called first, so that the former
158	target won't receive any notifications anymore.
159
160	When the object is destroyed all watching has an end as well.
161
162	\param messenger The target to which the notification messages shall be
163		   sent.
164	\return
165	- \c B_OK: Everything went fine.
166	- \c B_BAD_VALUE: The supplied BMessenger is invalid.
167	- \c B_NO_MEMORY: Insufficient memory to carry out this operation.
168*/
169status_t
170BVolumeRoster::StartWatching(BMessenger messenger)
171{
172	StopWatching();
173	status_t error = (messenger.IsValid() ? B_OK : B_ERROR);
174	// clone messenger
175	if (error == B_OK) {
176		fTarget = new(nothrow) BMessenger(messenger);
177		if (!fTarget)
178			error = B_NO_MEMORY;
179	}
180	// start watching
181	if (error == B_OK)
182		error = watch_node(NULL, B_WATCH_MOUNT, messenger);
183	// cleanup on failure
184	if (error != B_OK && fTarget) {
185		delete fTarget;
186		fTarget = NULL;
187	}
188	return error;
189}
190
191// StopWatching
192/*!	\brief Stops volume watching initiated with StartWatching() before.
193*/
194void
195BVolumeRoster::StopWatching()
196{
197	if (fTarget) {
198		stop_watching(*fTarget);
199		delete fTarget;
200		fTarget = NULL;
201	}
202}
203
204// Messenger
205/*!	\brief Returns a messenger to the target currently watching the volume
206		   list.
207	\return A messenger to the target currently watching the volume list, or
208			an invalid messenger, if noone is currently watching.
209*/
210BMessenger
211BVolumeRoster::Messenger() const
212{
213	return (fTarget ? *fTarget : BMessenger());
214}
215
216// FBC
217void BVolumeRoster::_SeveredVRoster1() {}
218void BVolumeRoster::_SeveredVRoster2() {}
219
220#ifdef USE_OPENBEOS_NAMESPACE
221}
222#endif
223