14 #include <sys/ioctl.h>
15 #include <linux/cdrom.h>
44 #define REPORT_EJECT_ERRORS 1
50 #define EJECT_TOOL_PATH "/bin/eject"
65 typedef std::list<MediaSource> DeviceList;
76 DeviceList systemDetectDevices(
bool supportingDVD_r )
85 ERR <<
"Can't create udev context." << endl;
92 ERR <<
"Can't create udev list entry." << endl;
96 ::udev_enumerate_add_match_subsystem( enumerate,
"block" );
97 ::udev_enumerate_add_match_property( enumerate,
"ID_CDROM",
"1" );
98 ::udev_enumerate_scan_devices( enumerate );
100 struct udev_list_entry * entry = 0;
101 udev_list_entry_foreach( entry, ::udev_enumerate_get_list_entry( enumerate ) )
104 ::udev_list_entry_get_name( entry ) ),
105 ::udev_device_unref );
108 ERR <<
"Can't create udev device." << endl;
112 if ( supportingDVD_r && ! ::udev_device_get_property_value( device,
"ID_CDROM_DVD" ) )
117 const char * devnodePtr( ::udev_device_get_devnode( device ) );
120 ERR <<
"Got NULL devicenode." << endl;
127 PathInfo devnode( devnodePtr );
128 if ( devnode.isBlk() )
130 MediaSource media(
"cdrom", devnode.path().asString(), devnode.major(), devnode.minor() );
131 DBG <<
"Found (udev): " << media << std::endl;
132 detected.push_back( media );
135 if ( detected.empty() )
137 WAR <<
"Did not find any CD/DVD device." << endl;
140 using namespace zypp::target::hal;
145 std::vector<std::string> drv_udis;
148 DBG <<
"Found " << drv_udis.size() <<
" cdrom drive udis" << std::endl;
149 for(
size_t d = 0; d < drv_udis.size(); d++)
155 bool supportsDVD=
false;
158 std::vector<std::string> caps;
167 std::vector<std::string>::const_iterator ci;
168 for( ci=caps.begin(); ci != caps.end(); ++ci)
175 MediaSource media(
"cdrom", drv.getDeviceFile(),
176 drv.getDeviceMajor(),
177 drv.getDeviceMinor());
178 DBG <<
"Found " << drv_udis[d] <<
": "
179 << media.asString() << std::endl;
180 if( supportingDVD_r && supportsDVD)
182 detected.push_front(media);
186 detected.push_back(media);
203 MediaCD::MediaCD(
const Url & url_r,
const Pathname & attach_point_hint_r )
204 :
MediaHandler( url_r, attach_point_hint_r, url_r.getPathName(), false )
206 , _lastdev_tried( -1 )
208 MIL <<
"MediaCD::MediaCD(" << url_r <<
", " << attach_point_hint_r <<
")" << endl;
212 ERR <<
"Unsupported schema in the Url: " << url_r.
asString() << endl;
217 if ( ! devices.empty() )
219 std::vector<std::string> words;
220 str::split( devices, std::back_inserter(words),
"," );
221 for (
const std::string & device : words )
223 if ( device.empty() )
228 DBG <<
"use device (delayed verify)" << device << endl;
233 DBG <<
"going to use on-demand device list" << endl;
239 ERR <<
"Unable to find any cdrom drive for " <<
_url.
asString() << endl;
252 int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK|O_CLOEXEC );
257 res = ::ioctl( fd, CDROMEJECT );
265 WAR <<
"Unable to open '" << device_r
266 <<
"' (" <<
::strerror( errno ) <<
")" << endl;
270 WAR <<
"Eject " << device_r
271 <<
" failed (" <<
::strerror( errno ) <<
")" << endl;
274 #if defined(EJECT_TOOL_PATH)
275 DBG <<
"Try to eject " << device_r <<
" using "
280 cmd[1] = device_r.c_str();
290 if(eject.
close() != 0)
292 WAR <<
"Eject of " << device_r <<
" failed." << std::endl;
299 MIL <<
"Eject of " << device_r <<
" successful." << endl;
311 int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK|O_CLOEXEC );
313 WAR <<
"Unable to open '" << device_r <<
"' (" <<
::strerror( errno ) <<
")" << endl;
316 int res = ::ioctl( fd, CDROMCLOSETRAY );
319 WAR <<
"Close tray " << device_r <<
" failed (" <<
::strerror( errno ) <<
")" << endl;
322 DBG <<
"Close tray " << device_r << endl;
329 DeviceList detected( systemDetectDevices( supportingDVD_r ) );
331 if ( detected.empty() )
333 WAR <<
"CD/DVD drive detection with HAL/UDEV failed! Guessing..." << std::endl;
334 PathInfo dvdinfo(
"/dev/dvd" );
335 PathInfo cdrinfo(
"/dev/cdrom" );
336 if ( dvdinfo.isBlk() )
338 MediaSource media(
"cdrom", dvdinfo.path().asString(), dvdinfo.major(), dvdinfo.minor() );
339 DBG <<
"Found (GUESS): " << media << std::endl;
340 detected.push_back( media );
343 && ! ( cdrinfo.major() == dvdinfo.major() && cdrinfo.minor() == dvdinfo.minor() ) )
345 MediaSource media(
"cdrom", cdrinfo.path().asString(), cdrinfo.major(), cdrinfo.minor() );
346 DBG <<
"Found (GUESS): " << media << std::endl;
347 detected.push_back( media );
356 DBG <<
"creating on-demand device list" << endl;
358 string device(
"/dev/cdrom" );
359 if (
_url.
getScheme() ==
"dvd" && PathInfo(
"/dev/dvd" ).isBlk() )
364 PathInfo dinfo( device );
367 MediaSource media(
"cdrom", device, dinfo.major(), dinfo.minor() );
368 if ( detected.empty() )
374 for(
const auto & d : detected )
377 if ( media.equals( d ) )
417 if ( options.empty() )
423 list<string> filesystems;
427 filesystems.push_back(
"udf");
429 filesystems.push_back(
"iso9660");
433 bool mountsucceeded =
false;
434 for ( DeviceList::iterator it =
_devices.begin() ; ! mountsucceeded && it !=
_devices.end() ; ++it, ++count )
436 DBG <<
"count " << count << endl;
439 DBG <<
"skipping device " << it->name << endl;
448 PathInfo dinfo( temp.
name );
449 if ( ! dinfo.isBlk() )
451 WAR <<
"skipping non block device: " << dinfo << endl;
454 DBG <<
"trying device " << dinfo << endl;
456 temp.
maj_nr = dinfo.major();
457 temp.
min_nr = dinfo.minor();
464 DBG <<
"Using a shared media "
473 mountsucceeded =
true;
480 MountEntries::const_iterator e;
481 for( e = entries.begin(); e != entries.end(); ++e)
483 bool is_device =
false;
484 std::string dev_path(Pathname(e->src).asString());
487 if( dev_path.compare(0,
sizeof(
"/dev/")-1,
"/dev/") == 0 &&
488 dev_info(e->src) && dev_info.isBlk())
493 if( is_device && media->maj_nr == dev_info.major() &&
494 media->min_nr == dev_info.minor())
499 DBG <<
"Using a system mounted media "
510 mountsucceeded =
true;
523 for(list<string>::iterator fsit = filesystems.begin()
524 ; !mountsucceeded && fsit != filesystems.end()
533 if( mountpoint.empty())
539 mount.
mount(it->name, mountpoint, *fsit, options);
546 while( !(mountsucceeded=
isAttached()) && --limit)
548 WAR <<
"Wait for /proc/mounts update and retry...." << endl;
568 "Unable to verify that the media was mounted",
628 if (!ejectDev.empty())
638 if (!ejectDev.empty())
643 #if REPORT_EJECT_ERRORS
660 bool ejected =
false;
668 if ( media->name != ejectDev_r )
674 PathInfo dinfo( media->name );
675 if( ! dinfo.isBlk() )
677 WAR <<
"skipping non block device: " << dinfo << endl;
680 DBG <<
"trying device " << dinfo << endl;
695 #if REPORT_EJECT_ERRORS
749 const Pathname & dirname,
bool dots )
const
787 if ( ! devices.empty() )
795 devices.push_back( it.name );
799 MIL <<
"got " << devices.size() <<
" detected devices, current: "
800 << (index < devices.size() ? devices[index] :
"<none>")
801 <<
"(" << index <<
")" << endl;
Hardware abstaction layer library wrapper.
std::vector< std::string > getCdromCapabilityNames() const
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
unsigned split(const C_Str &line_r, _OutputIterator result_r, const C_Str &sepchars_r=" \t")
Split line_r into words.
Hardware abstaction layer storage drive object.
HalDrive getDriveFromUDI(const std::string &udi) const
Construct a HalDrive object for the specified UDI.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Hardware abstaction layer exception.
std::string asString() const
Returns a default string representation of the Url object.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::list< DirEntry > DirContent
Returned by readdir.
std::vector< std::string > findDevicesByCapability(const std::string &capability) const
Retrieve UDI's of all devices with a capability.
std::string receiveLine()
Read one line from the input stream.
std::string getQueryParam(const std::string ¶m, EEncoding eflag=zypp::url::E_DECODED) const
Return the value for the specified query parameter.
std::string asString(const Patch::SeverityFlag &obj)
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 ...
std::string getScheme() const
Returns the scheme name of the URL.
std::string strerror(int errno_r)
Return string describing the error_r code.