MediaDISK.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00013 #include "zypp/base/Logger.h"
00014 #include "zypp/base/String.h"
00015 #include "zypp/media/Mount.h"
00016 #include "zypp/media/MediaDISK.h"
00017 #include "zypp/media/MediaManager.h"
00018
00019 #include <iostream>
00020 #include <fstream>
00021 #include <sstream>
00022
00023 #include <sys/types.h>
00024 #include <sys/mount.h>
00025 #include <errno.h>
00026 #include <dirent.h>
00027
00028
00029
00030
00031 #define DELAYED_VERIFY 1
00032
00033 using namespace std;
00034
00035 namespace zypp {
00036 namespace media {
00037
00039
00040
00041
00043
00045
00046
00047
00048
00049
00050
00051
00052 MediaDISK::MediaDISK( const Url & url_r,
00053 const Pathname & attach_point_hint_r )
00054 : MediaHandler( url_r, attach_point_hint_r,
00055 url_r.getPathName(),
00056 false )
00057 {
00058 MIL << "MediaDISK::MediaDISK(" << url_r << ", " << attach_point_hint_r << ")" << endl;
00059
00060 _device = Pathname(_url.getQueryParam("device")).asString();
00061 if( _device.empty())
00062 {
00063 ERR << "Media url does not contain a device specification" << std::endl;
00064 ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
00065 }
00066 #if DELAYED_VERIFY
00067 DBG << "Verify of " << _device << " delayed" << std::endl;
00068 #else
00069 if( !verifyIfDiskVolume( _device))
00070 {
00071 ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
00072 }
00073 #endif
00074
00075 _filesystem = _url.getQueryParam("filesystem");
00076 if(_filesystem.empty())
00077 _filesystem="auto";
00078
00079 }
00080
00082
00083
00084
00085
00086
00087
00088
00089 bool MediaDISK::verifyIfDiskVolume(const Pathname &dev_name)
00090 {
00091 if( dev_name.empty() ||
00092 dev_name.asString().compare(0, sizeof("/dev/")-1, "/dev/"))
00093 {
00094 ERR << "Specified device name " << dev_name
00095 << " is not allowed" << std::endl;
00096 return false;
00097 }
00098
00099 PathInfo dev_info(dev_name);
00100 if( !dev_info.isBlk())
00101 {
00102 ERR << "Specified device name " << dev_name
00103 << " is not a block device" << std::endl;
00104 return false;
00105 }
00106
00107
00108 {
00109 Pathname dpath("/dev/disk/by-uuid");
00110 std::list<Pathname> dlist;
00111 if( zypp::filesystem::readdir(dlist, dpath) == 0)
00112 {
00113 std::list<Pathname>::const_iterator it;
00114 for(it = dlist.begin(); it != dlist.end(); ++it)
00115 {
00116 PathInfo vol_info(*it);
00117 if( vol_info.isBlk() && vol_info.major() == dev_info.major() &&
00118 vol_info.minor() == dev_info.minor())
00119 {
00120 DBG << "Specified device name " << dev_name
00121 << " is a volume (disk/by-uuid link "
00122 << vol_info.path() << ")"
00123 << std::endl;
00124 return true;
00125 }
00126 }
00127 }
00128 }
00129
00130
00131
00132 {
00133 Pathname dpath("/dev/disk/by-label");
00134 std::list<Pathname> dlist;
00135 if( zypp::filesystem::readdir(dlist, dpath) == 0)
00136 {
00137 std::list<Pathname>::const_iterator it;
00138 for(it = dlist.begin(); it != dlist.end(); ++it)
00139 {
00140 PathInfo vol_info(*it);
00141 if( vol_info.isBlk() && vol_info.major() == dev_info.major() &&
00142 vol_info.minor() == dev_info.minor())
00143 {
00144 DBG << "Specified device name " << dev_name
00145 << " is a volume (disk/by-label link "
00146 << vol_info.path() << ")"
00147 << std::endl;
00148 return true;
00149 }
00150 }
00151 }
00152 }
00153
00154
00155
00156 ExternalProgram::Arguments args;
00157 args.push_back( "blkid" );
00158 args.push_back( "-p" );
00159 args.push_back( dev_name.asString() );
00160
00161 ExternalProgram cmd( args, ExternalProgram::Stderr_To_Stdout );
00162 cmd >> DBG;
00163 if ( cmd.close() != 0 )
00164 {
00165 ERR << cmd.execError() << endl
00166 << "Specified device name " << dev_name
00167 << " is not a usable disk volume"
00168 << std::endl;
00169 return false;
00170 }
00171 return true;
00172 }
00173
00175
00176
00177
00178
00179
00180
00181
00182 void MediaDISK::attachTo(bool next)
00183 {
00184 if(next)
00185 ZYPP_THROW(MediaNotSupportedException(url()));
00186
00187
00188
00189
00190
00191
00192 if(_device.empty())
00193 ZYPP_THROW(MediaBadUrlEmptyDestinationException(url()));
00194
00195 PathInfo dev_info(_device);
00196 if(!dev_info.isBlk())
00197 ZYPP_THROW(MediaBadUrlEmptyDestinationException(url()));
00198 #if DELAYED_VERIFY
00199 DBG << "Verifying " << _device << " ..." << std::endl;
00200 if( !verifyIfDiskVolume( _device))
00201 {
00202 ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
00203 }
00204 #endif
00205
00206 if(_filesystem.empty())
00207 ZYPP_THROW(MediaBadUrlEmptyFilesystemException(url()));
00208
00209 MediaSourceRef media( new MediaSource(
00210 "disk", _device, dev_info.major(), dev_info.minor()
00211 ));
00212 AttachedMedia ret( findAttachedMedia( media));
00213
00214 if( ret.mediaSource &&
00215 ret.attachPoint &&
00216 !ret.attachPoint->empty())
00217 {
00218 DBG << "Using a shared media "
00219 << ret.mediaSource->name
00220 << " attached on "
00221 << ret.attachPoint->path
00222 << endl;
00223
00224 removeAttachPoint();
00225 setAttachPoint(ret.attachPoint);
00226 setMediaSource(ret.mediaSource);
00227 return;
00228 }
00229
00230 MediaManager manager;
00231 MountEntries entries( manager.getMountEntries());
00232 MountEntries::const_iterator e;
00233 for( e = entries.begin(); e != entries.end(); ++e)
00234 {
00235 bool is_device = false;
00236 std::string dev_path(Pathname(e->src).asString());
00237 PathInfo dev_info;
00238
00239 if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
00240 dev_info(e->src) && dev_info.isBlk())
00241 {
00242 is_device = true;
00243 }
00244
00245 if( is_device && media->maj_nr == dev_info.major() &&
00246 media->min_nr == dev_info.minor())
00247 {
00248 AttachPointRef ap( new AttachPoint(e->dir, false));
00249 AttachedMedia am( media, ap);
00250 {
00251 DBG << "Using a system mounted media "
00252 << media->name
00253 << " attached on "
00254 << ap->path
00255 << endl;
00256
00257 media->iown = false;
00258
00259 setMediaSource(media);
00260 setAttachPoint(ap);
00261 return;
00262 }
00263 }
00264 }
00265
00266 Mount mount;
00267 std::string mountpoint = attachPoint().asString();
00268 if( !isUseableAttachPoint(attachPoint()))
00269 {
00270 mountpoint = createAttachPoint().asString();
00271 if( mountpoint.empty())
00272 ZYPP_THROW( MediaBadAttachPointException(url()));
00273 setAttachPoint( mountpoint, true);
00274 }
00275
00276 string options = _url.getQueryParam("mountoptions");
00277 if(options.empty())
00278 {
00279 options = "ro";
00280 }
00281
00282 if( !media->bdir.empty())
00283 {
00284 options += ",bind";
00285 mount.mount(media->bdir, mountpoint, "none", options);
00286 }
00287 else
00288 {
00289 mount.mount(_device, mountpoint, _filesystem, options);
00290 }
00291
00292 setMediaSource(media);
00293
00294
00295
00296 int limit = 3;
00297 bool mountsucceeded;
00298 while( !(mountsucceeded=isAttached()) && --limit)
00299 {
00300 sleep(1);
00301 }
00302
00303 if( !mountsucceeded)
00304 {
00305 setMediaSource(MediaSourceRef());
00306 try
00307 {
00308 mount.umount(attachPoint().asString());
00309 }
00310 catch (const MediaException & excpt_r)
00311 {
00312 ZYPP_CAUGHT(excpt_r);
00313 }
00314 ZYPP_THROW(MediaMountException(
00315 "Unable to verify that the media was mounted",
00316 _device, mountpoint
00317 ));
00318 }
00319 }
00320
00322
00323
00324
00325
00326
00327
00328 bool
00329 MediaDISK::isAttached() const
00330 {
00331 return checkAttached(false);
00332 }
00333
00335
00336
00337
00338
00339
00340
00341
00342 void MediaDISK::releaseFrom( const std::string & ejectDev )
00343 {
00344 AttachedMedia am( attachedMedia());
00345 if(am.mediaSource && am.mediaSource->iown)
00346 {
00347 Mount mount;
00348 mount.umount(attachPoint().asString());
00349 }
00350 }
00351
00353
00354
00355
00356
00357
00358
00359 void MediaDISK::getFile (const Pathname & filename) const
00360 {
00361 MediaHandler::getFile( filename );
00362 }
00363
00365
00366
00367
00368
00369
00370
00371 void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const
00372 {
00373 MediaHandler::getDir( dirname, recurse_r );
00374 }
00375
00377
00378
00379
00380
00381
00382
00383
00384 void MediaDISK::getDirInfo( std::list<std::string> & retlist,
00385 const Pathname & dirname, bool dots ) const
00386 {
00387 MediaHandler::getDirInfo( retlist, dirname, dots );
00388 }
00389
00391
00392
00393
00394
00395
00396
00397
00398 void MediaDISK::getDirInfo( filesystem::DirContent & retlist,
00399 const Pathname & dirname, bool dots ) const
00400 {
00401 MediaHandler::getDirInfo( retlist, dirname, dots );
00402 }
00403
00404 bool MediaDISK::getDoesFileExist( const Pathname & filename ) const
00405 {
00406 return MediaHandler::getDoesFileExist( filename );
00407 }
00408
00409 }
00410 }
00411