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 )
00031   : repo::Downloader(repoinfo)
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 void Downloader::download( MediaSetAccess &media,
00046                            const Pathname &dest_dir,
00047                            const ProgressData::ReceiverFnc & progress )
00048 {
00049   downloadMediaInfo( dest_dir, media );
00050 
00051   SignatureFileChecker sigchecker/*(repoInfo().name())*/;
00052 
00053   Pathname sig = repoInfo().path() + "/content.asc";
00054 
00055   this->enqueue( OnMediaLocation( sig, 1 ).setOptional(true) );
00056   this->start( dest_dir, media );
00057   // only if there is a signature in the destination directory
00058   if ( PathInfo(dest_dir / sig ).isExist() )
00059       sigchecker = SignatureFileChecker( dest_dir + sig/*, repoInfo().name() */);
00060   this->reset();
00061 
00062   Pathname key = repoInfo().path() + "/content.key";
00063 
00064   this->enqueue( OnMediaLocation( key, 1 ).setOptional(true) );
00065   this->start( dest_dir, media );
00066 
00067   KeyContext context;
00068   context.setRepoInfo(repoInfo());
00069   // only if there is a key in the destination directory
00070   if ( PathInfo(dest_dir / key).isExist() )
00071     sigchecker.addPublicKey(dest_dir + key, context);
00072   // set the checker context even if the key is not known (unsigned repo, key
00073   // file missing; bnc #495977)
00074   else
00075     sigchecker.setKeyContext(context);
00076 
00077   this->reset();
00078 
00079   if ( ! repoInfo().gpgCheck() )
00080   {
00081     WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
00082   }
00083   this->enqueue( OnMediaLocation( repoInfo().path() + "/content", 1 ),
00084                  repoInfo().gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) );
00085   this->start( dest_dir, media );
00086   this->reset();
00087 
00088   Pathname descr_dir;
00089 
00090   // Content file first to get the repoindex
00091   {
00092     Pathname inputfile( dest_dir +  repoInfo().path() + "/content" );
00093     ContentFileReader content;
00094     content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
00095     content.parse( inputfile );
00096   }
00097   if ( ! _repoindex )
00098   {
00099     ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No repository index in content file." ) );
00100   }
00101   MIL << "RepoIndex: " << _repoindex << endl;
00102   if ( _repoindex->metaFileChecksums.empty() )
00103   {
00104     ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No metadata checksums in content file." ) );
00105   }
00106   if ( _repoindex->signingKeys.empty() )
00107   {
00108     WAR << "No signing keys defined." << endl;
00109   }
00110 
00111   // Prepare parsing
00112   descr_dir = _repoindex->descrdir; // path below reporoot
00113   //_datadir  = _repoIndex->datadir;  // path below reporoot
00114 
00115 
00116   for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() )
00117   {
00118     // omit unwanted translations
00119     if ( str::hasPrefix( it->first, "packages" ) )
00120     {
00121       std::string rest( str::stripPrefix( it->first, "packages" ) );
00122       if ( ! (   rest.empty()
00123               || rest == ".DU"
00124               || rest == ".en"
00125               || rest == ".gz"
00126               || rest == ".DU.gz"
00127               || rest == ".en.gz" ) )
00128       {
00129         // Not 100% correct as we take each fallback of textLocale
00130         Locale toParse( ZConfig::instance().textLocale() );
00131         while ( toParse != Locale::noCode )
00132         {
00133           if ( rest == ("."+toParse.code()) || (rest == ("."+toParse.code()+".gz")) )
00134             break;
00135           toParse = toParse.fallback();
00136         }
00137         if ( toParse == Locale::noCode )
00138         {
00139           // discard
00140           continue;
00141         }
00142       }
00143     }
00144     else if ( it->first == "patterns.pat"
00145               || it->first == "patterns.pat.gz" )
00146     {
00147       // take all patterns in one go
00148     }
00149     else if ( str::endsWith( it->first, ".pat" )
00150               || str::endsWith( it->first, ".pat.gz" ) )
00151     {
00152 
00153       // *** see also zypp/parser/susetags/RepoParser.cc ***
00154 
00155       // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716
00156       // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
00157       // split at dots, take .pat or .pat.gz into account
00158 
00159       std::vector<std::string> patparts;
00160       unsigned archpos = 2;
00161       // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
00162       unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
00163       if ( patparts[count-1] == "gz" )
00164           archpos++;
00165 
00166       if ( count > archpos )
00167       {
00168         try                             // might by an invalid architecture
00169         {
00170           Arch patarch( patparts[count-archpos] );
00171           if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) )
00172           {
00173             // discard, if not compatible
00174             MIL << "Discarding pattern " << it->first << endl;
00175             continue;
00176           }
00177         }
00178         catch ( const Exception & excpt )
00179         {
00180           WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
00181           // keep .pat file if it doesn't contain an recognizable arch
00182         }
00183       }
00184     }
00185     MIL << "adding job " << it->first << endl;
00186     OnMediaLocation location( repoInfo().path() + descr_dir + it->first, 1 );
00187     location.setChecksum( it->second );
00188     this->enqueueDigested(location);
00189   }
00190 
00191   for_( it, _repoindex->mediaFileChecksums.begin(), _repoindex->mediaFileChecksums.end() )
00192   {
00193     // Repo adopts license files listed in HASH
00194     if ( it->first != "license.tar.gz" )
00195       continue;
00196 
00197     MIL << "adding job " << it->first << endl;
00198     OnMediaLocation location( repoInfo().path() + it->first, 1 );
00199     location.setChecksum( it->second );
00200     this->enqueueDigested(location);
00201   }
00202 
00203   for_( it, _repoindex->signingKeys.begin(),_repoindex->signingKeys.end() )
00204   {
00205     MIL << "adding job " << it->first << endl;
00206     OnMediaLocation location( repoInfo().path() + it->first, 1 );
00207     location.setChecksum( it->second );
00208     this->enqueueDigested(location);
00209   }
00210 
00211   this->start( dest_dir, media );
00212 }
00213 
00214 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
00215 {
00216   MIL << "Consuming repo index" << endl;
00217   _repoindex = data_r;
00218 }
00219 
00220 }// ns susetags
00221 }// ns source
00222 } // ns zypp

doxygen