Use libudev to detect available cd/dvd devices (bnc#590707,fate#308980)
authorMichael Andres <ma@suse.de>
Mon, 26 Apr 2010 15:44:28 +0000 (17:44 +0200)
committerMichael Andres <ma@suse.de>
Mon, 26 Apr 2010 15:44:28 +0000 (17:44 +0200)
CMakeLists.txt
cmake/modules/FindUdev.cmake [new file with mode: 0644]
zypp/CMakeLists.txt
zypp/media/MediaCD.cc

index ee18c9e..0629b1f 100644 (file)
@@ -108,6 +108,7 @@ ENDIF( NOT SATSOLVER_FOUND )
 FIND_PACKAGE(EXPAT REQUIRED)
 
 FIND_PACKAGE(OpenSSL REQUIRED)
+FIND_PACKAGE(Udev REQUIRED)
 
 FIND_PROGRAM( DOXYGEN doxygen )
 IF ( NOT DOXYGEN )
diff --git a/cmake/modules/FindUdev.cmake b/cmake/modules/FindUdev.cmake
new file mode 100644 (file)
index 0000000..25ca80c
--- /dev/null
@@ -0,0 +1,17 @@
+
+SET( UDEV_LIBRARY )
+SET( UDEV_INCLUDE_DIR )
+
+FIND_PATH( UDEV_INCLUDE_DIR libudev.h
+       /usr/include
+       /usr/local/include
+)
+
+FIND_LIBRARY( UDEV_LIBRARY NAMES udev
+       PATHS
+       /usr/lib
+       /usr/local/lib
+)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( Udev DEFAULT_MSG UDEV_LIBRARY UDEV_INCLUDE_DIR )
+MARK_AS_ADVANCED(  UDEV_LIBRARY UDEV_INCLUDE_DIR )
index 0a0fe05..1976362 100644 (file)
@@ -883,6 +883,7 @@ TARGET_LINK_LIBRARIES(zypp ${SATSOLVER_LIBRARY} ${SATSOLVER_EXT_LIBRARY} ${EXPAT
 TARGET_LINK_LIBRARIES(zypp ${OPENSSL_LIBRARIES} )
 TARGET_LINK_LIBRARIES(zypp ${CRYPTO_LIBRARIES} )
 TARGET_LINK_LIBRARIES(zypp ${SIGNALS_LIBRARY} )
+TARGET_LINK_LIBRARIES(zypp ${UDEV_LIBRARY} )
 
 INSTALL(TARGETS zypp LIBRARY DESTINATION ${LIB_INSTALL_DIR} )
 
index a7a5eb3..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/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>
 
 /*
 ** if to throw exception on eject errors or ignore them
@@ -202,30 +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;
-
-#warning Poor CDROM devices detection without HAL
-    /** \todo rewite using e.g. 'hwinfo --cdrom' or libudev */
-    WAR << "Cdrom drive detection without HAL! " << std::endl;
-    PathInfo dvdinfo( "/dev/dvd" );
-    PathInfo cdrinfo( "/dev/cdrom" );
-    if ( dvdinfo.isBlk() )
+    zypp::AutoDispose<struct udev *> udev( ::udev_new(), ::udev_unref );
+    if ( ! udev )
     {
-      MediaSource media( "cdrom", dvdinfo.path().asString(), dvdinfo.major(), dvdinfo.minor() );
-      DBG << "Found (NO_HAL): " << media << std::endl;
-      detected.push_back( media );
+      ERR << "Can't create udev context." << endl;
+      return DeviceList();
     }
-    if ( cdrinfo.isBlk()
-         && ! ( cdrinfo.major() == dvdinfo.major() && cdrinfo.minor() == dvdinfo.minor() ) )
+
+    zypp::AutoDispose<struct udev_enumerate *> enumerate( ::udev_enumerate_new(udev), ::udev_enumerate_unref );
+    if ( ! enumerate )
     {
-      MediaSource media( "cdrom", cdrinfo.path().asString(), cdrinfo.major(), cdrinfo.minor() );
-      DBG << "Found (NO_HAL): " << media << std::endl;
-      detected.push_back( media );
+      ERR << "Can't create udev list entry." << endl;
+      return DeviceList();
     }
 
+    ::udev_enumerate_add_match_subsystem( enumerate, "block" );
+    ::udev_enumerate_add_match_property( enumerate, "ID_CDROM", "1" );
+    ::udev_enumerate_scan_devices( enumerate );
+
+    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 )
+      {
+       ERR << "Can't create udev device." << endl;
+       continue;
+      }
+
+      if ( supportingDVD && ! ::udev_device_get_property_value( device, "ID_CDROM_DVD" ) )
+      {
+       continue;       // looking for dvd only
+      }
+
+      const char * devnodePtr( ::udev_device_get_devnode( device ) );
+      if ( ! devnodePtr )
+      {
+       ERR << "Got NULL devicenode." << endl;
+       continue;
+      }
+
+      // 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 );
+      }
+    }
     return detected;
   }