RepoProvideFile.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015 #include <set>
00016
00017 #include "zypp/base/Gettext.h"
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/base/String.h"
00020 #include "zypp/base/UserRequestException.h"
00021 #include "zypp/repo/RepoProvideFile.h"
00022 #include "zypp/ZYppCallbacks.h"
00023 #include "zypp/MediaSetAccess.h"
00024 #include "zypp/ZConfig.h"
00025 #include "zypp/repo/SUSEMediaVerifier.h"
00026 #include "zypp/repo/RepoException.h"
00027
00028 #include "zypp/repo/SUSEMediaVerifier.h"
00029 #include "zypp/repo/RepoException.h"
00030 #include "zypp/FileChecker.h"
00031 #include "zypp/Fetcher.h"
00032
00033 using std::endl;
00034 using std::set;
00035
00037 namespace zypp
00038 {
00039
00040 namespace repo
00041 {
00042
00044
00045
00046
00048
00050 namespace
00051 {
00052
00057 struct DownloadFileReportHack : public callback::ReceiveReport<repo::RepoReport>
00058 {
00059 virtual bool progress( const ProgressData &progress )
00060 {
00061 if ( _redirect )
00062 return _redirect( progress.val() );
00063 return true;
00064 }
00065 function<bool ( int )> _redirect;
00066 };
00067
00069 }
00071
00072 ManagedFile provideFile( RepoInfo repo_r,
00073 const OnMediaLocation & loc_r,
00074 const ProvideFilePolicy & policy_r )
00075 {
00076 RepoMediaAccess access;
00077 return access.provideFile(repo_r, loc_r, policy_r );
00078 }
00079
00081 class RepoMediaAccess::Impl
00082 {
00083 public:
00084 Impl( const ProvideFilePolicy & defaultPolicy_r )
00085 : _defaultPolicy( defaultPolicy_r )
00086 {}
00087
00088 ~Impl()
00089 {
00090 std::map<Url, shared_ptr<MediaSetAccess> >::iterator it;
00091 for ( it = _medias.begin();
00092 it != _medias.end();
00093 ++it )
00094 {
00095 it->second->release();
00096 }
00097 }
00098
00106 shared_ptr<MediaSetAccess> mediaAccessForUrl( const Url &url, RepoInfo repo )
00107 {
00108 std::map<Url, shared_ptr<MediaSetAccess> >::const_iterator it;
00109 it = _medias.find(url);
00110 shared_ptr<MediaSetAccess> media;
00111 if ( it != _medias.end() )
00112 {
00113 media = it->second;
00114 }
00115 else
00116 {
00117 media.reset( new MediaSetAccess(url) );
00118 _medias[url] = media;
00119 }
00120 setVerifierForRepo( repo, media );
00121 return media;
00122 }
00123
00124 private:
00125 void setVerifierForRepo( RepoInfo repo, shared_ptr<MediaSetAccess> media )
00126 {
00127
00128 media->setLabel( repo.name() );
00129
00130
00131
00132 Pathname mediafile = repo.metadataPath() + "/media.1/media";
00133 if ( ! repo.metadataPath().empty() )
00134 {
00135 if ( PathInfo(mediafile).isExist() )
00136 {
00137 std::map<shared_ptr<MediaSetAccess>, RepoInfo>::const_iterator it;
00138 it = _verifier.find(media);
00139 if ( it != _verifier.end() )
00140 {
00141 if ( it->second.alias() == repo.alias() )
00142 {
00143
00144 return;
00145 }
00146 }
00147
00148 std::ifstream str(mediafile.asString().c_str());
00149 std::string vendor;
00150 std::string mediaid;
00151 std::string buffer;
00152 if ( str )
00153 {
00154 getline(str, vendor);
00155 getline(str, mediaid);
00156 getline(str, buffer);
00157
00158 unsigned media_nr = str::strtonum<unsigned>(buffer);
00159 MIL << "Repository '" << repo.alias() << "' has " << media_nr << " medias"<< endl;
00160
00161 for ( unsigned i=1; i <= media_nr; ++i )
00162 {
00163 media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( vendor, mediaid, i ) );
00164
00165 media->setVerifier( i, verifier);
00166 }
00167 _verifier[media] = repo;
00168 }
00169 else
00170 {
00171 ZYPP_THROW(RepoMetadataException(repo));
00172 }
00173 }
00174 else
00175 {
00176 WAR << "No media verifier for repo '" << repo.alias() << "' media/media.1 does not exist in '" << repo.metadataPath() << "'" << endl;
00177 }
00178 }
00179 else
00180 {
00181 WAR << "'" << repo.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl;
00182 }
00183 }
00184
00185 private:
00186 std::map<shared_ptr<MediaSetAccess>, RepoInfo> _verifier;
00187 std::map<Url, shared_ptr<MediaSetAccess> > _medias;
00188
00189 public:
00190 ProvideFilePolicy _defaultPolicy;
00191 };
00193
00194
00195 RepoMediaAccess::RepoMediaAccess( const ProvideFilePolicy & defaultPolicy_r )
00196 : _impl( new Impl( defaultPolicy_r ) )
00197 {}
00198
00199 RepoMediaAccess::~RepoMediaAccess()
00200 {}
00201
00202 void RepoMediaAccess::setDefaultPolicy( const ProvideFilePolicy & policy_r )
00203 { _impl->_defaultPolicy = policy_r; }
00204
00205 const ProvideFilePolicy & RepoMediaAccess::defaultPolicy() const
00206 { return _impl->_defaultPolicy; }
00207
00208 ManagedFile RepoMediaAccess::provideFile( RepoInfo repo_r,
00209 const OnMediaLocation & loc_r,
00210 const ProvideFilePolicy & policy_r )
00211 {
00212 MIL << loc_r << endl;
00213
00214
00215
00216 DownloadFileReportHack dumb;
00217 dumb._redirect = bind( mem_fun_ref( &ProvideFilePolicy::progress ),
00218 ref( policy_r ), _1 );
00219 callback::TempConnect<repo::RepoReport> temp( dumb );
00220
00221 RepoException repo_excpt(repo_r,
00222 str::form(_("Can't provide file '%s' from repository '%s'"),
00223 loc_r.filename().c_str(),
00224 repo_r.alias().c_str() ) );
00225
00226 if ( repo_r.baseUrlsEmpty() )
00227 {
00228 repo_excpt.remember(RepoException(_("No url in repository.")));
00229 ZYPP_THROW(repo_excpt);
00230 }
00231
00232 Fetcher fetcher;
00233 fetcher.addCachePath( repo_r.packagesPath() );
00234
00235 MIL << "Added cache path " << repo_r.packagesPath() << endl;
00236
00237 for ( RepoInfo::urls_const_iterator it = repo_r.baseUrlsBegin();
00238 it != repo_r.baseUrlsEnd();
00239 )
00240 {
00241 Url url( *it );
00242 ++it;
00243 try
00244 {
00245 MIL << "Providing file of repo '" << repo_r.alias()
00246 << "' from " << url << endl;
00247 shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl( url, repo_r );
00248
00249 fetcher.enqueue( loc_r );
00250
00251
00252 fetcher.start( repo_r.packagesPath(), *access );
00253
00254
00255 ManagedFile ret( repo_r.packagesPath() + loc_r.filename() );
00256
00257 std::string scheme( url.getScheme() );
00258 if ( !repo_r.keepPackages() )
00259 {
00260 ret.setDispose( filesystem::unlink );
00261 }
00262
00263 if ( loc_r.checksum().empty() )
00264 {
00265
00266 WAR << "No checksum in metadata " << loc_r << endl;
00267 }
00268 else
00269 {
00270 std::ifstream input( ret->asString().c_str() );
00271 CheckSum retChecksum( loc_r.checksum().type(), input );
00272 input.close();
00273
00274 if ( loc_r.checksum() != retChecksum )
00275 {
00276
00277 std::ostringstream err;
00278 err << "File " << ret << " fails integrity check. Expected: [" << loc_r.checksum() << "] Got: [";
00279 if ( retChecksum.empty() )
00280 err << "Failed to compute checksum";
00281 else
00282 err << retChecksum;
00283 err << "]";
00284
00285 WAR << err.str() << endl;
00286
00287 if ( policy_r.failOnChecksumError() )
00288 ZYPP_THROW( FileCheckException( err.str() ) );
00289 else
00290 WAR << "NO failOnChecksumError: " << err.str() << endl;
00291 }
00292 }
00293
00294 MIL << "provideFile at " << ret << endl;
00295 return ret;
00296 }
00297 catch ( const SkipRequestException &e )
00298 {
00299 ZYPP_CAUGHT( e );
00300 ZYPP_RETHROW(e);
00301 }
00302 catch ( const AbortRequestException &e )
00303 {
00304 ZYPP_CAUGHT( e );
00305 ZYPP_RETHROW(e);
00306 }
00307 catch ( const Exception &e )
00308 {
00309 ZYPP_CAUGHT( e );
00310
00311 repo_excpt.remember(e);
00312
00313 WAR << "Trying next url" << endl;
00314 continue;
00315 }
00316 }
00317
00318 ZYPP_THROW(repo_excpt);
00319 return ManagedFile();
00320 }
00321
00323 }
00326 }