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;
111 if ( devnode.
isBlk() )
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( url_r, attach_point_hint_r, url_r.getPathName(), false )
133 , _lastdev_tried( -1 )
135 MIL <<
"MediaCD::MediaCD(" << url_r <<
", " << attach_point_hint_r <<
")" << endl;
139 ERR <<
"Unsupported schema in the Url: " << url_r.asString() << endl;
140 ZYPP_THROW(MediaUnsupportedUrlSchemeException(_url));
144 if ( ! devices.empty() )
146 std::vector<std::string> words;
147 str::split( devices, std::back_inserter(words),
"," );
148 for ( const std::string & device : words )
150 if ( device.empty() )
153 MediaSource media(
"cdrom", device, 0, 0 );
154 _devices.push_back( media );
155 DBG <<
"use device (delayed verify)" << device << endl;
160 DBG <<
"going to use on-demand device list" << endl;
164 if ( _devices.empty() )
166 ERR <<
"Unable to find any cdrom drive for " << _url.asString() << endl;
167 ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
177 bool MediaCD::openTray(
const std::string & device_r )
179 return CDTools::openTray(device_r);
188 bool MediaCD::closeTray(
const std::string & device_r )
190 return CDTools::closeTray(device_r);
196 DeviceList detected( systemDetectDevices( supportingDVD_r ) );
198 if ( detected.empty() )
200 WAR <<
"CD/DVD drive detection with UDEV failed! Guessing..." << std::endl;
203 if ( dvdinfo.
isBlk() )
206 DBG <<
"Found (GUESS): " << media << std::endl;
207 detected.push_back( media );
213 DBG <<
"Found (GUESS): " << media << std::endl;
214 detected.push_back( media );
221 if ( _devices.empty() )
223 DBG <<
"creating on-demand device list" << endl;
225 std::string device(
"/dev/cdrom" );
235 if ( detected.empty() )
237 _devices.push_front( media );
241 for(
const auto & d : detected )
245 _devices.push_front( d );
247 _devices.push_back( d );
270 void MediaCD::attachTo(
bool next )
272 DBG <<
"next " << next <<
" last " << _lastdev <<
" last tried " << _lastdev_tried << endl;
273 if ( next && _lastdev == -1 )
283 if ( options.empty() )
289 std::list<std::string> filesystems;
291 filesystems.push_back(
"iso9660");
295 filesystems.push_back(
"udf");
299 std::string mountpoint( attachPoint().
asString() );
300 bool mountsucceeded =
false;
301 for ( DeviceList::iterator it = _devices.begin() ; ! mountsucceeded && it != _devices.end() ; ++it, ++count )
303 DBG <<
"count " << count << endl;
304 if (next && count <=_lastdev_tried )
306 DBG <<
"skipping device " << it->name << endl;
309 _lastdev_tried = count;
316 if ( ! dinfo.
isBlk() )
318 WAR <<
"skipping non block device: " << dinfo << endl;
321 DBG <<
"trying device " << dinfo << endl;
331 DBG <<
"Using a shared media "
340 mountsucceeded =
true;
347 MountEntries::const_iterator e;
348 for( e = entries.begin(); e != entries.end(); ++e)
350 bool is_device =
false;
354 if( dev_path.compare(0,
sizeof(
"/dev/")-1,
"/dev/") == 0 &&
355 dev_info(e->src) && dev_info.
isBlk())
360 if( is_device && media->maj_nr == dev_info.
devMajor() &&
361 media->min_nr == dev_info.
devMinor())
366 DBG <<
"Using a system mounted media "
374 setMediaSource(media);
377 mountsucceeded =
true;
387 closeTray( it->name );
390 for(std::list<std::string>::iterator fsit = filesystems.begin()
391 ; !mountsucceeded && fsit != filesystems.end()
396 if( !isUseableAttachPoint( attachPoint() ) )
398 setAttachPoint( createAttachPoint(),
true );
399 mountpoint = attachPoint().asString();
402 mount.
mount(it->name, mountpoint, *fsit, options);
404 setMediaSource(media);
409 while( !(mountsucceeded=isAttached()) && --limit)
411 WAR <<
"Wait for /proc/mounts update and retry...." << endl;
431 "Unable to verify that the media was mounted",
467 DBG << _lastdev <<
" " << count << endl;
479 void MediaCD::releaseFrom(
const std::string & ejectDev )
491 if (!ejectDev.empty())
493 forceRelaseAllMedia(
false);
494 if(openTray( ejectDev ))
501 if (!ejectDev.empty())
503 forceRelaseAllMedia(
false);
504 if( !openTray( ejectDev ))
506#if REPORT_EJECT_ERRORS
521 void MediaCD::forceEject(
const std::string & ejectDev_r )
523#if REPORT_EJECT_ERRORS
524 bool ejected =
false;
526 if ( ! isAttached() )
530 for_( it, _devices.begin(), _devices.end() )
533 if ( media->name != ejectDev_r )
540 if( ! dinfo.
isBlk() )
542 WAR <<
"skipping non block device: " << dinfo << endl;
545 DBG <<
"trying device " << dinfo << endl;
551 forceRelaseAllMedia( media,
false );
552 if ( openTray( it->name ) )
554#if REPORT_EJECT_ERRORS
562#if REPORT_EJECT_ERRORS
578 MediaCD::isAttached()
const
580 return checkAttached(
false);
592 MediaHandler::getFile( file );
602 void MediaCD::getDir(
const Pathname & dirname,
bool recurse_r )
const
604 MediaHandler::getDir( dirname, recurse_r );
615 void MediaCD::getDirInfo( std::list<std::string> & retlist,
616 const Pathname & dirname,
bool dots )
const
618 MediaHandler::getDirInfo( retlist, dirname, dots );
631 MediaHandler::getDirInfo( retlist, dirname, dots );
635 bool MediaCD::getDoesFileExist(
const Pathname & filename )
const
637 return MediaHandler::getDoesFileExist( filename );
641 bool MediaCD::hasMoreDevices()
643 if (_devices.size() == 0)
645 else if (_lastdev_tried < 0)
648 return (
unsigned) _lastdev_tried < _devices.size() - 1;
652 void MediaCD::getDetectedDevices( std::vector<std::string> & devices,
unsigned int & index )
const
654 if ( ! devices.empty() )
657 if ( _devices.empty() )
661 for (
const auto & it : _devices )
662 devices.push_back( it.name );
664 index = ( _lastdev >= 0 ? (unsigned)_lastdev : 0 );
666 MIL <<
"got " << devices.size() <<
" detected devices, current: "
667 << (index < devices.size() ? devices[index] :
"<none>")
668 <<
"(" << index <<
")" << endl;
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Base class for Exception.
std::string getScheme() const
Returns the scheme name of the URL.
std::string asString() const
Returns a default string representation of the Url object.
std::string getQueryParam(const std::string ¶m, EEncoding eflag=zypp::url::E_DECODED) const
Return the value for the specified query parameter.
Wrapper class for stat/lstat.
const Pathname & path() const
Return current Pathname.
unsigned int devMinor() const
unsigned int devMajor() const
const std::string & asString() const
String representation.
std::list< DirEntry > DirContent
Returned by readdir.
Easy-to use interface to the ZYPP dependency resolver.
std::string asString(const Patch::Category &obj)
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.