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