xref: /haiku/src/kits/storage/VolumeRoster.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
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 
24 static const char kBootVolumePath[] = "/boot";
25 
26 using namespace std;
27 
28 #ifdef USE_OPENBEOS_NAMESPACE
29 namespace 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 */
65 BVolumeRoster::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 */
76 BVolumeRoster::~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 */
89 status_t
90 BVolumeRoster::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 */
111 void
112 BVolumeRoster::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 */
130 status_t
131 BVolumeRoster::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 */
169 status_t
170 BVolumeRoster::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 */
194 void
195 BVolumeRoster::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 */
210 BMessenger
211 BVolumeRoster::Messenger() const
212 {
213 	return (fTarget ? *fTarget : BMessenger());
214 }
215 
216 // FBC
217 void BVolumeRoster::_SeveredVRoster1() {}
218 void BVolumeRoster::_SeveredVRoster2() {}
219 
220 #ifdef USE_OPENBEOS_NAMESPACE
221 }
222 #endif
223