libzypp 8.13.6

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" // 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