libzypp 8.13.6
|
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" // for SignatureFileChecker 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 // the media.1 is always in the root of the media, not like the content 00039 // file which is in the path() location 00040 Pathname mediafile = media.provideFile( "/media.1/media" ); 00041 00042 return RepoStatus(content) && RepoStatus(mediafile); 00043 } 00044 00045 // search old repository file file to run the delta algorithm on 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/*(repoInfo().name())*/; 00061 00062 Pathname sig = repoInfo().path() + "/content.asc"; 00063 00064 this->enqueue( OnMediaLocation( sig, 1 ).setOptional(true) ); 00065 this->start( dest_dir, media ); 00066 // only if there is a signature in the destination directory 00067 if ( PathInfo(dest_dir / sig ).isExist() ) 00068 sigchecker = SignatureFileChecker( dest_dir + sig/*, repoInfo().name() */); 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 // only if there is a key in the destination directory 00079 if ( PathInfo(dest_dir / key).isExist() ) 00080 sigchecker.addPublicKey(dest_dir + key, context); 00081 // set the checker context even if the key is not known (unsigned repo, key 00082 // file missing; bnc #495977) 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 // Content file first to get the repoindex 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 // Prepare parsing 00121 descr_dir = _repoindex->descrdir; // path below reporoot 00122 //_datadir = _repoIndex->datadir; // path below reporoot 00123 00124 00125 for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() ) 00126 { 00127 // omit unwanted translations 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 // Not 100% correct as we take each fallback of textLocale 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 // discard 00149 continue; 00150 } 00151 } 00152 } 00153 else if ( it->first == "patterns.pat" 00154 || it->first == "patterns.pat.gz" ) 00155 { 00156 // take all patterns in one go 00157 } 00158 else if ( str::endsWith( it->first, ".pat" ) 00159 || str::endsWith( it->first, ".pat.gz" ) ) 00160 { 00161 00162 // *** see also zypp/parser/susetags/RepoParser.cc *** 00163 00164 // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716 00165 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots 00166 // split at dots, take .pat or .pat.gz into account 00167 00168 std::vector<std::string> patparts; 00169 unsigned archpos = 2; 00170 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots 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 // might by an invalid architecture 00178 { 00179 Arch patarch( patparts[count-archpos] ); 00180 if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) ) 00181 { 00182 // discard, if not compatible 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 // keep .pat file if it doesn't contain an recognizable arch 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 // Repo adopts license files listed in HASH 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 }// ns susetags 00230 }// ns source 00231 } // ns zypp