14 #include <sys/ioctl.h> 15 #include <linux/cdrom.h> 38 #define REPORT_EJECT_ERRORS 0 44 #define EJECT_TOOL_PATH "/bin/eject" 59 typedef std::list<MediaSource> DeviceList;
66 DeviceList systemDetectDevices(
bool supportingDVD_r )
75 ERR <<
"Can't create udev context." << endl;
82 ERR <<
"Can't create udev list entry." << endl;
86 ::udev_enumerate_add_match_subsystem( enumerate,
"block" );
87 ::udev_enumerate_add_match_property( enumerate,
"ID_CDROM",
"1" );
88 ::udev_enumerate_scan_devices( enumerate );
90 struct udev_list_entry * entry = 0;
91 udev_list_entry_foreach( entry, ::udev_enumerate_get_list_entry( enumerate ) )
94 ::udev_list_entry_get_name( entry ) ),
95 ::udev_device_unref );
98 ERR <<
"Can't create udev device." << endl;
102 if ( supportingDVD_r && ! ::udev_device_get_property_value( device,
"ID_CDROM_DVD" ) )
107 const char * devnodePtr( ::udev_device_get_devnode( device ) );
110 ERR <<
"Got NULL devicenode." << endl;
117 PathInfo devnode( devnodePtr );
118 if ( devnode.isBlk() )
120 MediaSource media(
"cdrom", devnode.path().asString(), devnode.devMajor(), devnode.devMinor() );
121 DBG <<
"Found (udev): " << media << std::endl;
122 detected.push_back( media );
125 if ( detected.empty() )
127 WAR <<
"Did not find any CD/DVD device." << endl;
137 MediaCD::MediaCD(
const Url & url_r,
const Pathname & attach_point_hint_r )
138 :
MediaHandler( url_r, attach_point_hint_r, url_r.getPathName(), false )
140 , _lastdev_tried( -1 )
142 MIL <<
"MediaCD::MediaCD(" << url_r <<
", " << attach_point_hint_r <<
")" << endl;
146 ERR <<
"Unsupported schema in the Url: " << url_r.
asString() << endl;
151 if ( ! devices.empty() )
153 std::vector<std::string> words;
154 str::split( devices, std::back_inserter(words),
"," );
155 for (
const std::string & device : words )
157 if ( device.empty() )
162 DBG <<
"use device (delayed verify)" << device << endl;
167 DBG <<
"going to use on-demand device list" << endl;
173 ERR <<
"Unable to find any cdrom drive for " <<
_url.
asString() << endl;
186 int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK|O_CLOEXEC );
191 res = ::ioctl( fd, CDROMEJECT );
199 WAR <<
"Unable to open '" << device_r
200 <<
"' (" <<
::strerror( errno ) <<
")" << endl;
204 WAR <<
"Eject " << device_r
205 <<
" failed (" <<
::strerror( errno ) <<
")" << endl;
208 #if defined(EJECT_TOOL_PATH) 209 DBG <<
"Try to eject " << device_r <<
" using " 214 cmd[1] = device_r.c_str();
224 if(eject.
close() != 0)
226 WAR <<
"Eject of " << device_r <<
" failed." << std::endl;
233 MIL <<
"Eject of " << device_r <<
" successful." << endl;
245 int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK|O_CLOEXEC );
247 WAR <<
"Unable to open '" << device_r <<
"' (" <<
::strerror( errno ) <<
")" << endl;
250 int res = ::ioctl( fd, CDROMCLOSETRAY );
253 WAR <<
"Close tray " << device_r <<
" failed (" <<
::strerror( errno ) <<
")" << endl;
256 DBG <<
"Close tray " << device_r << endl;
263 DeviceList detected( systemDetectDevices( supportingDVD_r ) );
265 if ( detected.empty() )
267 WAR <<
"CD/DVD drive detection with UDEV failed! Guessing..." << std::endl;
270 if ( dvdinfo.
isBlk() )
273 DBG <<
"Found (GUESS): " << media << std::endl;
274 detected.push_back( media );
280 DBG <<
"Found (GUESS): " << media << std::endl;
281 detected.push_back( media );
290 DBG <<
"creating on-demand device list" << endl;
292 string device(
"/dev/cdrom" );
302 if ( detected.empty() )
308 for(
const auto & d : detected )
311 if ( media.equals( d ) )
350 if ( options.empty() )
356 list<string> filesystems;
358 filesystems.push_back(
"iso9660");
362 filesystems.push_back(
"udf");
367 bool mountsucceeded =
false;
368 for ( DeviceList::iterator it =
_devices.begin() ; ! mountsucceeded && it !=
_devices.end() ; ++it, ++count )
370 DBG <<
"count " << count << endl;
373 DBG <<
"skipping device " << it->name << endl;
383 if ( ! dinfo.
isBlk() )
385 WAR <<
"skipping non block device: " << dinfo << endl;
388 DBG <<
"trying device " << dinfo << endl;
398 DBG <<
"Using a shared media " 407 mountsucceeded =
true;
414 MountEntries::const_iterator e;
415 for( e = entries.begin(); e != entries.end(); ++e)
417 bool is_device =
false;
421 if( dev_path.compare(0,
sizeof(
"/dev/")-1,
"/dev/") == 0 &&
422 dev_info(e->src) && dev_info.isBlk())
427 if( is_device && media->maj_nr == dev_info.devMajor() &&
428 media->min_nr == dev_info.devMinor())
433 DBG <<
"Using a system mounted media " 444 mountsucceeded =
true;
457 for(list<string>::iterator fsit = filesystems.begin()
458 ; !mountsucceeded && fsit != filesystems.end()
469 mount.
mount(it->name, mountpoint, *fsit, options);
476 while( !(mountsucceeded=
isAttached()) && --limit)
478 WAR <<
"Wait for /proc/mounts update and retry...." << endl;
498 "Unable to verify that the media was mounted",
558 if (!ejectDev.empty())
568 if (!ejectDev.empty())
573 #if REPORT_EJECT_ERRORS 590 #if REPORT_EJECT_ERRORS 591 bool ejected =
false;
600 if ( media->name != ejectDev_r )
607 if( ! dinfo.
isBlk() )
609 WAR <<
"skipping non block device: " << dinfo << endl;
612 DBG <<
"trying device " << dinfo << endl;
621 #if REPORT_EJECT_ERRORS 629 #if REPORT_EJECT_ERRORS 683 const Pathname & dirname,
bool dots )
const 721 if ( ! devices.empty() )
729 devices.push_back( it.name );
733 MIL <<
"got " << devices.size() <<
" detected devices, current: " 734 << (index < devices.size() ? devices[index] :
"<none>")
735 <<
"(" << index <<
")" << endl;
std::string getScheme() const
Returns the scheme name of the URL.
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.
Store and operate with byte count.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
unsigned int devMinor() const
#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.
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.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
const std::string & asString() const
String representation.
std::list< DirEntry > DirContent
Returned by readdir.
std::string receiveLine()
Read one line from the input stream.
int close()
Wait for the progamm to complete.
#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.
std::string strerror(int errno_r)
Return string describing the error_r code.
Easy-to use interface to the ZYPP dependency resolver.