1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaCD.cc
15 #include "zypp/base/Logger.h"
16 #include "zypp/ExternalProgram.h"
17 #include "zypp/media/Mount.h"
18 #include "zypp/media/MediaCD.h"
20 #include <cstring> // strerror
25 #include <sys/ioctl.h>
29 #include <linux/cdrom.h>
37 ///////////////////////////////////////////////////////////////////
39 // CLASS NAME : MediaCD
41 ///////////////////////////////////////////////////////////////////
43 ///////////////////////////////////////////////////////////////////
46 // METHOD NAME : MediaCD::MediaCD
47 // METHOD TYPE : Constructor
51 MediaCD::MediaCD( const Url & url_r,
52 const Pathname & attach_point_hint_r )
53 : MediaHandler( url_r, attach_point_hint_r,
54 url_r.getPathName(), // urlpath below attachpoint
55 false ), // does_download
58 string devices = _url.getQueryParam("devices");
61 string::size_type pos;
62 DBG << "parse " << devices << endl;
63 while(!devices.empty())
65 pos = devices.find(',');
66 string device = devices.substr(0,pos);
69 _devices.push_back(device);
70 DBG << "use device " << device << endl;
72 if (pos!=string::npos)
73 devices=devices.substr(pos+1);
80 //default is /dev/cdrom; for dvd: /dev/dvd if it exists
81 //TODO: make configurable
82 string device( "/dev/cdrom" );
83 if ( _url.getScheme() == "dvd" && PathInfo( "/dev/dvd" ).isBlk() ) {
86 DBG << "use default device " << device << endl;
87 _devices.push_back(device);
91 ///////////////////////////////////////////////////////////////////
94 // METHOD NAME : MediaCD::openTray
97 bool MediaCD::openTray( const string & device_r )
99 int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK );
101 WAR << "Unable to open '" << device_r << "' (" << ::strerror( errno ) << ")" << endl;
104 int res = ::ioctl( fd, CDROMEJECT );
107 WAR << "Eject " << device_r << " failed (" << ::strerror( errno ) << ")" << endl;
110 MIL << "Eject " << device_r << endl;
114 ///////////////////////////////////////////////////////////////////
117 // METHOD NAME : MediaCD::closeTray
118 // METHOD TYPE : bool
120 bool MediaCD::closeTray( const string & device_r )
122 int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK );
124 WAR << "Unable to open '" << device_r << "' (" << ::strerror( errno ) << ")" << endl;
127 int res = ::ioctl( fd, CDROMCLOSETRAY );
130 WAR << "Close tray " << device_r << " failed (" << ::strerror( errno ) << ")" << endl;
133 DBG << "Close tray " << device_r << endl;
137 ///////////////////////////////////////////////////////////////////
140 // METHOD NAME : MediaCD::attachTo
141 // METHOD TYPE : PMError
143 // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory.
145 void MediaCD::attachTo(bool next)
148 const char *mountpoint = attachPoint().asString().c_str();
149 bool mountsucceeded = false;
152 DBG << "next " << next << " last " << _lastdev << " lastdevice " << _mounteddevice << endl;
154 if (next && _lastdev == -1)
155 ZYPP_THROW(MediaNotSupportedException(url()));
157 string options = _url.getQueryParam("mountoptions");
163 //TODO: make configurable
164 list<string> filesystems;
166 // if DVD, try UDF filesystem before iso9660
167 if ( _url.getScheme() == "dvd" )
168 filesystems.push_back("udf");
170 filesystems.push_back("iso9660");
172 // try all devices in sequence
173 for (DeviceList::iterator it = _devices.begin()
174 ; !mountsucceeded && it != _devices.end()
177 DBG << "count " << count << endl;
178 if (next && count<=_lastdev )
180 DBG << "skip" << endl;
187 // try all filesystems in sequence
188 for(list<string>::iterator fsit = filesystems.begin()
189 ; !mountsucceeded && fsit != filesystems.end()
193 mount.mount (*it, mountpoint, *fsit, options);
194 _mounteddevice = *it;
196 mountsucceeded = true;
198 catch (const MediaException & excpt_r)
200 ZYPP_CAUGHT(excpt_r);
207 _mounteddevice.erase();
209 // FIXME not suitable for MediaMountExeption, as device cannot be
211 // errors might be different as well
212 ZYPP_THROW(MediaException("Error::E_mount_failed"));
214 DBG << _lastdev << " " << count << endl;
218 ///////////////////////////////////////////////////////////////////
221 // METHOD NAME : MediaCD::releaseFrom
222 // METHOD TYPE : PMError
224 // DESCRIPTION : Asserted that media is attached.
226 void MediaCD::releaseFrom( bool eject )
228 if (_mounteddevice.empty()) // no device mounted
230 if (eject) // eject wanted -> eject all devices
232 for (DeviceList::iterator it = _devices.begin()
233 ; it != _devices.end()
240 ZYPP_THROW(MediaNotAttachedException(url()));
244 mount.umount(attachPoint().asString());
249 openTray( _mounteddevice );
252 _mounteddevice.erase();
255 ///////////////////////////////////////////////////////////////////
258 // METHOD NAME : MediaCD::forceEject
259 // METHOD TYPE : void
261 // Asserted that media is not attached.
263 void MediaCD::forceEject()
265 if ( _mounteddevice.empty() ) { // no device mounted
266 for ( DeviceList::iterator it = _devices.begin(); it != _devices.end(); ++it ) {
267 if ( openTray( *it ) )
268 break; // on 1st success
273 ///////////////////////////////////////////////////////////////////
275 // METHOD NAME : MediaCD::getFile
276 // METHOD TYPE : PMError
278 // DESCRIPTION : Asserted that media is attached.
280 void MediaCD::getFile( const Pathname & filename ) const
282 MediaHandler::getFile( filename );
285 ///////////////////////////////////////////////////////////////////
287 // METHOD NAME : MediaCD::getDir
288 // METHOD TYPE : PMError
290 // DESCRIPTION : Asserted that media is attached.
292 void MediaCD::getDir( const Pathname & dirname, bool recurse_r ) const
294 MediaHandler::getDir( dirname, recurse_r );
297 ///////////////////////////////////////////////////////////////////
300 // METHOD NAME : MediaCD::getDirInfo
301 // METHOD TYPE : PMError
303 // DESCRIPTION : Asserted that media is attached and retlist is empty.
305 void MediaCD::getDirInfo( std::list<std::string> & retlist,
306 const Pathname & dirname, bool dots ) const
308 MediaHandler::getDirInfo( retlist, dirname, dots );
311 ///////////////////////////////////////////////////////////////////
314 // METHOD NAME : MediaCD::getDirInfo
315 // METHOD TYPE : PMError
317 // DESCRIPTION : Asserted that media is attached and retlist is empty.
319 void MediaCD::getDirInfo( filesystem::DirContent & retlist,
320 const Pathname & dirname, bool dots ) const
322 MediaHandler::getDirInfo( retlist, dirname, dots );