MediaCD.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00013 #include <iostream>
00014 
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/ExternalProgram.h"
00017 #include "zypp/media/Mount.h"
00018 #include "zypp/media/MediaCD.h"
00019 #include "zypp/media/MediaManager.h"
00020 #include "zypp/Url.h"
00021 #include "zypp/target/hal/HalContext.h"
00022 
00023 #include <cstring> // strerror
00024 #include <cstdlib> // getenv
00025 
00026 #include <errno.h>
00027 #include <dirent.h>
00028 
00029 #include <sys/ioctl.h>
00030 #include <sys/stat.h>
00031 #include <fcntl.h>
00032 #include <unistd.h> // geteuid, ...
00033 
00034 #include <linux/cdrom.h>
00035 
00036 /*
00037 ** try umount of foreign (user/automounter) media on eject
00038 **   0 = don't force, 1 = automounted only, 2 == all
00039 */
00040 #define  FORCE_RELEASE_FOREIGN   2
00041 
00042 /*
00043 ** Reuse foreign (user/automounter) mount points.
00044 ** 0 = don't use, 1 = automounted only, 2 = all
00045 */
00046 #define  REUSE_FOREIGN_MOUNTS    2
00047 
00048 /*
00049 ** if to throw exception on eject errors or ignore them
00050 */
00051 #define  REPORT_EJECT_ERRORS     1
00052 
00053 /*
00054 ** If defined to the full path of the eject utility,
00055 ** it will be used additionally to the eject-ioctl.
00056 */
00057 #define EJECT_TOOL_PATH "/bin/eject"
00058 
00059 
00060 using namespace std;
00061 
00062 namespace zypp {
00063   namespace media {
00064 
00066 //
00067 //  CLASS NAME : MediaCD
00068 //
00070 
00071 
00073   //
00074   //
00075   //  METHOD NAME : MediaCD::MediaCD
00076   //  METHOD TYPE : Constructor
00077   //
00078   //  DESCRIPTION :
00079   //
00080   MediaCD::MediaCD( const Url &      url_r,
00081                     const Pathname & attach_point_hint_r )
00082     : MediaHandler( url_r, attach_point_hint_r,
00083                     url_r.getPathName(), // urlpath below attachpoint
00084                     false ),
00085       _lastdev(-1), _lastdev_tried(-1)
00086   {
00087     MIL << "MediaCD::MediaCD(" << url_r << ", " << attach_point_hint_r << ")"
00088         << endl;
00089 
00090     if( url_r.getScheme() != "dvd" && url_r.getScheme() != "cd")
00091     {
00092       ERR << "Unsupported schema in the Url: " << url_r.asString() << endl;
00093       ZYPP_THROW(MediaUnsupportedUrlSchemeException(_url));
00094     }
00095 
00096     string devices = _url.getQueryParam("devices");
00097     if (!devices.empty())
00098     {
00099       string::size_type pos;
00100       DBG << "parse " << devices << endl;
00101       while(!devices.empty())
00102       {
00103         pos = devices.find(',');
00104         string device = devices.substr(0,pos);
00105         if (!device.empty())
00106         {
00107           MediaSource media("cdrom", device, 0, 0);
00108           _devices.push_back( media);
00109           DBG << "use device (delayed verify)" << device << endl;
00110         }
00111         if (pos!=string::npos)
00112           devices=devices.substr(pos+1);
00113         else
00114           devices.erase();
00115       }
00116     }
00117     else
00118     {
00119       DBG << "going to use on-demand device list" << endl;
00120       return;
00121     }
00122 
00123     if( _devices.empty())
00124     {
00125       ERR << "Unable to find any cdrom drive for " << _url.asString() << endl;
00126       ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
00127     }
00128   }
00129 
00131   //
00132   //
00133   //  METHOD NAME : MediaCD::openTray
00134   //  METHOD TYPE : bool
00135   //
00136   bool MediaCD::openTray( const std::string & device_r )
00137   {
00138     int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK );
00139     int res = -1;
00140 
00141     if ( fd != -1)
00142     {
00143       res = ::ioctl( fd, CDROMEJECT );
00144       ::close( fd );
00145     }
00146 
00147     if ( res )
00148     {
00149       if( fd == -1)
00150       {
00151         WAR << "Unable to open '" << device_r
00152             << "' (" << ::strerror( errno ) << ")" << endl;
00153       }
00154       else
00155       {
00156         WAR << "Eject " << device_r
00157             << " failed (" << ::strerror( errno ) << ")" << endl;
00158       }
00159 
00160 #if defined(EJECT_TOOL_PATH)
00161       DBG << "Try to eject " << device_r << " using "
00162         << EJECT_TOOL_PATH << " utility" << std::endl;
00163 
00164       const char *cmd[3];
00165       cmd[0] = EJECT_TOOL_PATH;
00166       cmd[1] = device_r.c_str();
00167       cmd[2] = NULL;
00168       ExternalProgram eject(cmd, ExternalProgram::Stderr_To_Stdout);
00169 
00170       for(std::string out( eject.receiveLine());
00171           out.length(); out = eject.receiveLine())
00172       {
00173         DBG << " " << out;
00174       }
00175 
00176       if(eject.close() != 0)
00177       {
00178         WAR << "Eject of " << device_r << " failed." << std::endl;
00179         return false;
00180       }
00181 #else
00182       return false;
00183 #endif
00184     }
00185     MIL << "Eject of " << device_r << " successful." << endl;
00186     return true;
00187   }
00188 
00190   //
00191   //
00192   //    METHOD NAME : MediaCD::closeTray
00193   //    METHOD TYPE : bool
00194   //
00195   bool MediaCD::closeTray( const std::string & device_r )
00196   {
00197     int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK );
00198     if ( fd == -1 ) {
00199       WAR << "Unable to open '" << device_r << "' (" << ::strerror( errno ) << ")" << endl;
00200       return false;
00201     }
00202     int res = ::ioctl( fd, CDROMCLOSETRAY );
00203     ::close( fd );
00204     if ( res ) {
00205       WAR << "Close tray " << device_r << " failed (" << ::strerror( errno ) << ")" << endl;
00206       return false;
00207     }
00208     DBG << "Close tray " << device_r << endl;
00209     return true;
00210   }
00211 
00213   //
00214   //
00215   //  METHOD NAME : MediaCD::detectDevices
00216   //  METHOD TYPE : MediaCD::DeviceList
00217   //
00218   MediaCD::DeviceList
00219   MediaCD::detectDevices(bool supportingDVD) const
00220   {
00221     DeviceList detected;
00222 
00223 #ifndef NO_HAL
00224     using namespace zypp::target::hal;
00225     try
00226     {
00227       HalContext hal(true);
00228 
00229       std::vector<std::string> drv_udis;
00230       drv_udis = hal.findDevicesByCapability("storage.cdrom");
00231 
00232       DBG << "Found " << drv_udis.size() << " cdrom drive udis" << std::endl;
00233       for(size_t d = 0; d < drv_udis.size(); d++)
00234       {
00235         HalDrive drv( hal.getDriveFromUDI( drv_udis[d]));
00236 
00237         if( drv)
00238         {
00239           bool supportsDVD=false;
00240           if( supportingDVD)
00241           {
00242             std::vector<std::string> caps;
00243             try {
00244               caps = drv.getCdromCapabilityNames();
00245             }
00246             catch(const HalException &e)
00247             {
00248               ZYPP_CAUGHT(e);
00249             }
00250 
00251             std::vector<std::string>::const_iterator ci;
00252             for( ci=caps.begin(); ci != caps.end(); ++ci)
00253             {
00254               if( *ci == "dvd")
00255                 supportsDVD = true;
00256             }
00257           }
00258 
00259           MediaSource media("cdrom", drv.getDeviceFile(),
00260                             drv.getDeviceMajor(),
00261                             drv.getDeviceMinor());
00262           DBG << "Found " << drv_udis[d] << ": "
00263               << media.asString() << std::endl;
00264           if( supportingDVD && supportsDVD)
00265           {
00266             detected.push_front(media);
00267           }
00268           else
00269           {
00270             detected.push_back(media);
00271           }
00272         }
00273       }
00274     }
00275     catch(const zypp::target::hal::HalException &e)
00276     {
00277       ZYPP_CAUGHT(e);
00278     }
00279 #else // NO_HAL
00280 #warning Poor CDROM devices detection without HAL
00281     WAR << "Cdrom drive detection without HAL! " << std::endl;
00282     PathInfo dvdinfo( "/dev/dvd" );
00283     PathInfo cdrinfo( "/dev/cdrom" );
00284     if ( dvdinfo.isBlk() )
00285     {
00286       MediaSource media( "cdrom", dvdinfo.path().asString(), dvdinfo.major(), dvdinfo.minor() );
00287       DBG << "Found (NO_HAL): " << media << std::endl;
00288       detected.push_back( media );
00289     }
00290     if ( cdrinfo.isBlk()
00291          && ! ( cdrinfo.major() == dvdinfo.major() && cdrinfo.minor() == dvdinfo.minor() ) )
00292     {
00293       MediaSource media( "cdrom", cdrinfo.path().asString(), cdrinfo.major(), cdrinfo.minor() );
00294       DBG << "Found (NO_HAL): " << media << std::endl;
00295       detected.push_back( media );
00296     }
00297 #endif
00298     return detected;
00299   }
00300 
00301 
00303   //
00304   //
00305   //  METHOD NAME : MediaCD::attachTo
00306   //  METHOD TYPE : PMError
00307   //
00308   //  DESCRIPTION : Asserted that not already attached, and attachPoint is a directory.
00309   //
00310   void MediaCD::attachTo(bool next)
00311   {
00312     DBG << "next " << next << " last " << _lastdev << " last tried " << _lastdev_tried << endl;
00313     if (next && _lastdev == -1)
00314       ZYPP_THROW(MediaNotSupportedException(url()));
00315 
00316     DeviceList detected(
00317       detectDevices(_url.getScheme() == "dvd" ? true : false));
00318 
00319     if(_devices.empty())
00320     {
00321       DBG << "creating on-demand device list" << endl;
00322       //default is /dev/cdrom; for dvd: /dev/dvd if it exists
00323       string device( "/dev/cdrom" );
00324       if ( _url.getScheme() == "dvd" && PathInfo( "/dev/dvd" ).isBlk() )
00325       {
00326         device = "/dev/dvd";
00327       }
00328 
00329       PathInfo dinfo(device);
00330       if( dinfo.isBlk())
00331       {
00332         MediaSource media("cdrom", device, dinfo.major(), dinfo.minor());
00333 
00334         DeviceList::const_iterator d( detected.begin());
00335         for( ; d != detected.end(); ++d)
00336         {
00337           // /dev/cdrom or /dev/dvd to the front
00338           if( media.equals( *d))
00339             _devices.push_front( *d);
00340           else
00341             _devices.push_back( *d);
00342         }
00343       }
00344       else
00345       {
00346         // no /dev/cdrom or /dev/dvd link
00347         _devices = detected;
00348       }
00349     }
00350 
00351     Mount mount;
00352     string mountpoint = attachPoint().asString();
00353     bool mountsucceeded = false;
00354     int count = 0;
00355     MediaMountException merr;
00356 
00357     string options = _url.getQueryParam("mountoptions");
00358     if (options.empty())
00359     {
00360       options="ro";
00361     }
00362 
00363     //TODO: make configurable
00364     list<string> filesystems;
00365 
00366     // if DVD, try UDF filesystem before iso9660
00367     if ( _url.getScheme() == "dvd" )
00368       filesystems.push_back("udf");
00369 
00370     filesystems.push_back("iso9660");
00371 
00372     // try all devices in sequence
00373     for (DeviceList::iterator it = _devices.begin()
00374     ; !mountsucceeded && it != _devices.end()
00375     ; ++it, count++ )
00376     {
00377       DBG << "count " << count << endl;
00378       if (next && count <=_lastdev_tried )
00379       {
00380         DBG << "skipping device " << it->name << endl;
00381         continue;
00382       }
00383 
00384       _lastdev_tried = count;
00385 
00386       MediaSource temp( *it);
00387       bool        valid=false;
00388       PathInfo    dinfo(temp.name);
00389       if( dinfo.isBlk())
00390       {
00391         temp.maj_nr = dinfo.major();
00392         temp.min_nr = dinfo.minor();
00393 
00394         DeviceList::const_iterator d( detected.begin());
00395         for( ; d != detected.end(); ++d)
00396         {
00397           if( temp.equals( *d))
00398           {
00399             valid = true;
00400             break;
00401           }
00402         }
00403       }
00404       if( !valid)
00405       {
00406         DBG << "skipping invalid device: " << it->name << endl;
00407         continue;
00408       }
00409 
00410       MediaSourceRef media( new MediaSource(temp));
00411       AttachedMedia ret( findAttachedMedia( media));
00412 
00413       if( ret.mediaSource && ret.attachPoint &&
00414          !ret.attachPoint->empty())
00415       {
00416         DBG << "Using a shared media "
00417             << ret.mediaSource->name
00418             << " attached on "
00419             << ret.attachPoint->path
00420             << endl;
00421         removeAttachPoint();
00422         setAttachPoint(ret.attachPoint);
00423         setMediaSource(ret.mediaSource);
00424         _lastdev = count;
00425         mountsucceeded = true;
00426         break;
00427       }
00428 
00429 #if REUSE_FOREIGN_MOUNTS > 0
00430       {
00431         MediaManager  manager;
00432         MountEntries  entries( manager.getMountEntries());
00433         MountEntries::const_iterator e;
00434         for( e = entries.begin(); e != entries.end(); ++e)
00435         {
00436           bool        is_device = false;
00437           std::string dev_path(Pathname(e->src).asString());
00438           PathInfo    dev_info;
00439 
00440           if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
00441               dev_info(e->src) && dev_info.isBlk())
00442           {
00443             is_device = true;
00444           }
00445 
00446           if( is_device && media->maj_nr == dev_info.major() &&
00447                            media->min_nr == dev_info.minor())
00448           {
00449             AttachPointRef ap( new AttachPoint(e->dir, false));
00450             AttachedMedia  am( media, ap);
00451             //
00452             // 1 = automounted only, 2 == all
00453             //
00454 #if REUSE_FOREIGN_MOUNTS == 1
00455             if( isAutoMountedMedia(am))
00456 #endif
00457             {
00458               DBG << "Using a system mounted media "
00459                   << media->name
00460                   << " attached on "
00461                   << ap->path
00462                   << endl;
00463 
00464               media->iown = false; // mark attachment as foreign
00465 
00466               setMediaSource(media);
00467               setAttachPoint(ap);
00468               _lastdev = count;
00469               mountsucceeded = true;
00470               break;
00471             }
00472           }
00473         }
00474         if( mountsucceeded)
00475           break;
00476       }
00477 #endif  // REUSE_FOREIGN_MOUNTS
00478 
00479       // close tray
00480       closeTray( it->name );
00481 
00482       // try all filesystems in sequence
00483       for(list<string>::iterator fsit = filesystems.begin()
00484           ; !mountsucceeded && fsit != filesystems.end()
00485           ; ++fsit)
00486       {
00487         try
00488         {
00489           if( !isUseableAttachPoint(Pathname(mountpoint)))
00490           {
00491             mountpoint = createAttachPoint().asString();
00492             setAttachPoint( mountpoint, true);
00493             if( mountpoint.empty())
00494             {
00495               ZYPP_THROW( MediaBadAttachPointException(url()));
00496             }
00497           }
00498 
00499           mount.mount(it->name, mountpoint, *fsit, options);
00500 
00501           setMediaSource(media);
00502 
00503           // wait for /etc/mtab update ...
00504           // (shouldn't be needed)
00505           int limit = 5;
00506           while( !(mountsucceeded=isAttached()) && --limit)
00507           {
00508             sleep(1);
00509           }
00510 
00511           if( mountsucceeded)
00512           {
00513             _lastdev = count;
00514           }
00515           else
00516           {
00517             setMediaSource(MediaSourceRef());
00518             try
00519             {
00520               mount.umount(attachPoint().asString());
00521             }
00522             catch (const MediaException & excpt_r)
00523             {
00524               ZYPP_CAUGHT(excpt_r);
00525             }
00526             ZYPP_THROW(MediaMountException(
00527               "Unable to verify that the media was mounted",
00528               it->name, mountpoint
00529             ));
00530           }
00531         }
00532         catch (const MediaMountException &e)
00533         {
00534           merr = e;
00535           removeAttachPoint();
00536           ZYPP_CAUGHT(e);
00537         }
00538         catch (const MediaException & excpt_r)
00539         {
00540           removeAttachPoint();
00541           ZYPP_CAUGHT(excpt_r);
00542         }
00543       } // for filesystems
00544     } // for _devices
00545 
00546     if (!mountsucceeded)
00547     {
00548       _lastdev = -1;
00549 
00550       if( !merr.mountOutput().empty())
00551       {
00552         ZYPP_THROW(MediaMountException(merr.mountError(),
00553                                        _url.asString(),
00554                                        mountpoint,
00555                                        merr.mountOutput()));
00556       }
00557       else
00558       {
00559         ZYPP_THROW(MediaMountException("Mounting media failed",
00560                                        _url.asString(), mountpoint));
00561       }
00562     }
00563     DBG << _lastdev << " " << count << endl;
00564   }
00565 
00566 
00568   //
00569   //
00570   //  METHOD NAME : MediaCD::releaseFrom
00571   //  METHOD TYPE : PMError
00572   //
00573   //  DESCRIPTION : Asserted that media is attached.
00574   //
00575   void MediaCD::releaseFrom( const std::string & ejectDev )
00576   {
00577     Mount mount;
00578     try
00579     {
00580       AttachedMedia am( attachedMedia());
00581       if(am.mediaSource && am.mediaSource->iown)
00582         mount.umount(am.attachPoint->path.asString());
00583     }
00584     catch (const Exception & excpt_r)
00585     {
00586       ZYPP_CAUGHT(excpt_r);
00587       if (!ejectDev.empty())
00588       {
00589 #if FORCE_RELEASE_FOREIGN > 0
00590         /* 1 = automounted only, 2 = all */
00591         forceRelaseAllMedia(false, FORCE_RELEASE_FOREIGN == 1);
00592 #endif
00593         if(openTray( ejectDev ))
00594           return;
00595       }
00596       ZYPP_RETHROW(excpt_r);
00597     }
00598 
00599     // eject device
00600     if (!ejectDev.empty())
00601     {
00602 #if FORCE_RELEASE_FOREIGN > 0
00603       /* 1 = automounted only, 2 = all */
00604       forceRelaseAllMedia(false, FORCE_RELEASE_FOREIGN == 1);
00605 #endif
00606       if( !openTray( ejectDev ))
00607       {
00608 #if REPORT_EJECT_ERRORS
00609         ZYPP_THROW(MediaNotEjectedException(ejectDev));
00610 #endif
00611       }
00612     }
00613   }
00614 
00616   //
00617   //
00618   //  METHOD NAME : MediaCD::forceEject
00619   //  METHOD TYPE : void
00620   //
00621   // Asserted that media is not attached.
00622   //
00623   void MediaCD::forceEject(const std::string & ejectDev)
00624   {
00625     bool ejected=false;
00626     if ( !isAttached()) {       // no device mounted in this instance
00627 
00628       DeviceList detected(
00629           detectDevices(_url.getScheme() == "dvd" ? true : false));
00630 
00631       if(_devices.empty())
00632       {
00633         DBG << "creating on-demand device list" << endl;
00634         //default is /dev/cdrom; for dvd: /dev/dvd if it exists
00635         string device( "/dev/cdrom" );
00636         if ( _url.getScheme() == "dvd" && PathInfo( "/dev/dvd" ).isBlk() ) {
00637           device = "/dev/dvd";
00638         }
00639 
00640         PathInfo dinfo(device);
00641         if( dinfo.isBlk())
00642         {
00643           MediaSource media("cdrom", device, dinfo.major(), dinfo.minor());
00644 
00645           DeviceList::const_iterator d( detected.begin());
00646           for( ; d != detected.end(); ++d)
00647           {
00648             // /dev/cdrom or /dev/dvd to the front
00649             if( media.equals( *d))
00650               _devices.push_front( *d);
00651             else
00652               _devices.push_back( *d);
00653           }
00654         }
00655         else
00656         {
00657           // no /dev/cdrom or /dev/dvd link
00658           _devices = detected;
00659         }
00660       }
00661 
00662       DeviceList::iterator it;
00663       for( it = _devices.begin(); it != _devices.end(); ++it ) {
00664         MediaSourceRef media( new MediaSource( *it));
00665         if (media->name != ejectDev)
00666           continue;
00667 
00668         bool        valid=false;
00669         PathInfo    dinfo(media->name);
00670         if( dinfo.isBlk())
00671         {
00672           media->maj_nr = dinfo.major();
00673           media->min_nr = dinfo.minor();
00674 
00675           DeviceList::const_iterator d( detected.begin());
00676           for( ; d != detected.end(); ++d)
00677           {
00678             if( media->equals( *d))
00679             {
00680               valid = true;
00681               break;
00682             }
00683           }
00684         }
00685         if( !valid)
00686         {
00687           DBG << "skipping invalid device: " << it->name << endl;
00688           continue;
00689         }
00690 
00691         // FIXME: we have also to check if it is mounted in the system
00692         AttachedMedia ret( findAttachedMedia( media));
00693         if( !ret.mediaSource)
00694         {
00695 #if FORCE_RELEASE_FOREIGN > 0
00696           /* 1 = automounted only, 2 = all */
00697           forceRelaseAllMedia(media, false, FORCE_RELEASE_FOREIGN == 1);
00698 #endif
00699           if ( openTray( it->name ) )
00700           {
00701             ejected = true;
00702             break; // on 1st success
00703           }
00704         }
00705       }
00706     }
00707     if( !ejected)
00708     {
00709 #if REPORT_EJECT_ERRORS
00710       ZYPP_THROW(MediaNotEjectedException());
00711 #endif
00712     }
00713   }
00714 
00715   bool MediaCD::isAutoMountedMedia(const AttachedMedia &media)
00716   {
00717     bool is_automounted = false;
00718     if( media.mediaSource && !media.mediaSource->name.empty())
00719     {
00720 #ifndef NO_HAL
00721       using namespace zypp::target::hal;
00722       try
00723       {
00724         HalContext hal(true);
00725 
00726         HalVolume vol = hal.getVolumeFromDeviceFile(media.mediaSource->name);
00727         if( vol)
00728         {
00729           std::string udi = vol.getUDI();
00730           std::string key;
00731           std::string mnt;
00732 
00733           try
00734           {
00735             key = "info.hal_mount.created_mount_point";
00736             mnt = hal.getDevicePropertyString(udi, key);
00737 
00738             if(media.attachPoint->path == mnt)
00739               is_automounted = true;
00740           }
00741           catch(const HalException &e1)
00742           {
00743             ZYPP_CAUGHT(e1);
00744 
00745             try
00746             {
00747               key = "volume.mount_point";
00748               mnt = hal.getDevicePropertyString(udi, key);
00749 
00750               if(media.attachPoint->path == mnt)
00751                 is_automounted = true;
00752             }
00753             catch(const HalException &e2)
00754             {
00755               ZYPP_CAUGHT(e2);
00756             }
00757           }
00758         }
00759       }
00760       catch(const HalException &e)
00761       {
00762         ZYPP_CAUGHT(e);
00763       }
00764 #else // NO_HAL
00765 #warning Can not detect automounted media without HAL
00766     INT << "Can not detect automounted media without HAL!" << endl;
00767     // ma@: This codepath is probably unused due to 'REUSE_FOREIGN_MOUNTS == 2'
00768     // Maybe we should cleanup all this automount-specail-handling.
00769 #endif
00770     }
00771     DBG << "Media "        << media.mediaSource->asString()
00772         << " attached on " << media.attachPoint->path
00773         << " is"           << (is_automounted ? "" : " not")
00774         << " automounted"  << std::endl;
00775     return is_automounted;
00776   }
00777 
00779   //
00780   //  METHOD NAME : MediaCD::isAttached
00781   //  METHOD TYPE : bool
00782   //
00783   //  DESCRIPTION : Override check if media is attached.
00784   //
00785   bool
00786   MediaCD::isAttached() const
00787   {
00788     return checkAttached(false);
00789   }
00790 
00792   //
00793   //  METHOD NAME : MediaCD::getFile
00794   //  METHOD TYPE : PMError
00795   //
00796   //  DESCRIPTION : Asserted that media is attached.
00797   //
00798   void MediaCD::getFile( const Pathname & filename ) const
00799   {
00800     MediaHandler::getFile( filename );
00801   }
00802 
00804   //
00805   //  METHOD NAME : MediaCD::getDir
00806   //  METHOD TYPE : PMError
00807   //
00808   //  DESCRIPTION : Asserted that media is attached.
00809   //
00810   void MediaCD::getDir( const Pathname & dirname, bool recurse_r ) const
00811   {
00812     MediaHandler::getDir( dirname, recurse_r );
00813   }
00814 
00816   //
00817   //
00818   //  METHOD NAME : MediaCD::getDirInfo
00819   //  METHOD TYPE : PMError
00820   //
00821   //  DESCRIPTION : Asserted that media is attached and retlist is empty.
00822   //
00823   void MediaCD::getDirInfo( std::list<std::string> & retlist,
00824                             const Pathname & dirname, bool dots ) const
00825   {
00826     MediaHandler::getDirInfo( retlist, dirname, dots );
00827   }
00828 
00830   //
00831   //
00832   //  METHOD NAME : MediaCD::getDirInfo
00833   //  METHOD TYPE : PMError
00834   //
00835   //  DESCRIPTION : Asserted that media is attached and retlist is empty.
00836   //
00837   void MediaCD::getDirInfo( filesystem::DirContent & retlist,
00838                             const Pathname & dirname, bool dots ) const
00839   {
00840     MediaHandler::getDirInfo( retlist, dirname, dots );
00841   }
00842 
00843   bool MediaCD::getDoesFileExist( const Pathname & filename ) const
00844   {
00845     return MediaHandler::getDoesFileExist( filename );
00846   }
00847 
00848   bool MediaCD::hasMoreDevices()
00849   {
00850     if (_devices.size() == 0)
00851       return false;
00852     else if (_lastdev_tried < 0)
00853       return true;
00854 
00855     return (unsigned) _lastdev_tried < _devices.size() - 1;
00856   }
00857 
00858   void
00859   MediaCD::getDetectedDevices(std::vector<std::string> & devices,
00860                               unsigned int & index) const
00861   {
00862     index = 0;
00863     if (!devices.empty())
00864       devices.clear();
00865 
00866     for (DeviceList::const_iterator it = _devices.begin();
00867          it != _devices.end(); ++it)
00868       devices.push_back(it->name);
00869 
00870     if (_lastdev >= 0)
00871       index = _lastdev;
00872 
00873     // try to detect again if _devices are empty (maybe this method will be
00874     // called before _devices get actually filled)
00875     if (devices.empty())
00876     {
00877       DBG << "no device list so far, trying to detect" << endl;
00878 
00879       DeviceList detected(
00880         detectDevices(_url.getScheme() == "dvd" ? true : false));
00881 
00882       for (DeviceList::const_iterator it = detected.begin();
00883            it != detected.end(); ++it)
00884         devices.push_back(it->name);
00885 
00886       // don't know which one is in use in this case
00887       index = 0;
00888     }
00889 
00890     MIL << "got " << devices.size() << " detected devices, current: "
00891         << (index < devices.size() ? devices[index] : "<none>")
00892         << "(" << index << ")" << endl;
00893   }
00894 
00895 
00896   } // namespace media
00897 } // namespace zypp
00898 // vim: set ts=8 sts=2 sw=2 ai noet:

doxygen