libzypp
10.5.0
|
00001 00002 #include <iostream> 00003 #include <fstream> 00004 00005 #include "zypp/base/LogTools.h" 00006 #include "zypp/base/String.h" 00007 #include "zypp/base/Regex.h" 00008 #include "zypp/OnMediaLocation.h" 00009 #include "zypp/MediaSetAccess.h" 00010 #include "zypp/Fetcher.h" 00011 #include "zypp/Locale.h" 00012 #include "zypp/ZConfig.h" 00013 #include "zypp/repo/MediaInfoDownloader.h" 00014 #include "zypp/repo/susetags/Downloader.h" 00015 #include "zypp/parser/ParseException.h" 00016 #include "zypp/parser/susetags/RepoIndex.h" 00017 #include "zypp/base/UserRequestException.h" 00018 #include "zypp/KeyContext.h" // for SignatureFileChecker 00019 00020 using namespace std; 00021 using namespace zypp::parser; 00022 using namespace zypp::parser::susetags; 00023 00024 namespace zypp 00025 { 00026 namespace repo 00027 { 00028 namespace susetags 00029 { 00030 00031 Downloader::Downloader( const RepoInfo &repoinfo, const Pathname &delta_dir ) 00032 : repo::Downloader(repoinfo), _delta_dir(delta_dir) 00033 { 00034 } 00035 00036 RepoStatus Downloader::status( MediaSetAccess &media ) 00037 { 00038 Pathname content = media.provideFile( repoInfo().path() + "/content"); 00039 // the media.1 is always in the root of the media, not like the content 00040 // file which is in the path() location 00041 Pathname mediafile = media.provideFile( "/media.1/media" ); 00042 00043 return RepoStatus(content) && RepoStatus(mediafile); 00044 } 00045 00046 // search old repository file file to run the delta algorithm on 00047 static Pathname search_deltafile( const Pathname &dir, const Pathname &file ) 00048 { 00049 Pathname deltafile(dir + file.basename()); 00050 if (PathInfo(deltafile).isExist()) 00051 return deltafile; 00052 return Pathname(); 00053 } 00054 00055 void Downloader::download( MediaSetAccess &media, 00056 const Pathname &dest_dir, 00057 const ProgressData::ReceiverFnc & progress ) 00058 { 00059 downloadMediaInfo( dest_dir, media ); 00060 00061 SignatureFileChecker sigchecker/*(repoInfo().name())*/; 00062 00063 Pathname sig = repoInfo().path() + "/content.asc"; 00064 00065 enqueue( OnMediaLocation( sig, 1 ).setOptional(true) ); 00066 start( dest_dir, media ); 00067 // only if there is a signature in the destination directory 00068 if ( PathInfo(dest_dir / sig ).isExist() ) 00069 sigchecker = SignatureFileChecker( dest_dir + sig/*, repoInfo().name() */); 00070 reset(); 00071 00072 Pathname key = repoInfo().path() + "/content.key"; 00073 00074 enqueue( OnMediaLocation( key, 1 ).setOptional(true) ); 00075 start( dest_dir, media ); 00076 00077 KeyContext context; 00078 context.setRepoInfo(repoInfo()); 00079 // only if there is a key in the destination directory 00080 if ( PathInfo(dest_dir / key).isExist() ) 00081 sigchecker.addPublicKey(dest_dir + key, context); 00082 // set the checker context even if the key is not known (unsigned repo, key 00083 // file missing; bnc #495977) 00084 else 00085 sigchecker.setKeyContext(context); 00086 00087 reset(); 00088 00089 if ( ! repoInfo().gpgCheck() ) 00090 { 00091 WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl; 00092 } 00093 enqueue( OnMediaLocation( repoInfo().path() + "/content", 1 ), 00094 repoInfo().gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) ); 00095 start( dest_dir, media ); 00096 reset(); 00097 00098 Pathname descr_dir; 00099 00100 // Content file first to get the repoindex 00101 { 00102 Pathname inputfile( dest_dir + repoInfo().path() + "/content" ); 00103 ContentFileReader content; 00104 content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) ); 00105 content.parse( inputfile ); 00106 } 00107 if ( ! _repoindex ) 00108 { 00109 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No repository index in content file." ) ); 00110 } 00111 MIL << "RepoIndex: " << _repoindex << endl; 00112 if ( _repoindex->metaFileChecksums.empty() ) 00113 { 00114 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No metadata checksums in content file." ) ); 00115 } 00116 if ( _repoindex->signingKeys.empty() ) 00117 { 00118 WAR << "No signing keys defined." << endl; 00119 } 00120 00121 // Prepare parsing 00122 descr_dir = _repoindex->descrdir; // path below reporoot 00123 //_datadir = _repoIndex->datadir; // path below reporoot 00124 00125 std::map<std::string,RepoIndex::FileChecksumMap::const_iterator> availablePackageTranslations; 00126 00127 for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() ) 00128 { 00129 // omit unwanted translations 00130 if ( str::hasPrefix( it->first, "packages" ) ) 00131 { 00132 static const str::regex rx_packages( "^packages((.gz)?|(.([^.]*))(.gz)?)$" ); 00133 str::smatch what; 00134 if ( str::regex_match( it->first, what, rx_packages ) ) 00135 { 00136 if ( what[4].empty() // packages(.gz)? 00137 || what[4] == "DU" 00138 || what[4] == "en" ) 00139 { ; /* always downloaded */ } 00140 else if ( what[4] == "FL" ) 00141 { continue; /* never downloaded */ } 00142 else 00143 { 00144 // remember and decide later 00145 availablePackageTranslations[what[4]] = it; 00146 continue; 00147 } 00148 } 00149 else 00150 continue; // discard 00151 } 00152 else if ( it->first == "patterns.pat" 00153 || it->first == "patterns.pat.gz" ) 00154 { 00155 // take all patterns in one go 00156 } 00157 else if ( str::endsWith( it->first, ".pat" ) 00158 || str::endsWith( it->first, ".pat.gz" ) ) 00159 { 00160 00161 // *** see also zypp/parser/susetags/RepoParser.cc *** 00162 00163 // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716 00164 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots 00165 // split at dots, take .pat or .pat.gz into account 00166 00167 std::vector<std::string> patparts; 00168 unsigned archpos = 2; 00169 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots 00170 unsigned count = str::split( it->first, std::back_inserter(patparts), "." ); 00171 if ( patparts[count-1] == "gz" ) 00172 archpos++; 00173 00174 if ( count > archpos ) 00175 { 00176 try // might by an invalid architecture 00177 { 00178 Arch patarch( patparts[count-archpos] ); 00179 if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) ) 00180 { 00181 // discard, if not compatible 00182 MIL << "Discarding pattern " << it->first << endl; 00183 continue; 00184 } 00185 } 00186 catch ( const Exception & excpt ) 00187 { 00188 WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl; 00189 // keep .pat file if it doesn't contain an recognizable arch 00190 } 00191 } 00192 } 00193 MIL << "adding job " << it->first << endl; 00194 OnMediaLocation location( repoInfo().path() + descr_dir + it->first, 1 ); 00195 location.setChecksum( it->second ); 00196 enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, it->first)); 00197 } 00198 00199 // check whether to download more package translations: 00200 { 00201 auto fnc_checkTransaltions( [&]( const Locale & locale_r ) { 00202 for ( Locale toGet( locale_r ); toGet != Locale::noCode; toGet = toGet.fallback() ) 00203 { 00204 auto it( availablePackageTranslations.find( toGet.code() ) ); 00205 if ( it != availablePackageTranslations.end() ) 00206 { 00207 auto mit( it->second ); 00208 MIL << "adding job " << mit->first << endl; 00209 OnMediaLocation location( repoInfo().path() + descr_dir + mit->first, 1 ); 00210 location.setChecksum( mit->second ); 00211 enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, mit->first)); 00212 break; 00213 } 00214 } 00215 }); 00216 for ( const Locale & it : ZConfig::instance().repoRefreshLocales() ) 00217 { 00218 fnc_checkTransaltions( it ); 00219 } 00220 fnc_checkTransaltions( ZConfig::instance().textLocale() ); 00221 } 00222 00223 for_( it, _repoindex->mediaFileChecksums.begin(), _repoindex->mediaFileChecksums.end() ) 00224 { 00225 // Repo adopts license files listed in HASH 00226 if ( it->first != "license.tar.gz" ) 00227 continue; 00228 00229 MIL << "adding job " << it->first << endl; 00230 OnMediaLocation location( repoInfo().path() + it->first, 1 ); 00231 location.setChecksum( it->second ); 00232 enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir, it->first)); 00233 } 00234 00235 for_( it, _repoindex->signingKeys.begin(),_repoindex->signingKeys.end() ) 00236 { 00237 MIL << "adding job " << it->first << endl; 00238 OnMediaLocation location( repoInfo().path() + it->first, 1 ); 00239 location.setChecksum( it->second ); 00240 enqueueDigested(location); 00241 } 00242 00243 start( dest_dir, media ); 00244 } 00245 00246 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r ) 00247 { 00248 MIL << "Consuming repo index" << endl; 00249 _repoindex = data_r; 00250 } 00251 00252 }// ns susetags 00253 }// ns source 00254 } // ns zypp