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