1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/source/RepoProvideFile.cc
17 #include "zypp/base/Gettext.h"
18 #include "zypp/base/Logger.h"
19 #include "zypp/base/String.h"
20 #include "zypp/base/UserRequestException.h"
21 #include "zypp/repo/RepoProvideFile.h"
22 #include "zypp/ZYppCallbacks.h"
23 #include "zypp/MediaSetAccess.h"
24 #include "zypp/ZConfig.h"
25 #include "zypp/repo/SUSEMediaVerifier.h"
26 #include "zypp/repo/RepoException.h"
28 #include "zypp/repo/SUSEMediaVerifier.h"
29 #include "zypp/repo/RepoException.h"
30 #include "zypp/FileChecker.h"
31 #include "zypp/Fetcher.h"
36 ///////////////////////////////////////////////////////////////////
38 { /////////////////////////////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////
41 { /////////////////////////////////////////////////////////////////
43 ///////////////////////////////////////////////////////////////////
47 ///////////////////////////////////////////////////////////////////
49 ///////////////////////////////////////////////////////////////////
51 { /////////////////////////////////////////////////////////////////
53 /** Hack to extract progress information from source::DownloadFileReport.
54 * We redirect the static report triggered from Repository::provideFile
55 * to feed the ProvideFilePolicy callbacks.
57 struct DownloadFileReportHack : public callback::ReceiveReport<repo::RepoReport>
59 virtual bool progress( const ProgressData &progress )
62 return _redirect( progress.val() );
65 function<bool ( int )> _redirect;
68 /////////////////////////////////////////////////////////////////
70 ///////////////////////////////////////////////////////////////////
72 ManagedFile provideFile( Repository repo_r,
73 const OnMediaLocation & loc_r,
74 const ProvideFilePolicy & policy_r )
76 RepoMediaAccess access;
77 return access.provideFile(repo_r, loc_r, policy_r );
80 class RepoMediaAccess::Impl
83 Impl( const ProvideFilePolicy & defaultPolicy_r )
84 : _defaultPolicy( defaultPolicy_r )
89 std::map<Url, shared_ptr<MediaSetAccess> >::iterator it;
90 for ( it = _medias.begin();
94 it->second->release();
98 shared_ptr<MediaSetAccess> mediaAccessForUrl( const Url &url )
100 std::map<Url, shared_ptr<MediaSetAccess> >::const_iterator it;
101 it = _medias.find(url);
102 shared_ptr<MediaSetAccess> media;
103 if ( it != _medias.end() )
109 media.reset( new MediaSetAccess(url) );
110 _medias[url] = media;
115 void setVerifierForRepo( Repository repo, shared_ptr<MediaSetAccess> media )
117 RepoInfo info = repo.info();
118 // set a verifier if the repository has it
120 Pathname mediafile = info.metadataPath() + "/media.1/media";
121 if ( ! info.metadataPath().empty() )
123 if ( PathInfo(mediafile).isExist() )
125 std::map<shared_ptr<MediaSetAccess>, Repository>::const_iterator it;
126 it = _verifier.find(media);
127 if ( it != _verifier.end() )
129 if ( it->second == repo )
131 // this media is already using this repo verifier
136 std::ifstream str(mediafile.asString().c_str());
142 getline(str, vendor);
143 getline(str, mediaid);
144 getline(str, buffer);
146 unsigned media_nr = str::strtonum<unsigned>(buffer);
147 MIL << "Repository '" << info.alias() << "' has " << media_nr << " medias"<< endl;
149 for ( unsigned i=1; i <= media_nr; ++i )
151 media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( vendor, mediaid, i ) );
153 media->setVerifier( i, verifier);
155 _verifier[media] = repo;
159 ZYPP_THROW(RepoMetadataException(info));
164 WAR << "No media verifier for repo '" << info.alias() << "' media/media.1 does not exist in '" << info.metadataPath() << "'" << endl;
169 WAR << "'" << info.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl;
173 std::map<shared_ptr<MediaSetAccess>, Repository> _verifier;
174 std::map<Url, shared_ptr<MediaSetAccess> > _medias;
175 ProvideFilePolicy _defaultPolicy;
180 RepoMediaAccess::RepoMediaAccess( const ProvideFilePolicy & defaultPolicy_r )
181 : _impl( new Impl( defaultPolicy_r ) )
184 RepoMediaAccess::~RepoMediaAccess()
187 void RepoMediaAccess::setDefaultPolicy( const ProvideFilePolicy & policy_r )
188 { _impl->_defaultPolicy = policy_r; }
190 const ProvideFilePolicy & RepoMediaAccess::defaultPolicy() const
191 { return _impl->_defaultPolicy; }
193 ManagedFile RepoMediaAccess::provideFile( Repository repo_r,
194 const OnMediaLocation & loc_r,
195 const ProvideFilePolicy & policy_r )
197 MIL << loc_r << endl;
198 // Arrange DownloadFileReportHack to recieve the source::DownloadFileReport
199 // and redirect download progress triggers to call the ProvideFilePolicy
201 DownloadFileReportHack dumb;
202 dumb._redirect = bind( mem_fun_ref( &ProvideFilePolicy::progress ),
203 ref( policy_r ), _1 );
204 callback::TempConnect<repo::RepoReport> temp( dumb );
207 RepoInfo info = repo_r.info();
209 RepoException repo_excpt(str::form(_("Can't provide file '%s' from repository '%s'"),
210 loc_r.filename().c_str(),
211 info.alias().c_str() ) );
213 if ( info.baseUrlsEmpty() )
215 repo_excpt.remember(RepoException(_("No url in repository.")));
216 ZYPP_THROW(repo_excpt);
220 fetcher.addCachePath( info.packagesPath() );
222 MIL << "Added cache path " << info.packagesPath() << endl;
224 for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin();
225 it != info.baseUrlsEnd();
226 /* incremented in the loop */ )
232 MIL << "Providing file of repo '" << info.alias()
233 << "' from " << url << endl;
234 shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl(url);
235 _impl->setVerifierForRepo(repo_r, access);
237 fetcher.enqueue( loc_r );
239 // FIXME: works for packages only
240 fetcher.start( info.packagesPath(), *access );
242 // reached if no exception has been thrown, so this is the correct file
243 ManagedFile ret( info.packagesPath() + loc_r.filename() );
245 std::string scheme( url.getScheme() );
246 if ( !info.keepPackages() )
248 ret.setDispose( filesystem::unlink );
251 if ( loc_r.checksum().empty() )
253 // no checksum in metadata
254 WAR << "No checksum in metadata " << loc_r << endl;
258 std::ifstream input( ret->asString().c_str() );
259 CheckSum retChecksum( loc_r.checksum().type(), input );
262 if ( loc_r.checksum() != retChecksum )
264 // failed integity check
265 std::ostringstream err;
266 err << "File " << ret << " fails integrity check. Expected: [" << loc_r.checksum() << "] Got: [";
267 if ( retChecksum.empty() )
268 err << "Failed to compute checksum";
273 if ( policy_r.failOnChecksumError() )
274 ZYPP_THROW( FileCheckException( err.str() ) );
276 WAR << "NO failOnChecksumError: " << err.str() << endl;
280 MIL << "provideFile at " << ret << endl;
283 catch ( const SkipRequestException &e )
288 catch ( const AbortRequestException &e )
293 catch ( const Exception &e )
297 repo_excpt.remember(e);
299 WAR << "Trying next url" << endl;
302 } // iteration over urls
304 ZYPP_THROW(repo_excpt);
305 return ManagedFile(); // not reached
308 /////////////////////////////////////////////////////////////////
310 ///////////////////////////////////////////////////////////////////
311 /////////////////////////////////////////////////////////////////
313 ///////////////////////////////////////////////////////////////////