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)
36 MIL << "initializing.." << std::endl;
37 //std::vector<media::MediaVerifierRef> single_media;
38 //single_media[0] = media::MediaVerifierRef(new media::NoVerifier());
39 //_verifiers = single_media;
43 MediaSetAccess::~MediaSetAccess()
49 void MediaSetAccess::setVerifier( unsigned media_nr, media::MediaVerifierRef verifier )
51 if (_medias.find(media_nr) != _medias.end())
53 // the media already exists, set theverifier
54 media::MediaAccessId id = _medias[media_nr];
55 media::MediaManager media_mgr;
56 media_mgr.addVerifier( id, verifier );
57 // remove any saved verifier for this media
58 _verifiers.erase(media_nr);
59 //if (! noattach && ! media_mgr.isAttached(id))
60 //media_mgr.attach(id);
64 // save the verifier in the map, and set it when
65 // the media number is first attached
66 _verifiers[media_nr] = verifier;
70 // callback::SendReport<source::DownloadFileReport> report;
71 // DownloadProgressFileReceiver download_report( report );
72 // SourceFactory source_factory;
73 // Url file_url( url().asString() + file_r.asString() );
74 // report->start( source_factory.createFrom(this), file_url );
75 // callback::TempConnect<media::DownloadProgressReport> tmp_download( download_report );
76 // Pathname file = provideJustFile( file_r, media_nr, cached, checkonly );
77 // report->finish( file_url, source::DownloadFileReport::NO_ERROR, "" );
81 Pathname MediaSetAccess::provideFile( const OnMediaLocation & on_media_file )
83 return provideFile( on_media_file.filename(), on_media_file.medianr() );
87 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr )
89 return provideFileInternal( file, media_nr, false, false);
92 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
94 callback::SendReport<media::MediaChangeReport> report;
95 media::MediaManager media_mgr;
101 // get the mediaId, but don't try to attach it here
102 media::MediaAccessId media = getMediaAccessId( media_nr);
106 DBG << "Cheking if file " << file
107 << " from media number " << media_nr << " exists." << endl;
108 // try to attach the media
109 if ( ! media_mgr.isAttached(media) )
110 media_mgr.attachDesiredMedia(media);
111 exists = media_mgr.doesFileExist(media, file);
114 catch ( media::MediaException & excp )
117 media::MediaChangeReport::Action user;
120 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
123 media_mgr.release (media);
125 catch (const Exception & excpt_r)
127 ZYPP_CAUGHT(excpt_r);
128 MIL << "Failed to release media " << media << endl;
132 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
134 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
135 typeid(excp) == typeid( media::MediaNotAFileException ) )
137 reason = media::MediaChangeReport::NOT_FOUND;
139 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
140 typeid(excp) == typeid( media::MediaNotAttachedException) )
142 reason = media::MediaChangeReport::WRONG;
145 vector<string> devices;
146 unsigned int devindex;
147 media_mgr.getDetectedDevices(media, devices, devindex);
149 // release all media before requesting another (#336881)
150 media_mgr.releaseAll();
152 user = report->requestMedia (
155 string(), //! \todo label
161 DBG << "doesFileExist exception caught, callback answer: " << user << endl;
163 if( user == media::MediaChangeReport::ABORT )
165 DBG << "Aborting" << endl;
166 ZYPP_RETHROW ( excp );
168 else if ( user == media::MediaChangeReport::IGNORE )
170 DBG << "Skipping" << endl;
171 SkipRequestException nexcp("User-requested skipping of a file");
172 nexcp.remember(excp);
175 else if ( user == media::MediaChangeReport::EJECT )
177 DBG << "Eject: try to release" << endl;
178 media_mgr.releaseAll();
180 media_mgr.release (media,
181 devindex < devices.size() ? devices[devindex] : "");
183 else if ( user == media::MediaChangeReport::RETRY ||
184 user == media::MediaChangeReport::CHANGE_URL )
187 DBG << "Going to try again" << endl;
188 // invalidate current media access id
189 media_mgr.close(media);
190 _medias.erase(media_nr);
192 // not attaching, media set will do that for us
193 // this could generate uncaught exception (#158620)
198 DBG << "Don't know, let's ABORT" << endl;
199 ZYPP_RETHROW ( excp );
201 } while( user == media::MediaChangeReport::EJECT );
204 // retry or change URL
210 Pathname MediaSetAccess::provideFileInternal(const Pathname & file, unsigned media_nr, bool cached, bool checkonly )
212 callback::SendReport<media::MediaChangeReport> report;
213 media::MediaManager media_mgr;
215 media::MediaAccessId media;
219 // get the mediaId, but don't try to attach it here
220 media = getMediaAccessId( media_nr);
224 DBG << "Going to try to provide file " << file
225 << " from media number " << media_nr << endl;
226 // try to attach the media
227 if ( ! media_mgr.isAttached(media) )
228 media_mgr.attachDesiredMedia(media);
229 media_mgr.provideFile (media, file, false, false);
232 catch ( media::MediaException & excp )
235 media::MediaChangeReport::Action user = media::MediaChangeReport::ABORT;
236 unsigned int devindex = 0;
237 vector<string> devices;
238 media_mgr.getDetectedDevices(media, devices, devindex);
242 if (user != media::MediaChangeReport::EJECT) // no use in calling this again
244 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
247 media_mgr.release(media);
249 catch (const Exception & excpt_r)
251 ZYPP_CAUGHT(excpt_r);
252 MIL << "Failed to release media " << media << endl;
257 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
259 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
260 typeid(excp) == typeid( media::MediaNotAFileException ) )
262 reason = media::MediaChangeReport::NOT_FOUND;
264 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
265 typeid(excp) == typeid( media::MediaNotAttachedException) )
267 reason = media::MediaChangeReport::WRONG;
272 user = media::MediaChangeReport::ABORT;
275 // release all media before requesting another (#336881)
276 media_mgr.releaseAll();
278 user = report->requestMedia (
281 string(), //! \todo label
289 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
291 if( user == media::MediaChangeReport::ABORT )
293 DBG << "Aborting" << endl;
294 ZYPP_RETHROW ( excp );
296 else if ( user == media::MediaChangeReport::IGNORE )
298 DBG << "Skipping" << endl;
299 SkipRequestException nexcp("User-requested skipping of a file");
300 nexcp.remember(excp);
303 else if ( user == media::MediaChangeReport::EJECT )
305 DBG << "Eject: try to release" << endl;
306 media_mgr.releaseAll();
308 media_mgr.release (media,
309 devindex < devices.size() ? devices[devindex] : "");
311 else if ( user == media::MediaChangeReport::RETRY ||
312 user == media::MediaChangeReport::CHANGE_URL )
315 DBG << "Going to try again" << endl;
316 // invalidate current media access id
317 media_mgr.close(media);
318 _medias.erase(media_nr);
320 // not attaching, media set will do that for us
321 // this could generate uncaught exception (#158620)
326 DBG << "Don't know, let's ABORT" << endl;
327 ZYPP_RETHROW ( excp );
329 } while( user == media::MediaChangeReport::EJECT );
332 // retry or change URL
335 return media_mgr.localPath( media, file );
339 Pathname MediaSetAccess::provideDir(const Pathname & dir,
343 callback::SendReport<media::MediaChangeReport> report;
344 media::MediaManager media_mgr;
345 media::MediaAccessId _media;
349 // get the mediaId, but don't try to attach it here
350 _media = getMediaAccessId(media_nr);
354 DBG << "Going to try provide direcotry " << dir
355 << (recursive ? " (recursively)" : "")
356 << " from media nr. " << media_nr << endl;
358 // try to attach the media
359 if (!media_mgr.isAttached(_media))
360 media_mgr.attachDesiredMedia(_media);
362 _media = getMediaAccessId(media_nr); // in case of redirect
365 media_mgr.provideDirTree(_media, dir);
367 media_mgr.provideDir(_media, dir);
369 break; // quit the retry loop
371 catch (media::MediaException & excp)
374 media::MediaChangeReport::Action user;
378 DBG << "Media couldn't provide dir " << dir << ", releasing." << endl;
381 media_mgr.release (_media);
383 catch (const Exception & excpt_r)
385 ZYPP_CAUGHT(excpt_r);
386 ERR << "Failed to release media " << _media << endl;
389 //MIL << "Releasing all medias of all sources" << endl;
392 //! \todo do we need replacement for this at all?
393 //zypp::SourceManager::sourceManager()->releaseAllSources();
395 catch (const zypp::Exception& excpt_r)
397 ZYPP_CAUGHT(excpt_r);
398 ERR << "Failed to release all sources" << endl;
402 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
404 if (typeid(excp) == typeid(media::MediaFileNotFoundException)
405 || typeid(excp) == typeid(media::MediaNotAFileException))
407 reason = media::MediaChangeReport::NOT_FOUND;
409 else if (typeid(excp) == typeid( media::MediaNotDesiredException)
410 || typeid(excp) == typeid(media::MediaNotAttachedException))
412 reason = media::MediaChangeReport::WRONG;
415 vector<string> devices;
416 unsigned int devindex;
417 media_mgr.getDetectedDevices(_media, devices, devindex);
419 // release all media before requesting another (#336881)
420 media_mgr.releaseAll();
422 user = report->requestMedia(_url,
424 string(), //! \todo label
430 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
432 if (user == media::MediaChangeReport::ABORT)
434 DBG << "Aborting" << endl;
435 ZYPP_RETHROW ( excp );
437 else if (user == media::MediaChangeReport::EJECT)
439 DBG << "Eject: try to release" << endl;
440 media_mgr.releaseAll();
442 media_mgr.release (_media,
443 devindex < devices.size() ? devices[devindex] : "");
445 else if (user == media::MediaChangeReport::RETRY ||
446 user == media::MediaChangeReport::CHANGE_URL)
449 DBG << "Going to try again" << endl;
450 // invalidate current media access id
451 media_mgr.close(_media);
452 _medias.erase(media_nr);
454 // not attaching, media set will do that for us
455 // this could generate uncaught exception (#158620)
461 DBG << "Don't know, let's ABORT" << endl;
466 while (user == media::MediaChangeReport::EJECT);
468 // retry or change URL
472 return media_mgr.localPath(_media, dir);
475 media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
477 media::MediaManager media_mgr;
479 if (_medias.find(medianr) != _medias.end())
481 media::MediaAccessId id = _medias[medianr];
482 //if (! noattach && ! media_mgr.isAttached(id))
483 //media_mgr.attach(id);
487 url = rewriteUrl (_url, medianr);
488 media::MediaAccessId id = media_mgr.open(url, _prefAttachPoint);
489 _medias[medianr] = id;
493 if (_verifiers.find(medianr) != _verifiers.end())
495 // a verifier is set for this media
496 // FIXME check the case where the verifier exists
497 // but we have no access id for the media
498 media::MediaAccessId id = _medias[medianr];
499 media::MediaManager media_mgr;
500 media_mgr.delVerifier(id);
501 media_mgr.addVerifier( id, _verifiers[medianr] );
502 // remove any saved verifier for this media
503 _verifiers.erase(medianr);
506 catch ( const Exception &e )
509 WAR << "Verifier not found" << endl;
516 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
518 std::string scheme = url_r.getScheme();
519 if (scheme == "cd" || scheme == "dvd")
522 DBG << "Rewriting url " << url_r << endl;
526 // TODO the iso parameter will not be required in the future, this
527 // code has to be adapted together with the MediaISO change.
528 // maybe some MediaISOURL interface should be used.
529 std::string isofile = url_r.getQueryParam("iso");
530 str::regex e("^(.*)(cd|dvd)[0-9]+\\.iso$", str::regex::icase);
533 if(str::regex_match(isofile, what, e))
536 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
537 url.setQueryParam("iso", isofile);
538 DBG << "Url rewrite result: " << url << endl;
544 std::string pathname = url_r.getPathName();
545 str::regex e("^(.*)(cd|dvd)[0-9]+(/)?$", str::regex::icase);
547 if(str::regex_match(pathname, what, e))
550 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
551 url.setPathName(pathname);
552 DBG << "Url rewrite result: " << url << endl;
559 void MediaSetAccess::release()
561 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
562 media::MediaManager manager;
563 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
564 manager.release(m->second, "");
567 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
569 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
573 // media::MediaVerifierRef MediaSetAccess::verifier(unsigned media_nr)
574 // { return media::MediaVerifierRef(new media::NoVerifier()); }
576 /////////////////////////////////////////////////////////////////
578 ///////////////////////////////////////////////////////////////////