1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
13 #include "zypp/base/LogTools.h"
14 #include "zypp/base/Regex.h"
15 #include "zypp/base/UserRequestException.h"
16 #include "zypp/ZYppCallbacks.h"
17 #include "zypp/MediaSetAccess.h"
18 #include "zypp/PathInfo.h"
19 //#include "zypp/source/MediaSetAccessReportReceivers.h"
23 ///////////////////////////////////////////////////////////////////
25 { /////////////////////////////////////////////////////////////////
27 IMPL_PTR_TYPE(MediaSetAccess);
29 ///////////////////////////////////////////////////////////////////
31 MediaSetAccess::MediaSetAccess(const Url &url,
32 const Pathname & prefered_attach_point)
34 , _prefAttachPoint(prefered_attach_point)
37 MediaSetAccess::MediaSetAccess(const std::string & label_r,
39 const Pathname & prefered_attach_point)
41 , _prefAttachPoint(prefered_attach_point)
45 MediaSetAccess::~MediaSetAccess()
51 catch(...) {} // don't let exception escape a dtor.
55 void MediaSetAccess::setVerifier( unsigned media_nr, media::MediaVerifierRef verifier )
57 if (_medias.find(media_nr) != _medias.end())
59 // the media already exists, set theverifier
60 media::MediaAccessId id = _medias[media_nr];
61 media::MediaManager media_mgr;
62 media_mgr.addVerifier( id, verifier );
63 // remove any saved verifier for this media
64 _verifiers.erase(media_nr);
65 //if (! noattach && ! media_mgr.isAttached(id))
66 //media_mgr.attach(id);
70 // save the verifier in the map, and set it when
71 // the media number is first attached
72 _verifiers[media_nr] = verifier;
76 // callback::SendReport<source::DownloadFileReport> report;
77 // DownloadProgressFileReceiver download_report( report );
78 // SourceFactory source_factory;
79 // Url file_url( url().asString() + file_r.asString() );
80 // report->start( source_factory.createFrom(this), file_url );
81 // callback::TempConnect<media::DownloadProgressReport> tmp_download( download_report );
82 // Pathname file = provideJustFile( file_r, media_nr, cached, checkonly );
83 // report->finish( file_url, source::DownloadFileReport::NO_ERROR, "" );
86 void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file )
88 releaseFile( on_media_file.filename(), on_media_file.medianr() );
91 void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
93 media::MediaManager media_mgr;
94 media::MediaAccessId media;
96 media = getMediaAccessId( media_nr);
97 DBG << "Going to release file " << file
98 << " from media number " << media_nr << endl;
100 if ( ! media_mgr.isAttached(media) )
101 return; //disattached media is free
103 media_mgr.releaseFile (media, file);
106 void MediaSetAccess::dirInfo( filesystem::DirContent &retlist, const Pathname &dirname,
107 bool dots, unsigned media_nr )
109 media::MediaManager media_mgr;
110 media::MediaAccessId media;
111 media = getMediaAccessId(media_nr);
113 // try to attach the media
114 if ( ! media_mgr.isAttached(media) )
115 media_mgr.attachDesiredMedia(media);
117 media_mgr.dirInfo(media, retlist, dirname, dots);
120 Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options )
122 return provide( ProvideFile, resource, options );
125 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options )
127 OnMediaLocation resource;
128 resource.setLocation(file, media_nr);
129 return provide( ProvideFile, resource, options );
132 Pathname MediaSetAccess::provideOptionalFile(const Pathname & file, unsigned media_nr )
134 OnMediaLocation resource;
135 resource.setLocation(file, media_nr);
138 ret = provide(ProvideFile, resource, NON_INTERACTIVE);
140 catch ( const Exception &e )
148 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
150 callback::SendReport<media::MediaChangeReport> report;
151 media::MediaManager media_mgr;
156 // get the mediaId, but don't try to attach it here
157 media::MediaAccessId media = getMediaAccessId( media_nr);
161 DBG << "Cheking if file " << file
162 << " from media number " << media_nr << " exists." << endl;
163 // try to attach the media
164 if ( ! media_mgr.isAttached(media) )
165 media_mgr.attachDesiredMedia(media);
166 exists = media_mgr.doesFileExist(media, file);
169 catch ( media::MediaException & excp )
172 media::MediaChangeReport::Action user;
175 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
178 media_mgr.release (media);
180 catch (const Exception & excpt_r)
182 ZYPP_CAUGHT(excpt_r);
183 MIL << "Failed to release media " << media << endl;
187 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
189 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
190 typeid(excp) == typeid( media::MediaNotAFileException ) )
192 reason = media::MediaChangeReport::NOT_FOUND;
194 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
195 typeid(excp) == typeid( media::MediaNotAttachedException) )
197 reason = media::MediaChangeReport::WRONG;
199 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
200 typeid(excp) == typeid( media::MediaTemporaryProblemException))
202 reason = media::MediaChangeReport::IO_SOFT;
205 vector<string> devices;
206 unsigned int devindex;
207 media_mgr.getDetectedDevices(media, devices, devindex);
209 // release all media before requesting another (#336881)
210 media_mgr.releaseAll();
212 user = report->requestMedia (
221 MIL << "doesFileExist exception caught, callback answer: " << user << endl;
223 if( user == media::MediaChangeReport::ABORT )
225 DBG << "Aborting" << endl;
226 ZYPP_RETHROW ( excp );
228 else if ( user == media::MediaChangeReport::IGNORE )
230 DBG << "Skipping" << endl;
231 SkipRequestException nexcp("User-requested skipping of a file");
232 nexcp.remember(excp);
235 else if ( user == media::MediaChangeReport::EJECT )
237 DBG << "Eject: try to release" << endl;
238 media_mgr.releaseAll();
240 media_mgr.release (media,
241 devindex < devices.size() ? devices[devindex] : "");
243 else if ( user == media::MediaChangeReport::RETRY ||
244 user == media::MediaChangeReport::CHANGE_URL )
247 DBG << "Going to try again" << endl;
248 // invalidate current media access id
249 media_mgr.close(media);
250 _medias.erase(media_nr);
252 // not attaching, media set will do that for us
253 // this could generate uncaught exception (#158620)
258 DBG << "Don't know, let's ABORT" << endl;
259 ZYPP_RETHROW ( excp );
261 } while( user == media::MediaChangeReport::EJECT );
264 // retry or change URL
270 Pathname MediaSetAccess::provide( ProvideAction action,
271 const OnMediaLocation &resource,
272 ProvideFileOptions options )
274 Pathname file(resource.filename());
275 unsigned media_nr(resource.medianr());
277 callback::SendReport<media::MediaChangeReport> report;
278 media::MediaManager media_mgr;
280 media::MediaAccessId media;
284 // get the mediaId, but don't try to attach it here
285 media = getMediaAccessId( media_nr);
289 DBG << "Going to try to provide file " << file
290 << " from media number " << media_nr << endl;
291 // try to attach the media
292 if ( ! media_mgr.isAttached(media) )
293 media_mgr.attachDesiredMedia(media);
298 media_mgr.provideFile (media, file); break;
300 media_mgr.provideDir (media, file); break;
301 case ProvideDirRecursive:
302 media_mgr.provideDirTree(media, file); break;
304 ZYPP_THROW(Exception("Unknown action"));
308 catch ( media::MediaException & excp )
311 media::MediaChangeReport::Action user = media::MediaChangeReport::ABORT;
312 unsigned int devindex = 0;
313 vector<string> devices;
314 media_mgr.getDetectedDevices(media, devices, devindex);
318 if (user != media::MediaChangeReport::EJECT) // no use in calling this again
320 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
323 media_mgr.release(media);
325 catch (const Exception & excpt_r)
327 ZYPP_CAUGHT(excpt_r);
328 MIL << "Failed to release media " << media << endl;
333 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
335 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
336 typeid(excp) == typeid( media::MediaNotAFileException ) )
338 reason = media::MediaChangeReport::NOT_FOUND;
340 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
341 typeid(excp) == typeid( media::MediaNotAttachedException) )
343 reason = media::MediaChangeReport::WRONG;
345 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
346 typeid(excp) == typeid( media::MediaTemporaryProblemException))
348 reason = media::MediaChangeReport::IO_SOFT;
351 // non interactive only bother the user if wrong medium is in the drive
352 // otherwise propagate the error
353 if ( ( options & NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG)
359 // release all media before requesting another (#336881)
360 media_mgr.releaseAll();
362 user = report->requestMedia (
373 MIL << "ProvideFile exception caught, callback answer: " << user << endl;
375 if( user == media::MediaChangeReport::ABORT )
377 DBG << "Aborting" << endl;
378 ZYPP_RETHROW ( excp );
380 else if ( user == media::MediaChangeReport::IGNORE )
382 DBG << "Skipping" << endl;
383 SkipRequestException nexcp("User-requested skipping of a file");
384 nexcp.remember(excp);
387 else if ( user == media::MediaChangeReport::EJECT )
389 DBG << "Eject: try to release" << endl;
390 media_mgr.releaseAll();
392 media_mgr.release (media,
393 devindex < devices.size() ? devices[devindex] : "");
395 else if ( user == media::MediaChangeReport::RETRY ||
396 user == media::MediaChangeReport::CHANGE_URL )
399 DBG << "Going to try again" << endl;
400 // invalidate current media access id
401 media_mgr.close(media);
402 _medias.erase(media_nr);
404 // not attaching, media set will do that for us
405 // this could generate uncaught exception (#158620)
410 DBG << "Don't know, let's ABORT" << endl;
411 ZYPP_RETHROW ( excp );
413 } while( user == media::MediaChangeReport::EJECT );
416 // retry or change URL
419 return media_mgr.localPath( media, file );
423 Pathname MediaSetAccess::provideDir(const Pathname & dir,
426 ProvideFileOptions options )
428 OnMediaLocation resource;
429 resource.setLocation(dir, media_nr);
431 return provide( recursive? ProvideDir : ProvideDirRecursive, resource, options );
434 media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
436 media::MediaManager media_mgr;
438 if (_medias.find(medianr) != _medias.end())
440 media::MediaAccessId id = _medias[medianr];
441 //if (! noattach && ! media_mgr.isAttached(id))
442 //media_mgr.attach(id);
446 url = rewriteUrl (_url, medianr);
447 media::MediaAccessId id = media_mgr.open(url, _prefAttachPoint);
448 _medias[medianr] = id;
452 if (_verifiers.find(medianr) != _verifiers.end())
454 // a verifier is set for this media
455 // FIXME check the case where the verifier exists
456 // but we have no access id for the media
457 media::MediaAccessId id = _medias[medianr];
458 media::MediaManager media_mgr;
459 media_mgr.delVerifier(id);
460 media_mgr.addVerifier( id, _verifiers[medianr] );
461 // remove any saved verifier for this media
462 _verifiers.erase(medianr);
465 catch ( const Exception &e )
468 WAR << "Verifier not found" << endl;
475 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
477 std::string scheme = url_r.getScheme();
478 if (scheme == "cd" || scheme == "dvd")
481 DBG << "Rewriting url " << url_r << endl;
485 // TODO the iso parameter will not be required in the future, this
486 // code has to be adapted together with the MediaISO change.
487 // maybe some MediaISOURL interface should be used.
488 std::string isofile = url_r.getQueryParam("iso");
489 str::regex e("^(.*)(cd|dvd)[0-9]+\\.iso$", str::regex::icase);
492 if(str::regex_match(isofile, what, e))
495 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
496 url.setQueryParam("iso", isofile);
497 DBG << "Url rewrite result: " << url << endl;
503 std::string pathname = url_r.getPathName();
504 str::regex e("^(.*)(cd|dvd)[0-9]+(/)?$", str::regex::icase);
506 if(str::regex_match(pathname, what, e))
509 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
510 url.setPathName(pathname);
511 DBG << "Url rewrite result: " << url << endl;
518 void MediaSetAccess::release()
520 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
521 media::MediaManager manager;
522 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
523 manager.release(m->second, "");
526 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
528 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
532 // media::MediaVerifierRef MediaSetAccess::verifier(unsigned media_nr)
533 // { return media::MediaVerifierRef(new media::NoVerifier()); }
535 /////////////////////////////////////////////////////////////////
537 ///////////////////////////////////////////////////////////////////