xref: /haiku/src/kits/storage/Volume.cpp (revision 31f5d420edd1625a5c211fceee69e943677593d2)
1 // ----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //
5 //  File Name:		Volume.cpp
6 //
7 //	Description:	BVolume class
8 // ----------------------------------------------------------------------
9 /*!
10 	\file Volume.h
11 	BVolume implementation.
12 */
13 
14 #include <errno.h>
15 
16 #include <Bitmap.h>
17 #include <Directory.h>
18 #include <fs_info.h>
19 #include <kernel_interface.h>
20 #include <Node.h>
21 #include <Volume.h>
22 
23 
24 #ifdef USE_OPENBEOS_NAMESPACE
25 namespace OpenBeOS {
26 #endif
27 
28 /*!
29 	\class BVolume
30 	\brief Represents a disk volume
31 
32 	Provides an interface for querying information about a volume.
33 
34 	The class is a simple wrapper for a \c dev_t and the function
35 	fs_stat_dev. The only exception is the method is SetName(), which
36 	sets the name of the volume.
37 
38 	\author Vincent Dominguez
39 	\author <a href='mailto:bonefish@users.sf.net'>Ingo Weinhold</a>
40 
41 	\version 0.0.0
42 */
43 
44 /*!	\var dev_t BVolume::fDevice
45 	\brief The volume's device ID.
46 */
47 
48 /*!	\var dev_t BVolume::fCStatus
49 	\brief The object's initialization status.
50 */
51 
52 // constructor
53 /*!	\brief Creates an uninitialized BVolume.
54 
55 	InitCheck() will return \c B_NO_INIT.
56 */
57 BVolume::BVolume()
58 	: fDevice(-1),
59 	  fCStatus(B_NO_INIT)
60 {
61 }
62 
63 // constructor
64 /*!	\brief Creates a BVolume and initializes it to the volume specified
65 		   by the supplied device ID.
66 
67 	InitCheck() should be called to check whether the initialization was
68 	successful.
69 
70 	\param device The device ID of the volume.
71 */
72 BVolume::BVolume(dev_t device)
73 	: fDevice(-1),
74 	  fCStatus(B_NO_INIT)
75 {
76 	SetTo(device);
77 }
78 
79 // copy constructor
80 /*!	\brief Creates a BVolume and makes it a clone of the supplied one.
81 
82 	Afterwards the object refers to the same device the supplied object
83 	does. If the latter is not properly initialized, this object isn't
84 	either.
85 
86 	\param volume The volume object to be cloned.
87 */
88 BVolume::BVolume(const BVolume &volume)
89 	: fDevice(volume.fDevice),
90 	  fCStatus(volume.fCStatus)
91 {
92 }
93 
94 // destructor
95 /*!	\brief Frees all resources associated with the object.
96 
97 	Does nothing.
98 */
99 BVolume::~BVolume()
100 {
101 }
102 
103 // InitCheck
104 /*!	\brief Returns the result of the last initialization.
105 	\return
106 	- \c B_OK: The object is properly initialized.
107 	- an error code otherwise
108 */
109 status_t
110 BVolume::InitCheck(void) const
111 {
112 	return fCStatus;
113 }
114 
115 // SetTo
116 /*!	\brief Re-initializes the object to refer to the volume specified by
117 		   the supplied device ID.
118 	\param device The device ID of the volume.
119 	\param
120 	- \c B_OK: Everything went fine.
121 	- an error code otherwise
122 */
123 status_t
124 BVolume::SetTo(dev_t device)
125 {
126 	// uninitialize
127 	Unset();
128 	// check the parameter
129 	status_t error = (device >= 0 ? B_OK : B_BAD_VALUE);
130 	if (error == B_OK) {
131 		fs_info info;
132 		if (fs_stat_dev(device, &info) != 0)
133 			error = errno;
134 	}
135 	// set the new value
136 	if (error == B_OK)
137 		fDevice = device;
138 	// set the init status variable
139 	fCStatus = error;
140 	return fCStatus;
141 }
142 
143 // Unset
144 /*!	\brief Uninitialized the BVolume.
145 */
146 void
147 BVolume::Unset()
148 {
149 	fDevice = -1;
150 	fCStatus = B_NO_INIT;
151 }
152 
153 // Device
154 /*!	\brief Returns the device ID of the volume the object refers to.
155 	\return Returns the device ID of the volume the object refers to
156 			or -1, if the object is not properly initialized.
157 */
158 dev_t
159 BVolume::Device() const
160 {
161 	return fDevice;
162 }
163 
164 // GetRootDirectory
165 /*!	\brief Returns the root directory of the volume referred to by the object.
166 	\param directory A pointer to a pre-allocated BDirectory to be initialized
167 		   to the volume's root directory.
168 	\return
169 	- \c B_OK: Everything went fine.
170 	- \c B_BAD_VALUE: \c NULL \a directory or the object is not properly
171 	  initialized.
172 	- another error code
173 */
174 status_t
175 BVolume::GetRootDirectory(BDirectory *directory) const
176 {
177 	// check parameter and initialization
178 	status_t error = (directory && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
179 	// get FS stat
180 	fs_info info;
181 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
182 		error = errno;
183 	// init the directory
184 	if (error == B_OK) {
185 		node_ref ref;
186 		ref.device = info.dev;
187 		ref.node = info.root;
188 		error = directory->SetTo(&ref);
189 	}
190 	return error;
191 }
192 
193 // Capacity
194 /*!	\brief Returns the volume's total storage capacity.
195 	\return
196 	- The volume's total storage capacity (in bytes), when the object is
197 	  properly initialized.
198 	- \c B_BAD_VALUE otherwise.
199 */
200 off_t
201 BVolume::Capacity() const
202 {
203 	// check initialization
204 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
205 	// get FS stat
206 	fs_info info;
207 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
208 		error = errno;
209 	return (error == B_OK ? info.total_blocks * info.block_size : error);
210 }
211 
212 // FreeBytes
213 /*!	\brief Returns the amount of storage that's currently unused on the
214 		   volume (in bytes).
215 	\return
216 	- The amount of storage that's currently unused on the volume (in bytes),
217 	  when the object is properly initialized.
218 	- \c B_BAD_VALUE otherwise.
219 */
220 off_t
221 BVolume::FreeBytes() const
222 {
223 	// check initialization
224 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
225 	// get FS stat
226 	fs_info info;
227 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
228 		error = errno;
229 	return (error == B_OK ? info.free_blocks * info.block_size : error);
230 }
231 
232 // GetName
233 /*!	\brief Returns the name of the volume.
234 
235 	The name of the volume is copied into the provided buffer.
236 
237 	\param name A pointer to a pre-allocated character buffer of size
238 		   \c B_FILE_NAME_LENGTH or larger into which the name of the
239 		   volume shall be written.
240 	\return
241 	- \c B_OK: Everything went fine.
242 	- \c B_BAD_VALUE: \c NULL \a name or the object is not properly
243 	  initialized.
244 	- another error code
245 */
246 status_t
247 BVolume::GetName(char *name) const
248 {
249 	// check parameter and initialization
250 	status_t error = (name && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
251 	// get FS stat
252 	fs_info info;
253 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
254 		error = errno;
255 	// copy the name
256 	if (error == B_OK)
257 		strncpy(name, info.volume_name, B_FILE_NAME_LENGTH);
258 	return error;
259 }
260 
261 // SetName
262 /*!	\brief Sets the name of the volume referred to by this object.
263 	\param name The volume's new name. Must not be longer than
264 		   \c B_FILE_NAME_LENGTH (including the terminating null).
265 	\return
266 	- \c B_OK: Everything went fine.
267 	- \c B_BAD_VALUE: \c NULL \a name or the object is not properly
268 	  initialized.
269 	- another error code
270 */
271 status_t
272 BVolume::SetName(const char *name)
273 {
274 	// check initialization
275 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
276 	if (error == B_OK)
277 		error = BPrivate::Storage::set_volume_name(fDevice, name);
278 	return error;
279 }
280 
281 // GetIcon
282 /*!	\brief Returns the icon of the volume.
283 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
284 		   to store the requested icon (16x16 for the mini and 32x32 for the
285 		   large icon).
286 	\param which Specifies the size of the icon to be retrieved:
287 		   \c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon.
288 */
289 status_t
290 BVolume::GetIcon(BBitmap *icon, icon_size which) const
291 {
292 	// check parameter and initialization
293 	status_t error = (icon && InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
294 	BRect rect;
295 	if (error == B_OK) {
296 		if (which == B_MINI_ICON)
297 			rect.Set(0, 0, 15, 15);
298 		else if (which == B_LARGE_ICON)
299 			rect.Set(0, 0, 31, 31);
300 		else
301 			error = B_BAD_VALUE;
302 	}
303 	// check whether icon size and bitmap dimensions do match
304 	if (error == B_OK
305 		&& (icon->Bounds() != rect || icon->ColorSpace() != B_CMAP8)) {
306 		error = B_BAD_VALUE;
307 	}
308 	// get FS stat
309 	fs_info info;
310 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
311 		error = errno;
312 	// get the icon
313 	if (error == B_OK)
314 		error = get_device_icon(info.device_name, icon->Bits(), which);
315 	return error;
316 }
317 
318 // IsRemovable
319 /*!	\brief Returns whether the volume is removable.
320 	\return \c true, when the object is properly initialized and the
321 	referred to volume is removable, \c false otherwise.
322 */
323 bool
324 BVolume::IsRemovable() const
325 {
326 	// check initialization
327 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
328 	// get FS stat
329 	fs_info info;
330 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
331 		error = errno;
332 	return (error == B_OK && (info.flags & B_FS_IS_REMOVABLE));
333 }
334 
335 // IsReadOnly
336 /*!	\brief Returns whether the volume is read only.
337 	\return \c true, when the object is properly initialized and the
338 	referred to volume is read only, \c false otherwise.
339 */
340 bool
341 BVolume::IsReadOnly(void) const
342 {
343 	// check initialization
344 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
345 	// get FS stat
346 	fs_info info;
347 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
348 		error = errno;
349 	return (error == B_OK && (info.flags & B_FS_IS_READONLY));
350 }
351 
352 // IsPersistent
353 /*!	\brief Returns whether the volume is persistent.
354 	\return \c true, when the object is properly initialized and the
355 	referred to volume is persistent, \c false otherwise.
356 */
357 bool
358 BVolume::IsPersistent(void) const
359 {
360 	// check initialization
361 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
362 	// get FS stat
363 	fs_info info;
364 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
365 		error = errno;
366 	return (error == B_OK && (info.flags & B_FS_IS_PERSISTENT));
367 }
368 
369 // IsShared
370 /*!	\brief Returns whether the volume is shared.
371 	\return \c true, when the object is properly initialized and the
372 	referred to volume is shared, \c false otherwise.
373 */
374 bool
375 BVolume::IsShared(void) const
376 {
377 	// check initialization
378 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
379 	// get FS stat
380 	fs_info info;
381 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
382 		error = errno;
383 	return (error == B_OK && (info.flags & B_FS_IS_SHARED));
384 }
385 
386 // KnowsMime
387 /*!	\brief Returns whether the volume supports MIME types.
388 	\return \c true, when the object is properly initialized and the
389 	referred to volume supports MIME types, \c false otherwise.
390 */
391 bool
392 BVolume::KnowsMime(void) const
393 {
394 	// check initialization
395 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
396 	// get FS stat
397 	fs_info info;
398 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
399 		error = errno;
400 	return (error == B_OK && (info.flags & B_FS_HAS_MIME));
401 }
402 
403 // KnowsAttr
404 /*!	\brief Returns whether the volume supports attributes.
405 	\return \c true, when the object is properly initialized and the
406 	referred to volume supports attributes, \c false otherwise.
407 */
408 bool
409 BVolume::KnowsAttr(void) const
410 {
411 	// check initialization
412 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
413 	// get FS stat
414 	fs_info info;
415 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
416 		error = errno;
417 	return (error == B_OK && (info.flags & B_FS_HAS_ATTR));
418 }
419 
420 // KnowsQuery
421 /*!	\brief Returns whether the volume supports queries.
422 	\return \c true, when the object is properly initialized and the
423 	referred to volume supports queries, \c false otherwise.
424 */
425 bool
426 BVolume::KnowsQuery(void) const
427 {
428 	// check initialization
429 	status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
430 	// get FS stat
431 	fs_info info;
432 	if (error == B_OK && fs_stat_dev(fDevice, &info) != 0)
433 		error = errno;
434 	return (error == B_OK && (info.flags & B_FS_HAS_QUERY));
435 }
436 
437 // ==
438 /*!	\brief Returns whether two BVolume objects are equal.
439 
440 	Two volume objects are said to be equal, if they either are both
441 	uninitialized, or both are initialized and refer to the same volume.
442 
443 	\param volume The object to be compared with.
444 	\result \c true, if this object and the supplied one are equal, \c false
445 			otherwise.
446 */
447 bool
448 BVolume::operator==(const BVolume &volume) const
449 {
450 	return (InitCheck() != B_OK && volume.InitCheck() != B_OK
451 			|| fDevice == volume.fDevice);
452 }
453 
454 // !=
455 /*!	\brief Returns whether two BVolume objects are unequal.
456 
457 	Two volume objects are said to be equal, if they either are both
458 	uninitialized, or both are initialized and refer to the same volume.
459 
460 	\param volume The object to be compared with.
461 	\result \c true, if this object and the supplied one are unequal, \c false
462 			otherwise.
463 */
464 bool
465 BVolume::operator!=(const BVolume &volume) const
466 {
467 	return !(*this == volume);
468 }
469 
470 // =
471 /*!	\brief Assigns another BVolume object to this one.
472 
473 	This object is made an exact clone of the supplied one.
474 
475 	\param volume The volume from which shall be assigned.
476 	\return A reference to this object.
477 */
478 BVolume&
479 BVolume::operator=(const BVolume &volume)
480 {
481 	if (&volume != this) {
482 		this->fDevice = volume.fDevice;
483 		this->fCStatus = volume.fCStatus;
484 	}
485 	return *this;
486 }
487 
488 
489 // FBC
490 void BVolume::_ReservedVolume1() {}
491 void BVolume::_ReservedVolume2() {}
492 void BVolume::_ReservedVolume3() {}
493 void BVolume::_ReservedVolume4() {}
494 void BVolume::_ReservedVolume5() {}
495 void BVolume::_ReservedVolume6() {}
496 void BVolume::_ReservedVolume7() {}
497 void BVolume::_ReservedVolume8() {}
498 
499 #ifdef USE_OPENBEOS_NAMESPACE
500 }
501 #endif
502