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"
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////
39 { /////////////////////////////////////////////////////////////////
41 ///////////////////////////////////////////////////////////////////
45 ///////////////////////////////////////////////////////////////////
47 ///////////////////////////////////////////////////////////////////
49 { /////////////////////////////////////////////////////////////////
51 /** Hack to extract progress information from source::DownloadFileReport.
52 * We redirect the static report triggered from Repository::provideFile
53 * to feed the ProvideFilePolicy callbacks.
55 struct DownloadFileReportHack : public callback::ReceiveReport<repo::RepoReport>
57 virtual bool progress( const ProgressData &progress )
60 return _redirect( progress.val() );
63 function<bool ( int )> _redirect;
66 /////////////////////////////////////////////////////////////////
68 ///////////////////////////////////////////////////////////////////
70 ManagedFile provideFile( Repository repo_r,
71 const OnMediaLocation & loc_r,
72 const ProvideFilePolicy & policy_r )
74 RepoMediaAccess access;
75 return access.provideFile(repo_r, loc_r, policy_r );
78 class RepoMediaAccess::Impl
81 Impl( const ProvideFilePolicy & defaultPolicy_r )
82 : _defaultPolicy( defaultPolicy_r )
87 std::map<Url, shared_ptr<MediaSetAccess> >::iterator it;
88 for ( it = _medias.begin();
92 it->second->release();
96 shared_ptr<MediaSetAccess> mediaAccessForUrl( const Url &url )
98 std::map<Url, shared_ptr<MediaSetAccess> >::const_iterator it;
99 it = _medias.find(url);
100 shared_ptr<MediaSetAccess> media;
101 if ( it != _medias.end() )
107 media.reset( new MediaSetAccess(url) );
108 _medias[url] = media;
113 void setVerifierForRepo( Repository repo, shared_ptr<MediaSetAccess> media )
115 RepoInfo info = repo.info();
116 // set a verifier if the repository has it
117 Pathname mediafile = info.metadataPath() + "/media.1/media";
118 if ( ! mediafile.empty() )
120 if ( PathInfo(mediafile).isExist() )
122 std::map<shared_ptr<MediaSetAccess>, Repository>::const_iterator it;
123 it = _verifier.find(media);
124 if ( it != _verifier.end() )
126 if ( it->second == repo )
128 // this media is already using this repo verifier
133 std::ifstream str(mediafile.asString().c_str());
139 getline(str, vendor);
140 getline(str, mediaid);
141 getline(str, buffer);
143 unsigned media_nr = str::strtonum<unsigned>(buffer);
144 MIL << "Repository '" << info.alias() << "' has " << media_nr << " medias"<< endl;
146 for ( unsigned i=1; i <= media_nr; ++i )
148 media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( vendor, mediaid, i ) );
150 media->setVerifier( i, verifier);
152 _verifier[media] = repo;
156 ZYPP_THROW(RepoMetadataException(info));
161 WAR << "No media verifier for repo '" << info.alias() << "'" << endl;
166 MIL << "Unknown metadata path for repo '" << info.alias() << "'. Can't set media verifier."<< endl;
170 std::map<shared_ptr<MediaSetAccess>, Repository> _verifier;
171 std::map<Url, shared_ptr<MediaSetAccess> > _medias;
172 ProvideFilePolicy _defaultPolicy;
177 RepoMediaAccess::RepoMediaAccess( const ProvideFilePolicy & defaultPolicy_r )
178 : _impl( new Impl( defaultPolicy_r ) )
181 RepoMediaAccess::~RepoMediaAccess()
184 void RepoMediaAccess::setDefaultPolicy( const ProvideFilePolicy & policy_r )
185 { _impl->_defaultPolicy = policy_r; }
187 const ProvideFilePolicy & RepoMediaAccess::defaultPolicy() const
188 { return _impl->_defaultPolicy; }
190 ManagedFile RepoMediaAccess::provideFile( Repository repo_r,
191 const OnMediaLocation & loc_r,
192 const ProvideFilePolicy & policy_r )
194 MIL << loc_r << endl;
195 // Arrange DownloadFileReportHack to recieve the source::DownloadFileReport
196 // and redirect download progress triggers to call the ProvideFilePolicy
198 DownloadFileReportHack dumb;
199 dumb._redirect = bind( mem_fun_ref( &ProvideFilePolicy::progress ),
200 ref( policy_r ), _1 );
201 callback::TempConnect<repo::RepoReport> temp( dumb );
204 RepoInfo info = repo_r.info();
206 RepoException repo_excpt(str::form(_("Can't provide file %s from repository %s"),
207 loc_r.filename().c_str(),
208 info.alias().c_str() ) );
210 if ( info.baseUrlsEmpty() )
212 repo_excpt.remember(RepoException(_("No url in repository.")));
213 ZYPP_THROW(repo_excpt);
216 for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin();
217 it != info.baseUrlsEnd();
218 /* incremented in the loop */ )
224 MIL << "Providing file of repo '" << info.alias()
225 << "' from " << url << endl;
226 shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl(url);
227 _impl->setVerifierForRepo(repo_r, access);
229 ManagedFile ret( access->provideFile(loc_r) );
231 std::string scheme( url.getScheme() );
232 if ( scheme == "http" || scheme == "https" || scheme == "ftp" )
234 ret.setDispose( filesystem::unlink );
237 if ( loc_r.checksum().empty() )
239 // no checksum in metadata
240 WAR << "No checksum in metadata " << loc_r << endl;
244 std::ifstream input( ret->asString().c_str() );
245 CheckSum retChecksum( loc_r.checksum().type(), input );
248 if ( loc_r.checksum() != retChecksum )
250 // failed integity check
251 std::ostringstream err;
252 err << "File " << ret << " fails integrity check. Expected: [" << loc_r.checksum() << "] Got: [";
253 if ( retChecksum.empty() )
254 err << "Failed to compute checksum";
259 if ( policy_r.failOnChecksumError() )
260 ZYPP_THROW( Exception( err.str() ) );
262 WAR << "NO failOnChecksumError: " << err.str() << endl;
266 MIL << "provideFile at " << ret << endl;
269 catch ( const SkipRequestException &e )
274 catch ( const AbortRequestException &e )
279 catch ( const Exception &e )
283 repo_excpt.remember(e);
285 WAR << "Trying next url" << endl;
288 } // iteration over urls
290 ZYPP_THROW(repo_excpt);
291 return ManagedFile(); // not reached
294 /////////////////////////////////////////////////////////////////
296 ///////////////////////////////////////////////////////////////////
297 /////////////////////////////////////////////////////////////////
299 ///////////////////////////////////////////////////////////////////