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

Generated on Tue Nov 28 16:49:29 2006 for zypp by  doxygen 1.5.0