1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
13 #include "zypp/base/LogTools.h"
14 #include "zypp/ZYppCallbacks.h"
15 #include "zypp/MediaSetAccess.h"
16 #include "zypp/PathInfo.h"
17 //#include "zypp/source/MediaSetAccessReportReceivers.h"
21 ///////////////////////////////////////////////////////////////////
23 { /////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////
26 ChecksumFileChecker::ChecksumFileChecker( const CheckSum &checksum )
31 bool ChecksumFileChecker::operator()( const Pathname &file )
33 // FIXME probably this funcionality should be in CheckSum itself
34 CheckSum real_checksum( _checksum.type(), filesystem::checksum( file, _checksum.type() ));
35 if ( real_checksum == _checksum )
41 ERR << "Got " << real_checksum << ", expected " << _checksum << std::endl;
46 bool NullFileChecker::operator()(const Pathname &file )
51 MediaSetAccess::MediaSetAccess( const Url &url, const Pathname &path )
55 MIL << "initializing.." << std::endl;
56 //std::vector<media::MediaVerifierRef> single_media;
57 //single_media[0] = media::MediaVerifierRef(new media::NoVerifier());
58 //_verifiers = single_media;
61 MediaSetAccess::~MediaSetAccess()
65 void MediaSetAccess::setVerifiers( const std::vector<media::MediaVerifierRef> &verifiers )
67 _verifiers = verifiers;
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 void MediaSetAccess::providePossiblyCachedMetadataFile( const Pathname &file_to_download, unsigned medianr, const Pathname &destination, const Pathname &cached_file, const CheckSum &checksum )
83 Url file_url( _url.asString() + file_to_download.asString() );
84 // if we have a cached file and its the same
85 if ( PathInfo(cached_file).isExist() && (! checksum.empty()) && is_checksum( cached_file, checksum ) )
87 MIL << "file " << file_url << " found in previous cache. Using cached copy." << std::endl;
88 // checksum is already checked.
89 // we could later implement double failover and try to download if file copy fails.
90 if ( filesystem::copy(cached_file, destination) != 0 )
91 ZYPP_THROW(Exception("Can't copy " + cached_file.asString() + " to " + destination.asString()));
95 // we dont have it or its not the same, download it.
96 Pathname downloaded_file = provideFile( file_to_download, medianr, ChecksumFileChecker(checksum) );
98 if ( filesystem::copy(downloaded_file, destination) != 0 )
99 ZYPP_THROW(Exception("Can't copy " + downloaded_file.asString() + " to " + destination.asString()));
103 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr )
105 return provideFileInternal( file, media_nr, false, false);
108 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, FileChecker checker )
110 Pathname p = provideFileInternal( file, media_nr, false, false);
114 ZYPP_THROW(Exception("Error checker"));
119 Pathname MediaSetAccess::provideFileInternal(const Pathname & file, unsigned media_nr, bool cached, bool checkonly )
121 callback::SendReport<media::MediaChangeReport> report;
122 media::MediaManager media_mgr;
123 // get the mediaId, but don't try to attach it here
124 media::MediaAccessId media = getMediaAccessId( media_nr);
130 DBG << "Going to try provide file " << file << " from " << media_nr << endl;
131 // try to attach the media
132 if ( ! media_mgr.isAttached(media) )
133 media_mgr.attach(media);
134 media_mgr.provideFile (media, file, false, false);
137 catch ( Exception & excp )
140 media::MediaChangeReport::Action user;
143 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
146 media_mgr.release (media, false);
148 catch (const Exception & excpt_r)
150 ZYPP_CAUGHT(excpt_r);
151 MIL << "Failed to release media " << media << endl;
154 MIL << "Releasing all medias of all sources" << endl;
157 //zypp::SourceManager::sourceManager()->releaseAllSources();
159 catch (const zypp::Exception& excpt_r)
161 ZYPP_CAUGHT(excpt_r);
162 ERR << "Failed to release all sources" << endl;
166 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
168 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
169 typeid(excp) == typeid( media::MediaNotAFileException ) )
171 reason = media::MediaChangeReport::NOT_FOUND;
173 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
174 typeid(excp) == typeid( media::MediaNotAttachedException) )
176 reason = media::MediaChangeReport::WRONG;
179 user = checkonly ? media::MediaChangeReport::ABORT :
180 report->requestMedia (
181 Source_Ref::noSource,
187 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
189 if( user == media::MediaChangeReport::ABORT )
191 DBG << "Aborting" << endl;
192 ZYPP_RETHROW ( excp );
194 else if ( user == media::MediaChangeReport::IGNORE )
196 DBG << "Skipping" << endl;
197 ZYPP_THROW ( source::SkipRequestedException("User-requested skipping of a file") );
199 else if ( user == media::MediaChangeReport::EJECT )
201 DBG << "Eject: try to release" << endl;
204 //zypp::SourceManager::sourceManager()->releaseAllSources();
206 catch (const zypp::Exception& excpt_r)
208 ZYPP_CAUGHT(excpt_r);
209 ERR << "Failed to release all sources" << endl;
211 media_mgr.release (media, true); // one more release needed for eject
212 // FIXME: this will not work, probably
214 else if ( user == media::MediaChangeReport::RETRY ||
215 user == media::MediaChangeReport::CHANGE_URL )
218 DBG << "Going to try again" << endl;
220 // not attaching, media set will do that for us
221 // this could generate uncaught exception (#158620)
226 DBG << "Don't know, let's ABORT" << endl;
227 ZYPP_RETHROW ( excp );
229 } while( user == media::MediaChangeReport::EJECT );
232 // retry or change URL
235 return media_mgr.localPath( media, file );
238 media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
240 media::MediaManager media_mgr;
242 if (medias.find(medianr) != medias.end())
244 media::MediaAccessId id = medias[medianr];
245 //if (! noattach && ! media_mgr.isAttached(id))
246 //media_mgr.attach(id);
250 url = rewriteUrl (_url, medianr);
251 media::MediaAccessId id = media_mgr.open(url, _path);
253 // MIL << "Adding media verifier" << endl;
254 // media_mgr.delVerifier(id);
255 // media_mgr.addVerifier(id, _source.verifier(medianr));
257 //catch (const Exception & excpt_r)
259 // ZYPP_CAUGHT(excpt_r);
260 // WAR << "Verifier not found" << endl;
262 medias[medianr] = id;
265 // media_mgr.attach(id);
270 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
272 std::string scheme = url_r.getScheme();
273 if (scheme == "cd" || scheme == "dvd")
276 DBG << "Rewriting url " << url_r << endl;
280 std::string isofile = url_r.getQueryParam("iso");
281 boost::regex e("^(.*(cd|dvd))([0-9]+)(\\.iso)$", boost::regex::icase);
283 if(boost::regex_match(isofile, what, e, boost::match_extra))
286 isofile = what[1] + str::numstring(medianr) + what[4];
287 url.setQueryParam("iso", isofile);
288 DBG << "Url rewrite result: " << url << endl;
294 std::string pathname = url_r.getPathName();
295 boost::regex e("^(.*(cd|dvd))([0-9]+)(/?)$", boost::regex::icase);
297 if(boost::regex_match(pathname, what, e, boost::match_extra))
300 pathname = what[1] + str::numstring(medianr) + what[4];
301 url.setPathName(pathname);
302 DBG << "Url rewrite result: " << url << endl;
309 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
314 // media::MediaVerifierRef MediaSetAccess::verifier(unsigned media_nr)
315 // { return media::MediaVerifierRef(new media::NoVerifier()); }
317 MediaVerifier::MediaVerifier(const std::string & vendor_r, const std::string & id_r, const media::MediaNr media_nr)
318 : _media_vendor(vendor_r)
320 , _media_nr(media_nr)
323 bool MediaVerifier::isDesiredMedia(const media::MediaAccessRef &ref)
325 if (_media_vendor.empty() || _media_id.empty())
328 Pathname media_file = "/media." + str::numstring(_media_nr) + "/media";
329 ref->provideFile (media_file);
330 media_file = ref->localPath(media_file);
331 std::ifstream str(media_file.asString().c_str());
335 #warning check the stream status
336 getline(str, vendor);
339 return (vendor == _media_vendor && id == _media_id );
343 /////////////////////////////////////////////////////////////////
344 } // namespace source
345 ///////////////////////////////////////////////////////////////////