MediaCD.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 extern "C"
00013 {
00014 #include <sys/ioctl.h>
00015 #include <linux/cdrom.h>
00016 #if HAVE_UDEV
00017 #include <libudev.h>
00018 #endif
00019 }
00020 
00021 #ifndef HAVE_UDEV
00022 #if HAVE_HAL
00023 #include "zypp/target/hal/HalContext.h"
00024 #endif
00025 #endif
00026 
00027 #include <cstring> // strerror
00028 #include <cstdlib> // getenv
00029 #include <iostream>
00030 
00031 #include "zypp/base/Logger.h"
00032 #include "zypp/ExternalProgram.h"
00033 #include "zypp/media/Mount.h"
00034 #include "zypp/media/MediaCD.h"
00035 #include "zypp/media/MediaManager.h"
00036 #include "zypp/Url.h"
00037 #include "zypp/AutoDispose.h"
00038 
00039 
00040 
00041 /*
00042 ** if to throw exception on eject errors or ignore them
00043 */
00044 #define  REPORT_EJECT_ERRORS     1
00045 
00046 /*
00047 ** If defined to the full path of the eject utility,
00048 ** it will be used additionally to the eject-ioctl.
00049 */
00050 #define EJECT_TOOL_PATH "/bin/eject"
00051 
00052 
00053 using namespace std;
00054 
00056 namespace zypp
00057 {
00059   namespace media
00060   {
00061 
00063     namespace
00064     {
00065       typedef std::list<MediaSource> DeviceList;
00066 
00076       DeviceList systemDetectDevices( bool supportingDVD_r )
00077       {
00078         DeviceList detected;
00079 
00080 #ifdef HAVE_UDEV
00081         // http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/index.html
00082         zypp::AutoDispose<struct udev *> udev( ::udev_new(), ::udev_unref );
00083         if ( ! udev )
00084         {
00085           ERR << "Can't create udev context." << endl;
00086           return DeviceList();
00087         }
00088 
00089         zypp::AutoDispose<struct udev_enumerate *> enumerate( ::udev_enumerate_new(udev), ::udev_enumerate_unref );
00090         if ( ! enumerate )
00091         {
00092           ERR << "Can't create udev list entry." << endl;
00093           return DeviceList();
00094         }
00095 
00096         ::udev_enumerate_add_match_subsystem( enumerate, "block" );
00097         ::udev_enumerate_add_match_property( enumerate, "ID_CDROM", "1" );
00098         ::udev_enumerate_scan_devices( enumerate );
00099 
00100         struct udev_list_entry * entry = 0;
00101         udev_list_entry_foreach( entry, ::udev_enumerate_get_list_entry( enumerate ) )
00102         {
00103           zypp::AutoDispose<struct udev_device *> device( ::udev_device_new_from_syspath( ::udev_enumerate_get_udev( enumerate ),
00104                                                                                           ::udev_list_entry_get_name( entry ) ),
00105                                                           ::udev_device_unref );
00106           if ( ! device )
00107           {
00108             ERR << "Can't create udev device." << endl;
00109             continue;
00110           }
00111 
00112           if ( supportingDVD_r && ! ::udev_device_get_property_value( device, "ID_CDROM_DVD" ) )
00113           {
00114             continue;   // looking for dvd only
00115           }
00116 
00117           const char * devnodePtr( ::udev_device_get_devnode( device ) );
00118           if ( ! devnodePtr )
00119           {
00120             ERR << "Got NULL devicenode." << endl;
00121             continue;
00122           }
00123 
00124           // In case we need it someday:
00125           //const char * mountpath = ::udev_device_get_property_value( device, "FSTAB_DIR" );
00126 
00127           PathInfo devnode( devnodePtr );
00128           if ( devnode.isBlk() )
00129           {
00130             MediaSource media( "cdrom", devnode.path().asString(), devnode.major(), devnode.minor() );
00131             DBG << "Found (udev): " << media << std::endl;
00132             detected.push_back( media );
00133           }
00134         }
00135         if ( detected.empty() )
00136         {
00137           WAR << "Did not find any CD/DVD device." << endl;
00138         }
00139 #elif HAVE_HAL
00140         using namespace zypp::target::hal;
00141         try
00142         {
00143           HalContext hal(true);
00144 
00145           std::vector<std::string> drv_udis;
00146           drv_udis = hal.findDevicesByCapability("storage.cdrom");
00147 
00148           DBG << "Found " << drv_udis.size() << " cdrom drive udis" << std::endl;
00149           for(size_t d = 0; d < drv_udis.size(); d++)
00150           {
00151             HalDrive drv( hal.getDriveFromUDI( drv_udis[d]));
00152 
00153             if( drv)
00154             {
00155               bool supportsDVD=false;
00156               if( supportingDVD_r)
00157               {
00158                 std::vector<std::string> caps;
00159                 try {
00160                   caps = drv.getCdromCapabilityNames();
00161                 }
00162                 catch(const HalException &e)
00163                 {
00164                   ZYPP_CAUGHT(e);
00165                 }
00166 
00167                 std::vector<std::string>::const_iterator ci;
00168                 for( ci=caps.begin(); ci != caps.end(); ++ci)
00169                 {
00170                   if( *ci == "dvd")
00171                     supportsDVD = true;
00172                 }
00173               }
00174 
00175               MediaSource media("cdrom", drv.getDeviceFile(),
00176                       drv.getDeviceMajor(),
00177                       drv.getDeviceMinor());
00178                   DBG << "Found " << drv_udis[d] << ": "
00179                   << media.asString() << std::endl;
00180                   if( supportingDVD_r && supportsDVD)
00181                   {
00182                     detected.push_front(media);
00183                   }
00184                   else
00185                   {
00186                     detected.push_back(media);
00187                   }
00188             }
00189           }
00190         }
00191         catch(const zypp::target::hal::HalException &e)
00192         {
00193           ZYPP_CAUGHT(e);
00194         }
00195 #endif
00196         return detected;
00197       }
00198 
00199     } // namespace
00201 
00202 
00203   MediaCD::MediaCD( const Url & url_r, const Pathname & attach_point_hint_r )
00204     : MediaHandler( url_r, attach_point_hint_r, url_r.getPathName(), false )
00205     , _lastdev( -1 )
00206     , _lastdev_tried( -1 )
00207   {
00208     MIL << "MediaCD::MediaCD(" << url_r << ", " << attach_point_hint_r << ")" << endl;
00209 
00210     if ( url_r.getScheme() != "dvd" && url_r.getScheme() != "cd" )
00211     {
00212       ERR << "Unsupported schema in the Url: " << url_r.asString() << endl;
00213       ZYPP_THROW(MediaUnsupportedUrlSchemeException(_url));
00214     }
00215 
00216     string devices = _url.getQueryParam( "devices" );
00217     if ( ! devices.empty() )
00218     {
00219       std::vector<std::string> words;
00220       str::split( devices, std::back_inserter(words), "," );
00221       for_each_( it, words )
00222       {
00223         const std::string & device( *it );
00224         if ( device.empty() )
00225           continue;
00226 
00227         MediaSource media( "cdrom", device, 0, 0 );
00228         _devices.push_back( media );
00229         DBG << "use device (delayed verify)" << device << endl;
00230       }
00231     }
00232     else
00233     {
00234       DBG << "going to use on-demand device list" << endl;
00235       return;
00236     }
00237 
00238     if ( _devices.empty() )
00239     {
00240       ERR << "Unable to find any cdrom drive for " << _url.asString() << endl;
00241       ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
00242     }
00243   }
00244 
00246   //
00247   //
00248   //  METHOD NAME : MediaCD::openTray
00249   //  METHOD TYPE : bool
00250   //
00251   bool MediaCD::openTray( const std::string & device_r )
00252   {
00253     int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK );
00254     int res = -1;
00255 
00256     if ( fd != -1)
00257     {
00258       res = ::ioctl( fd, CDROMEJECT );
00259       ::close( fd );
00260     }
00261 
00262     if ( res )
00263     {
00264       if( fd == -1)
00265       {
00266         WAR << "Unable to open '" << device_r
00267             << "' (" << ::strerror( errno ) << ")" << endl;
00268       }
00269       else
00270       {
00271         WAR << "Eject " << device_r
00272             << " failed (" << ::strerror( errno ) << ")" << endl;
00273       }
00274 
00275 #if defined(EJECT_TOOL_PATH)
00276       DBG << "Try to eject " << device_r << " using "
00277         << EJECT_TOOL_PATH << " utility" << std::endl;
00278 
00279       const char *cmd[3];
00280       cmd[0] = EJECT_TOOL_PATH;
00281       cmd[1] = device_r.c_str();
00282       cmd[2] = NULL;
00283       ExternalProgram eject(cmd, ExternalProgram::Stderr_To_Stdout);
00284 
00285       for(std::string out( eject.receiveLine());
00286           out.length(); out = eject.receiveLine())
00287       {
00288         DBG << " " << out;
00289       }
00290 
00291       if(eject.close() != 0)
00292       {
00293         WAR << "Eject of " << device_r << " failed." << std::endl;
00294         return false;
00295       }
00296 #else
00297       return false;
00298 #endif
00299     }
00300     MIL << "Eject of " << device_r << " successful." << endl;
00301     return true;
00302   }
00303 
00305   //
00306   //
00307   //    METHOD NAME : MediaCD::closeTray
00308   //    METHOD TYPE : bool
00309   //
00310   bool MediaCD::closeTray( const std::string & device_r )
00311   {
00312     int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK );
00313     if ( fd == -1 ) {
00314       WAR << "Unable to open '" << device_r << "' (" << ::strerror( errno ) << ")" << endl;
00315       return false;
00316     }
00317     int res = ::ioctl( fd, CDROMCLOSETRAY );
00318     ::close( fd );
00319     if ( res ) {
00320       WAR << "Close tray " << device_r << " failed (" << ::strerror( errno ) << ")" << endl;
00321       return false;
00322     }
00323     DBG << "Close tray " << device_r << endl;
00324     return true;
00325   }
00326 
00327 
00328   MediaCD::DeviceList MediaCD::detectDevices( bool supportingDVD_r ) const
00329   {
00330     DeviceList detected( systemDetectDevices( supportingDVD_r ) );
00331 
00332     if ( detected.empty() )
00333     {
00334       WAR << "CD/DVD drive detection with HAL/UDEV failed! Guessing..." << std::endl;
00335       PathInfo dvdinfo( "/dev/dvd" );
00336       PathInfo cdrinfo( "/dev/cdrom" );
00337       if ( dvdinfo.isBlk() )
00338       {
00339         MediaSource media( "cdrom", dvdinfo.path().asString(), dvdinfo.major(), dvdinfo.minor() );
00340         DBG << "Found (GUESS): " << media << std::endl;
00341         detected.push_back( media );
00342       }
00343       if ( cdrinfo.isBlk()
00344         && ! ( cdrinfo.major() == dvdinfo.major() && cdrinfo.minor() == dvdinfo.minor() ) )
00345       {
00346         MediaSource media( "cdrom", cdrinfo.path().asString(), cdrinfo.major(), cdrinfo.minor() );
00347         DBG << "Found (GUESS): " << media << std::endl;
00348         detected.push_back( media );
00349       }
00350     }
00351 
00352     // NOTE: On the fly build on-demand device list. Code was moved to
00353     // here to get rid of code duplication, while keeping the ABI. Acuallty
00354     // this code should be moved to a _devices accessor method.
00355     if ( _devices.empty() )
00356     {
00357       DBG << "creating on-demand device list" << endl;
00358       //default is /dev/cdrom; for dvd: /dev/dvd if it exists
00359       string device( "/dev/cdrom" );
00360       if ( _url.getScheme() == "dvd" && PathInfo( "/dev/dvd" ).isBlk() )
00361       {
00362         device = "/dev/dvd";
00363       }
00364 
00365       PathInfo dinfo( device );
00366       if ( dinfo.isBlk() )
00367       {
00368         MediaSource media( "cdrom", device, dinfo.major(), dinfo.minor() );
00369         if ( detected.empty() )
00370         {
00371           _devices.push_front( media ); // better try this than nothing
00372         }
00373         else
00374         {
00375           for_each_( it, detected )
00376           {
00377             // /dev/cdrom or /dev/dvd to the front
00378             if ( media.equals( *it ) )
00379               _devices.push_front( *it );
00380             else
00381               _devices.push_back( *it );
00382           }
00383         }
00384       }
00385       else
00386       {
00387         // no /dev/cdrom or /dev/dvd link
00388         _devices = detected;
00389       }
00390     }
00391 
00392     return detected;
00393   }
00394 
00395 
00397   //
00398   //
00399   //  METHOD NAME : MediaCD::attachTo
00400   //  METHOD TYPE : PMError
00401   //
00402   //  DESCRIPTION : Asserted that not already attached, and attachPoint is a directory.
00403   //
00404   void MediaCD::attachTo( bool next )
00405   {
00406     DBG << "next " << next << " last " << _lastdev << " last tried " << _lastdev_tried << endl;
00407     if ( next && _lastdev == -1 )
00408       ZYPP_THROW(MediaNotSupportedException(url()));
00409 
00410     // This also fills the _devices list on demand
00411     DeviceList detected( detectDevices( _url.getScheme() == "dvd" ? true : false ) );
00412 
00413     Mount mount;
00414     MediaMountException merr;
00415     string mountpoint = attachPoint().asString();
00416 
00417     string options = _url.getQueryParam( "mountoptions" );
00418     if ( options.empty() )
00419     {
00420       options="ro";
00421     }
00422 
00423     //TODO: make configurable
00424     list<string> filesystems;
00425 
00426     // if DVD, try UDF filesystem before iso9660
00427     if ( _url.getScheme() == "dvd" )
00428       filesystems.push_back("udf");
00429 
00430     filesystems.push_back("iso9660");
00431 
00432     // try all devices in sequence
00433     int count = 0;
00434     bool mountsucceeded = false;
00435     for ( DeviceList::iterator it = _devices.begin() ; ! mountsucceeded && it != _devices.end() ; ++it, ++count )
00436     {
00437       DBG << "count " << count << endl;
00438       if (next && count <=_lastdev_tried )
00439       {
00440         DBG << "skipping device " << it->name << endl;
00441         continue;
00442       }
00443 
00444       _lastdev_tried = count;
00445 
00446       // bnc#755815: _devices contains either devices passed as url option
00447       //        or autodetected ones. Accept both as long as they are block
00448       //        devices.
00449       MediaSource temp( *it );
00450       PathInfo dinfo( temp.name );
00451       if ( ! dinfo.isBlk() )
00452       {
00453         WAR <<  "skipping non block device: " << dinfo << endl;
00454         continue;
00455       }
00456 
00457       DBG << "trying device " << dinfo << endl;
00458 
00459       temp.maj_nr = dinfo.major();
00460       temp.min_nr = dinfo.minor();
00461       MediaSourceRef media( new MediaSource(temp));
00462       AttachedMedia ret( findAttachedMedia( media));
00463 
00464       if( ret.mediaSource && ret.attachPoint &&
00465          !ret.attachPoint->empty())
00466       {
00467         DBG << "Using a shared media "
00468             << ret.mediaSource->name
00469             << " attached on "
00470             << ret.attachPoint->path
00471             << endl;
00472         removeAttachPoint();
00473         setAttachPoint(ret.attachPoint);
00474         setMediaSource(ret.mediaSource);
00475         _lastdev = count;
00476         mountsucceeded = true;
00477         break;
00478       }
00479 
00480       {
00481         MediaManager  manager;
00482         MountEntries  entries( manager.getMountEntries());
00483         MountEntries::const_iterator e;
00484         for( e = entries.begin(); e != entries.end(); ++e)
00485         {
00486           bool        is_device = false;
00487           std::string dev_path(Pathname(e->src).asString());
00488           PathInfo    dev_info;
00489 
00490           if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
00491               dev_info(e->src) && dev_info.isBlk())
00492           {
00493             is_device = true;
00494           }
00495 
00496           if( is_device && media->maj_nr == dev_info.major() &&
00497                            media->min_nr == dev_info.minor())
00498           {
00499             AttachPointRef ap( new AttachPoint(e->dir, false));
00500             AttachedMedia  am( media, ap);
00501             {
00502               DBG << "Using a system mounted media "
00503                   << media->name
00504                   << " attached on "
00505                   << ap->path
00506                   << endl;
00507 
00508               media->iown = false; // mark attachment as foreign
00509 
00510               setMediaSource(media);
00511               setAttachPoint(ap);
00512               _lastdev = count;
00513               mountsucceeded = true;
00514               break;
00515             }
00516           }
00517         }
00518         if( mountsucceeded)
00519           break;
00520       }
00521 
00522       // close tray
00523       closeTray( it->name );
00524 
00525       // try all filesystems in sequence
00526       for(list<string>::iterator fsit = filesystems.begin()
00527           ; !mountsucceeded && fsit != filesystems.end()
00528           ; ++fsit)
00529       {
00530         try
00531         {
00532           if( !isUseableAttachPoint(Pathname(mountpoint)))
00533           {
00534             mountpoint = createAttachPoint().asString();
00535             setAttachPoint( mountpoint, true);
00536             if( mountpoint.empty())
00537             {
00538               ZYPP_THROW( MediaBadAttachPointException(url()));
00539             }
00540           }
00541 
00542           mount.mount(it->name, mountpoint, *fsit, options);
00543 
00544           setMediaSource(media);
00545 
00546           // wait for /etc/mtab update ...
00547           // (shouldn't be needed)
00548           int limit = 2;
00549           while( !(mountsucceeded=isAttached()) && --limit)
00550           {
00551             WAR << "Wait for /proc/mounts update and retry...." << endl;
00552             sleep(1);
00553           }
00554 
00555           if( mountsucceeded)
00556           {
00557             _lastdev = count;
00558           }
00559           else
00560           {
00561             setMediaSource(MediaSourceRef());
00562             try
00563             {
00564               mount.umount(attachPoint().asString());
00565             }
00566             catch (const MediaException & excpt_r)
00567             {
00568               ZYPP_CAUGHT(excpt_r);
00569             }
00570             ZYPP_THROW(MediaMountException(
00571               "Unable to verify that the media was mounted",
00572               it->name, mountpoint
00573             ));
00574           }
00575         }
00576         catch (const MediaMountException &e)
00577         {
00578           merr = e;
00579           removeAttachPoint();
00580           ZYPP_CAUGHT(e);
00581         }
00582         catch (const MediaException & excpt_r)
00583         {
00584           removeAttachPoint();
00585           ZYPP_CAUGHT(excpt_r);
00586         }
00587       } // for filesystems
00588     } // for _devices
00589 
00590     if (!mountsucceeded)
00591     {
00592       _lastdev = -1;
00593 
00594       if( !merr.mountOutput().empty())
00595       {
00596         ZYPP_THROW(MediaMountException(merr.mountError(),
00597                                        _url.asString(),
00598                                        mountpoint,
00599                                        merr.mountOutput()));
00600       }
00601       else
00602       {
00603         ZYPP_THROW(MediaMountException("Mounting media failed",
00604                                        _url.asString(), mountpoint));
00605       }
00606     }
00607     DBG << _lastdev << " " << count << endl;
00608   }
00609 
00610 
00612   //
00613   //
00614   //  METHOD NAME : MediaCD::releaseFrom
00615   //  METHOD TYPE : PMError
00616   //
00617   //  DESCRIPTION : Asserted that media is attached.
00618   //
00619   void MediaCD::releaseFrom( const std::string & ejectDev )
00620   {
00621     Mount mount;
00622     try
00623     {
00624       AttachedMedia am( attachedMedia());
00625       if(am.mediaSource && am.mediaSource->iown)
00626         mount.umount(am.attachPoint->path.asString());
00627     }
00628     catch (const Exception & excpt_r)
00629     {
00630       ZYPP_CAUGHT(excpt_r);
00631       if (!ejectDev.empty())
00632       {
00633         forceRelaseAllMedia(false);
00634         if(openTray( ejectDev ))
00635           return;
00636       }
00637       ZYPP_RETHROW(excpt_r);
00638     }
00639 
00640     // eject device
00641     if (!ejectDev.empty())
00642     {
00643       forceRelaseAllMedia(false);
00644       if( !openTray( ejectDev ))
00645       {
00646 #if REPORT_EJECT_ERRORS
00647         ZYPP_THROW(MediaNotEjectedException(ejectDev));
00648 #endif
00649       }
00650     }
00651   }
00652 
00654   //
00655   //
00656   //  METHOD NAME : MediaCD::forceEject
00657   //  METHOD TYPE : void
00658   //
00659   // Asserted that media is not attached.
00660   //
00661   void MediaCD::forceEject( const std::string & ejectDev_r )
00662   {
00663     bool ejected = false;
00664     if ( ! isAttached() )       // no device mounted in this instance
00665     {
00666       // This also fills the _devices list on demand
00667       DeviceList detected( detectDevices( _url.getScheme() == "dvd" ? true : false ) );
00668 
00669       for_( it, _devices.begin(), _devices.end() )
00670       {
00671         MediaSourceRef media( new MediaSource( *it ) );
00672         if ( media->name != ejectDev_r )
00673           continue;
00674 
00675         // bnc#755815: _devices contains either devices passed as url option
00676         //      or autodetected ones. Accept both as long as they are block
00677         //      devices.
00678         PathInfo dinfo( media->name );
00679         if( ! dinfo.isBlk() )
00680         {
00681           WAR <<  "skipping non block device: " << dinfo << endl;
00682           continue;
00683         }
00684         DBG << "trying device " << dinfo << endl;
00685 
00686         // FIXME: we have also to check if it is mounted in the system
00687         AttachedMedia ret( findAttachedMedia( media));
00688         if( !ret.mediaSource )
00689         {
00690           forceRelaseAllMedia( media, false );
00691           if ( openTray( it->name ) )
00692           {
00693             ejected = true;
00694             break; // on 1st success
00695           }
00696         }
00697       }
00698     }
00699 #if REPORT_EJECT_ERRORS
00700     if( !ejected)
00701     {
00702       ZYPP_THROW(MediaNotEjectedException());
00703     }
00704 #endif
00705   }
00706 
00708   //
00709   //  METHOD NAME : MediaCD::isAttached
00710   //  METHOD TYPE : bool
00711   //
00712   //  DESCRIPTION : Override check if media is attached.
00713   //
00714   bool
00715   MediaCD::isAttached() const
00716   {
00717     return checkAttached(false);
00718   }
00719 
00721   //
00722   //  METHOD NAME : MediaCD::getFile
00723   //  METHOD TYPE : PMError
00724   //
00725   //  DESCRIPTION : Asserted that media is attached.
00726   //
00727   void MediaCD::getFile( const Pathname & filename ) const
00728   {
00729     MediaHandler::getFile( filename );
00730   }
00731 
00733   //
00734   //  METHOD NAME : MediaCD::getDir
00735   //  METHOD TYPE : PMError
00736   //
00737   //  DESCRIPTION : Asserted that media is attached.
00738   //
00739   void MediaCD::getDir( const Pathname & dirname, bool recurse_r ) const
00740   {
00741     MediaHandler::getDir( dirname, recurse_r );
00742   }
00743 
00745   //
00746   //
00747   //  METHOD NAME : MediaCD::getDirInfo
00748   //  METHOD TYPE : PMError
00749   //
00750   //  DESCRIPTION : Asserted that media is attached and retlist is empty.
00751   //
00752   void MediaCD::getDirInfo( std::list<std::string> & retlist,
00753                             const Pathname & dirname, bool dots ) const
00754   {
00755     MediaHandler::getDirInfo( retlist, dirname, dots );
00756   }
00757 
00759   //
00760   //
00761   //  METHOD NAME : MediaCD::getDirInfo
00762   //  METHOD TYPE : PMError
00763   //
00764   //  DESCRIPTION : Asserted that media is attached and retlist is empty.
00765   //
00766   void MediaCD::getDirInfo( filesystem::DirContent & retlist, const Pathname & dirname, bool dots ) const
00767   {
00768     MediaHandler::getDirInfo( retlist, dirname, dots );
00769   }
00770 
00771 
00772   bool MediaCD::getDoesFileExist( const Pathname & filename ) const
00773   {
00774     return MediaHandler::getDoesFileExist( filename );
00775   }
00776 
00777 
00778   bool MediaCD::hasMoreDevices()
00779   {
00780     if (_devices.size() == 0)
00781       return false;
00782     else if (_lastdev_tried < 0)
00783       return true;
00784 
00785     return (unsigned) _lastdev_tried < _devices.size() - 1;
00786   }
00787 
00788 
00789   void MediaCD::getDetectedDevices( std::vector<std::string> & devices, unsigned int & index ) const
00790   {
00791     if ( ! devices.empty() )
00792       devices.clear();
00793 
00794     if ( _devices.empty() )
00795       // This also fills the _devices list on demand
00796       detectDevices( _url.getScheme() == "dvd" ? true : false );
00797 
00798     for_each_( it, _devices )
00799       devices.push_back( (*it).name );
00800 
00801     index = ( _lastdev >= 0  ? (unsigned)_lastdev : 0 );
00802 
00803     MIL << "got " << devices.size() << " detected devices, current: "
00804         << (index < devices.size() ? devices[index] : "<none>")
00805         << "(" << index << ")" << endl;
00806   }
00807 
00808   } // namespace media
00810 } // namespace zypp

Generated on Tue May 5 14:43:17 2015 for libzypp by  doxygen 1.5.6