14 #include <sys/ioctl.h> 15 #include <linux/cdrom.h> 27 #include <zypp-media/Mount> 28 #include <zypp-media/CDTools> 39 #define REPORT_EJECT_ERRORS 0 52 using DeviceList = std::list<MediaSource>;
59 DeviceList systemDetectDevices(
bool supportingDVD_r )
68 ERR <<
"Can't create udev context." << endl;
75 ERR <<
"Can't create udev list entry." << endl;
79 ::udev_enumerate_add_match_subsystem( enumerate,
"block" );
80 ::udev_enumerate_add_match_property( enumerate,
"ID_CDROM",
"1" );
81 ::udev_enumerate_scan_devices( enumerate );
83 struct udev_list_entry * entry = 0;
84 udev_list_entry_foreach( entry, ::udev_enumerate_get_list_entry( enumerate ) )
87 ::udev_list_entry_get_name( entry ) ),
88 ::udev_device_unref );
91 ERR <<
"Can't create udev device." << endl;
95 if ( supportingDVD_r && ! ::udev_device_get_property_value( device,
"ID_CDROM_DVD" ) )
100 const char * devnodePtr( ::udev_device_get_devnode( device ) );
103 ERR <<
"Got NULL devicenode." << endl;
110 PathInfo devnode( devnodePtr );
111 if ( devnode.isBlk() )
113 MediaSource media(
"cdrom", devnode.path().asString(), devnode.devMajor(), devnode.devMinor() );
114 DBG <<
"Found (udev): " << media << std::endl;
115 detected.push_back( media );
118 if ( detected.empty() )
120 WAR <<
"Did not find any CD/DVD device." << endl;
131 :
MediaHandler( origin_r, attach_point_hint_r, origin_r.authority().url().getPathName(), false )
133 , _lastdev_tried( -1 )
135 MIL <<
"MediaCD::MediaCD(" <<
url() <<
", " << attach_point_hint_r <<
")" << endl;
140 ERR <<
"Unsupported schema in the Url: " << authorityUrl.asString() << endl;
144 std::string devices = authorityUrl.getQueryParam(
"devices" );
145 if ( ! devices.empty() )
147 std::vector<std::string> words;
148 str::split( devices, std::back_inserter(words),
"," );
149 for (
const std::string & device : words )
151 if ( device.empty() )
156 DBG <<
"use device (delayed verify)" << device << endl;
161 DBG <<
"going to use on-demand device list" << endl;
167 ERR <<
"Unable to find any cdrom drive for " << authorityUrl.asString() << endl;
197 DeviceList detected( systemDetectDevices( supportingDVD_r ) );
199 if ( detected.empty() )
201 WAR <<
"CD/DVD drive detection with UDEV failed! Guessing..." << std::endl;
204 if ( dvdinfo.
isBlk() )
207 DBG <<
"Found (GUESS): " << media << std::endl;
208 detected.push_back( media );
214 DBG <<
"Found (GUESS): " << media << std::endl;
215 detected.push_back( media );
224 DBG <<
"creating on-demand device list" << endl;
226 std::string device(
"/dev/cdrom" );
236 if ( detected.empty() )
242 for(
const auto & d : detected )
245 if ( media.equals( d ) )
285 std::string options = authorityUrl.getQueryParam(
"mountoptions" );
286 if ( options.empty() )
292 std::list<std::string> filesystems;
294 filesystems.push_back(
"iso9660");
297 if ( authorityUrl.getScheme() ==
"dvd" )
298 filesystems.push_back(
"udf");
303 bool mountsucceeded =
false;
304 for ( DeviceList::iterator it =
_devices.begin() ; ! mountsucceeded && it !=
_devices.end() ; ++it, ++count )
306 DBG <<
"count " << count << endl;
309 DBG <<
"skipping device " << it->name << endl;
319 if ( ! dinfo.
isBlk() )
321 WAR <<
"skipping non block device: " << dinfo << endl;
324 DBG <<
"trying device " << dinfo << endl;
334 DBG <<
"Using a shared media " 343 mountsucceeded =
true;
350 MountEntries::const_iterator e;
351 for( e = entries.begin(); e != entries.end(); ++e)
353 bool is_device =
false;
357 if( dev_path.compare(0,
sizeof(
"/dev/")-1,
"/dev/") == 0 &&
358 dev_info(e->src) && dev_info.isBlk())
363 if( is_device && media->maj_nr == dev_info.devMajor() &&
364 media->min_nr == dev_info.devMinor())
369 DBG <<
"Using a system mounted media " 380 mountsucceeded =
true;
393 for(std::list<std::string>::iterator fsit = filesystems.begin()
394 ; !mountsucceeded && fsit != filesystems.end()
405 mount.
mount(it->name, mountpoint, *fsit, options);
412 while( !(mountsucceeded=
isAttached()) && --limit)
414 WAR <<
"Wait for /proc/mounts update and retry...." << endl;
434 "Unable to verify that the media was mounted",
460 authorityUrl.asString(),
467 authorityUrl.asString(), mountpoint));
494 if (!ejectDev.empty())
504 if (!ejectDev.empty())
509 #if REPORT_EJECT_ERRORS 526 #if REPORT_EJECT_ERRORS 527 bool ejected =
false;
536 if ( media->name != ejectDev_r )
543 if( ! dinfo.
isBlk() )
545 WAR <<
"skipping non block device: " << dinfo << endl;
548 DBG <<
"trying device " << dinfo << endl;
557 #if REPORT_EJECT_ERRORS 565 #if REPORT_EJECT_ERRORS 619 const Pathname & dirname,
bool dots )
const 657 if ( ! devices.empty() )
665 devices.push_back( it.name );
669 MIL <<
"got " << devices.size() <<
" detected devices, current: " 670 << (index < devices.size() ? devices[index] :
"<none>")
671 <<
"(" << index <<
")" << endl;
const Pathname & path() const
Return current Pathname.
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
const zypp::Url & url() const
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
unsigned int devMinor() const
std::list< DirEntry > DirContent
Returned by readdir.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \, const Trim trim_r=NO_TRIM)
Split line_r into words.
Manages a data source characterized by an authoritative URL and a list of mirror URLs.
const std::string & asString() const
String representation.
std::string scheme() const
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Base class for Exception.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
unsigned int devMajor() const
Wrapper class for ::stat/::lstat.
const OriginEndpoint & authority() const