Downloader.cc
Go to the documentation of this file.00001
00002 #include <iostream>
00003 #include <fstream>
00004
00005 #include "zypp/base/Logger.h"
00006 #include "zypp/base/String.h"
00007 #include "zypp/OnMediaLocation.h"
00008 #include "zypp/MediaSetAccess.h"
00009 #include "zypp/Fetcher.h"
00010 #include "zypp/Locale.h"
00011 #include "zypp/ZConfig.h"
00012 #include "zypp/repo/MediaInfoDownloader.h"
00013 #include "zypp/repo/susetags/Downloader.h"
00014 #include "zypp/parser/ParseException.h"
00015 #include "zypp/parser/susetags/RepoIndex.h"
00016 #include "zypp/base/UserRequestException.h"
00017 #include "zypp/KeyContext.h"
00018
00019 using namespace std;
00020 using namespace zypp::parser;
00021 using namespace zypp::parser::susetags;
00022
00023 namespace zypp
00024 {
00025 namespace repo
00026 {
00027 namespace susetags
00028 {
00029
00030 Downloader::Downloader( const RepoInfo &repoinfo, const Pathname &delta_dir )
00031 : repo::Downloader(repoinfo), _delta_dir(delta_dir)
00032 {
00033 }
00034
00035 RepoStatus Downloader::status( MediaSetAccess &media )
00036 {
00037 Pathname content = media.provideFile( repoInfo().path() + "/content");
00038
00039
00040 Pathname mediafile = media.provideFile( "/media.1/media" );
00041
00042 return RepoStatus(content) && RepoStatus(mediafile);
00043 }
00044
00045
00046 static Pathname search_deltafile( const Pathname &dir, const Pathname &file )
00047 {
00048 Pathname deltafile(dir + file.basename());
00049 if (PathInfo(deltafile).isExist())
00050 return deltafile;
00051 return Pathname();
00052 }
00053
00054 void Downloader::download( MediaSetAccess &media,
00055 const Pathname &dest_dir,
00056 const ProgressData::ReceiverFnc & progress )
00057 {
00058 downloadMediaInfo( dest_dir, media );
00059
00060 SignatureFileChecker sigchecker;
00061
00062 Pathname sig = repoInfo().path() + "/content.asc";
00063
00064 this->enqueue( OnMediaLocation( sig, 1 ).setOptional(true) );
00065 this->start( dest_dir, media );
00066
00067 if ( PathInfo(dest_dir / sig ).isExist() )
00068 sigchecker = SignatureFileChecker( dest_dir + sig);
00069 this->reset();
00070
00071 Pathname key = repoInfo().path() + "/content.key";
00072
00073 this->enqueue( OnMediaLocation( key, 1 ).setOptional(true) );
00074 this->start( dest_dir, media );
00075
00076 KeyContext context;
00077 context.setRepoInfo(repoInfo());
00078
00079 if ( PathInfo(dest_dir / key).isExist() )
00080 sigchecker.addPublicKey(dest_dir + key, context);
00081
00082
00083 else
00084 sigchecker.setKeyContext(context);
00085
00086 this->reset();
00087
00088 if ( ! repoInfo().gpgCheck() )
00089 {
00090 WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
00091 }
00092 this->enqueue( OnMediaLocation( repoInfo().path() + "/content", 1 ),
00093 repoInfo().gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) );
00094 this->start( dest_dir, media );
00095 this->reset();
00096
00097 Pathname descr_dir;
00098
00099
00100 {
00101 Pathname inputfile( dest_dir + repoInfo().path() + "/content" );
00102 ContentFileReader content;
00103 content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
00104 content.parse( inputfile );
00105 }
00106 if ( ! _repoindex )
00107 {
00108 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No repository index in content file." ) );
00109 }
00110 MIL << "RepoIndex: " << _repoindex << endl;
00111 if ( _repoindex->metaFileChecksums.empty() )
00112 {
00113 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No metadata checksums in content file." ) );
00114 }
00115 if ( _repoindex->signingKeys.empty() )
00116 {
00117 WAR << "No signing keys defined." << endl;
00118 }
00119
00120
00121 descr_dir = _repoindex->descrdir;
00122
00123
00124
00125 for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() )
00126 {
00127
00128 if ( str::hasPrefix( it->first, "packages" ) )
00129 {
00130 std::string rest( str::stripPrefix( it->first, "packages" ) );
00131 if ( ! ( rest.empty()
00132 || rest == ".DU"
00133 || rest == ".en"
00134 || rest == ".gz"
00135 || rest == ".DU.gz"
00136 || rest == ".en.gz" ) )
00137 {
00138
00139 Locale toParse( ZConfig::instance().textLocale() );
00140 while ( toParse != Locale::noCode )
00141 {
00142 if ( rest == ("."+toParse.code()) || (rest == ("."+toParse.code()+".gz")) )
00143 break;
00144 toParse = toParse.fallback();
00145 }
00146 if ( toParse == Locale::noCode )
00147 {
00148
00149 continue;
00150 }
00151 }
00152 }
00153 else if ( it->first == "patterns.pat"
00154 || it->first == "patterns.pat.gz" )
00155 {
00156
00157 }
00158 else if ( str::endsWith( it->first, ".pat" )
00159 || str::endsWith( it->first, ".pat.gz" ) )
00160 {
00161
00162
00163
00164
00165
00166
00167
00168 std::vector<std::string> patparts;
00169 unsigned archpos = 2;
00170
00171 unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
00172 if ( patparts[count-1] == "gz" )
00173 archpos++;
00174
00175 if ( count > archpos )
00176 {
00177 try
00178 {
00179 Arch patarch( patparts[count-archpos] );
00180 if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) )
00181 {
00182
00183 MIL << "Discarding pattern " << it->first << endl;
00184 continue;
00185 }
00186 }
00187 catch ( const Exception & excpt )
00188 {
00189 WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
00190
00191 }
00192 }
00193 }
00194 MIL << "adding job " << it->first << endl;
00195 OnMediaLocation location( repoInfo().path() + descr_dir + it->first, 1 );
00196 location.setChecksum( it->second );
00197 this->enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, it->first));
00198 }
00199
00200 for_( it, _repoindex->mediaFileChecksums.begin(), _repoindex->mediaFileChecksums.end() )
00201 {
00202
00203 if ( it->first != "license.tar.gz" )
00204 continue;
00205
00206 MIL << "adding job " << it->first << endl;
00207 OnMediaLocation location( repoInfo().path() + it->first, 1 );
00208 location.setChecksum( it->second );
00209 this->enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir, it->first));
00210 }
00211
00212 for_( it, _repoindex->signingKeys.begin(),_repoindex->signingKeys.end() )
00213 {
00214 MIL << "adding job " << it->first << endl;
00215 OnMediaLocation location( repoInfo().path() + it->first, 1 );
00216 location.setChecksum( it->second );
00217 this->enqueueDigested(location);
00218 }
00219
00220 this->start( dest_dir, media );
00221 }
00222
00223 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
00224 {
00225 MIL << "Consuming repo index" << endl;
00226 _repoindex = data_r;
00227 }
00228
00229 }
00230 }
00231 }