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 << "provideFile " << 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();
205 if ( info.baseUrlsEmpty() )
206 ZYPP_THROW(Exception(_("No url in repository.")));
208 for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin();
209 it != info.baseUrlsEnd();
215 MIL << "Providing file of repo '" << info.alias()
216 << "' from " << url << endl;
217 shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl(url);
218 _impl->setVerifierForRepo(repo_r, access);
220 ManagedFile ret( access->provideFile(loc_r) );
222 std::string scheme( url.getScheme() );
223 if ( scheme == "http" || scheme == "https" || scheme == "ftp" )
225 ret.setDispose( filesystem::unlink );
228 if ( loc_r.checksum().empty() )
230 // no checksum in metadata
231 WAR << "No checksum in metadata " << loc_r << endl;
235 std::ifstream input( ret->asString().c_str() );
236 CheckSum retChecksum( loc_r.checksum().type(), input );
239 if ( loc_r.checksum() != retChecksum )
241 // failed integity check
242 std::ostringstream err;
243 err << "File " << ret << " fails integrity check. Expected: [" << loc_r.checksum() << "] Got: [";
244 if ( retChecksum.empty() )
245 err << "Failed to compute checksum";
250 if ( policy_r.failOnChecksumError() )
251 ZYPP_THROW( Exception( err.str() ) );
253 WAR << "NO failOnChecksumError: " << err.str() << endl;
257 MIL << "provideFile at " << ret << endl;
260 catch ( const SkipRequestException &e )
265 catch ( const AbortRequestException &e )
270 catch ( const Exception &e )
273 WAR << "Trying next url" << endl;
276 } // iteration over urls
278 ZYPP_THROW(Exception(str::form(_("Can't provide file %s from repository %s"),
279 loc_r.filename().c_str(),
280 info.alias().c_str() ) ) );
282 return ManagedFile(); // not reached
285 /////////////////////////////////////////////////////////////////
287 ///////////////////////////////////////////////////////////////////
288 /////////////////////////////////////////////////////////////////
290 ///////////////////////////////////////////////////////////////////