Use libudev to detect available cd/dvd devices (bnc#590707,fate#308980)
[platform/upstream/libzypp.git] / zypp / media / MediaCD.cc
index 53843d2..3976aef 100644 (file)
@@ -9,7 +9,15 @@
 /** \file zypp/media/MediaCD.cc
  *
 */
+extern "C"
+{
+#include <sys/ioctl.h>
+#include <linux/cdrom.h>
+#include <libudev.h>
+}
 
+#include <cstring> // strerror
+#include <cstdlib> // getenv
 #include <iostream>
 
 #include "zypp/base/Logger.h"
 #include "zypp/media/MediaCD.h"
 #include "zypp/media/MediaManager.h"
 #include "zypp/Url.h"
-#include "zypp/target/hal/HalContext.h"
+#include "zypp/AutoDispose.h"
 
-#include <cstring> // strerror
-#include <cstdlib> // getenv
 
-#include <errno.h>
-#include <dirent.h>
-
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h> // geteuid, ...
-
-#include <linux/cdrom.h>
-
-/*
-** try umount of foreign (user/automounter) media on eject
-**   0 = don't force, 1 = automounted only, 2 == all
-*/
-#define  FORCE_RELEASE_FOREIGN   2
-
-/*
-** Reuse foreign (user/automounter) mount points.
-** 0 = don't use, 1 = automounted only, 2 = all
-*/
-#define  REUSE_FOREIGN_MOUNTS    2
 
 /*
 ** if to throw exception on eject errors or ignore them
@@ -215,86 +200,62 @@ namespace zypp {
   //  METHOD NAME : MediaCD::detectDevices
   //  METHOD TYPE : MediaCD::DeviceList
   //
-  MediaCD::DeviceList
-  MediaCD::detectDevices(bool supportingDVD) const
+  MediaCD::DeviceList MediaCD::detectDevices( bool supportingDVD ) const
   {
-    DeviceList detected;
+    zypp::AutoDispose<struct udev *> udev( ::udev_new(), ::udev_unref );
+    if ( ! udev )
+    {
+      ERR << "Can't create udev context." << endl;
+      return DeviceList();
+    }
 
-#ifndef NO_HALa
-    using namespace zypp::target::hal;
-    try
+    zypp::AutoDispose<struct udev_enumerate *> enumerate( ::udev_enumerate_new(udev), ::udev_enumerate_unref );
+    if ( ! enumerate )
     {
-      HalContext hal(true);
+      ERR << "Can't create udev list entry." << endl;
+      return DeviceList();
+    }
 
-      std::vector<std::string> drv_udis;
-      drv_udis = hal.findDevicesByCapability("storage.cdrom");
+    ::udev_enumerate_add_match_subsystem( enumerate, "block" );
+    ::udev_enumerate_add_match_property( enumerate, "ID_CDROM", "1" );
+    ::udev_enumerate_scan_devices( enumerate );
 
-      DBG << "Found " << drv_udis.size() << " cdrom drive udis" << std::endl;
-      for(size_t d = 0; d < drv_udis.size(); d++)
+    DeviceList detected;
+    struct udev_list_entry * entry = 0;
+    udev_list_entry_foreach( entry, ::udev_enumerate_get_list_entry( enumerate ) )
+    {
+      zypp::AutoDispose<struct udev_device *> device( ::udev_device_new_from_syspath( ::udev_enumerate_get_udev( enumerate ),
+                                                                                     ::udev_list_entry_get_name( entry ) ),
+                                                     ::udev_device_unref );
+      if ( ! device )
       {
-        HalDrive drv( hal.getDriveFromUDI( drv_udis[d]));
+       ERR << "Can't create udev device." << endl;
+       continue;
+      }
 
-        if( drv)
-        {
-          bool supportsDVD=false;
-          if( supportingDVD)
-          {
-            std::vector<std::string> caps;
-            try {
-              caps = drv.getCdromCapabilityNames();
-            }
-            catch(const HalException &e)
-            {
-              ZYPP_CAUGHT(e);
-            }
+      if ( supportingDVD && ! ::udev_device_get_property_value( device, "ID_CDROM_DVD" ) )
+      {
+       continue;       // looking for dvd only
+      }
 
-            std::vector<std::string>::const_iterator ci;
-            for( ci=caps.begin(); ci != caps.end(); ++ci)
-            {
-              if( *ci == "dvd")
-                supportsDVD = true;
-            }
-          }
+      const char * devnodePtr( ::udev_device_get_devnode( device ) );
+      if ( ! devnodePtr )
+      {
+       ERR << "Got NULL devicenode." << endl;
+       continue;
+      }
 
-          MediaSource media("cdrom", drv.getDeviceFile(),
-                            drv.getDeviceMajor(),
-                            drv.getDeviceMinor());
-          DBG << "Found " << drv_udis[d] << ": "
-              << media.asString() << std::endl;
-          if( supportingDVD && supportsDVD)
-          {
-            detected.push_front(media);
-          }
-          else
-          {
-            detected.push_back(media);
-          }
-        }
+      // In case we need it someday:
+      //const char * mountpath = ::udev_device_get_property_value( device, "FSTAB_DIR" );
+
+      PathInfo devnode( devnodePtr );
+      if ( devnode.isBlk() )
+      {
+       MediaSource media( "cdrom", devnode.path().asString(), devnode.major(), devnode.minor() );
+       DBG << "Found (udev): " << media << std::endl;
+       detected.push_back( media );
       }
     }
-    catch(const zypp::target::hal::HalException &e)
-    {
-      ZYPP_CAUGHT(e);
-    }
-#else // NO_HAL
-#warning Poor CDROM devices detection without HAL
-    WAR << "Cdrom drive detection without HAL! " << std::endl;
-    PathInfo dvdinfo( "/dev/dvd" );
-    PathInfo cdrinfo( "/dev/cdrom" );
-    if ( dvdinfo.isBlk() )
-    {
-      MediaSource media( "cdrom", dvdinfo.path().asString(), dvdinfo.major(), dvdinfo.minor() );
-      DBG << "Found (NO_HAL): " << media << std::endl;
-      detected.push_back( media );
-    }
-    if ( cdrinfo.isBlk()
-         && ! ( cdrinfo.major() == dvdinfo.major() && cdrinfo.minor() == dvdinfo.minor() ) )
-    {
-      MediaSource media( "cdrom", cdrinfo.path().asString(), cdrinfo.major(), cdrinfo.minor() );
-      DBG << "Found (NO_HAL): " << media << std::endl;
-      detected.push_back( media );
-    }
-#endif
     return detected;
   }
 
@@ -426,7 +387,6 @@ namespace zypp {
         break;
       }
 
-#if REUSE_FOREIGN_MOUNTS > 0
       {
         MediaManager  manager;
         MountEntries  entries( manager.getMountEntries());
@@ -448,12 +408,6 @@ namespace zypp {
           {
             AttachPointRef ap( new AttachPoint(e->dir, false));
             AttachedMedia  am( media, ap);
-            //
-            // 1 = automounted only, 2 == all
-            //
-#if REUSE_FOREIGN_MOUNTS == 1
-            if( isAutoMountedMedia(am))
-#endif
             {
               DBG << "Using a system mounted media "
                   << media->name
@@ -474,7 +428,6 @@ namespace zypp {
         if( mountsucceeded)
           break;
       }
-#endif  // REUSE_FOREIGN_MOUNTS
 
       // close tray
       closeTray( it->name );
@@ -586,10 +539,7 @@ namespace zypp {
       ZYPP_CAUGHT(excpt_r);
       if (!ejectDev.empty())
       {
-#if FORCE_RELEASE_FOREIGN > 0
-        /* 1 = automounted only, 2 = all */
-        forceRelaseAllMedia(false, FORCE_RELEASE_FOREIGN == 1);
-#endif
+        forceRelaseAllMedia(false);
         if(openTray( ejectDev ))
           return;
       }
@@ -599,10 +549,7 @@ namespace zypp {
     // eject device
     if (!ejectDev.empty())
     {
-#if FORCE_RELEASE_FOREIGN > 0
-      /* 1 = automounted only, 2 = all */
-      forceRelaseAllMedia(false, FORCE_RELEASE_FOREIGN == 1);
-#endif
+      forceRelaseAllMedia(false);
       if( !openTray( ejectDev ))
       {
 #if REPORT_EJECT_ERRORS
@@ -692,10 +639,7 @@ namespace zypp {
         AttachedMedia ret( findAttachedMedia( media));
         if( !ret.mediaSource)
         {
-#if FORCE_RELEASE_FOREIGN > 0
-          /* 1 = automounted only, 2 = all */
-          forceRelaseAllMedia(media, false, FORCE_RELEASE_FOREIGN == 1);
-#endif
+          forceRelaseAllMedia(media, false);
           if ( openTray( it->name ) )
           {
             ejected = true;
@@ -712,69 +656,6 @@ namespace zypp {
     }
   }
 
-  bool MediaCD::isAutoMountedMedia(const AttachedMedia &media)
-  {
-    bool is_automounted = false;
-    if( media.mediaSource && !media.mediaSource->name.empty())
-    {
-#ifndef NO_HAL
-      using namespace zypp::target::hal;
-      try
-      {
-        HalContext hal(true);
-
-        HalVolume vol = hal.getVolumeFromDeviceFile(media.mediaSource->name);
-        if( vol)
-        {
-          std::string udi = vol.getUDI();
-          std::string key;
-          std::string mnt;
-
-          try
-          {
-            key = "info.hal_mount.created_mount_point";
-            mnt = hal.getDevicePropertyString(udi, key);
-
-            if(media.attachPoint->path == mnt)
-              is_automounted = true;
-          }
-          catch(const HalException &e1)
-          {
-            ZYPP_CAUGHT(e1);
-
-            try
-            {
-              key = "volume.mount_point";
-              mnt = hal.getDevicePropertyString(udi, key);
-
-              if(media.attachPoint->path == mnt)
-                is_automounted = true;
-            }
-            catch(const HalException &e2)
-            {
-              ZYPP_CAUGHT(e2);
-            }
-          }
-        }
-      }
-      catch(const HalException &e)
-      {
-        ZYPP_CAUGHT(e);
-      }
-#else // NO_HAL
-#warning Can not detect automounted media without HAL
-    INT << "Can not detect automounted media without HAL!" << endl;
-    // ma@: This codepath is probably unused due to 'REUSE_FOREIGN_MOUNTS == 2'
-    // Maybe we should cleanup all this automount-specail-handling.
-#endif
-    }
-    DBG << "Media "        << media.mediaSource->asString()
-        << " attached on " << media.attachPoint->path
-        << " is"           << (is_automounted ? "" : " not")
-        << " automounted"  << std::endl;
-    return is_automounted;
-  }
-
   ///////////////////////////////////////////////////////////////////
   //
   //  METHOD NAME : MediaCD::isAttached