libzypp  10.5.0
Downloader.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00009 
00010 #include <fstream>
00011 #include "zypp/base/String.h"
00012 #include "zypp/base/Logger.h"
00013 #include "zypp/base/Function.h"
00014 
00015 #include "zypp/Date.h"
00016 
00017 #include "zypp/parser/yum/RepomdFileReader.h"
00018 #include "zypp/parser/yum/PatchesFileReader.h"
00019 #include "Downloader.h"
00020 #include "zypp/repo/MediaInfoDownloader.h"
00021 #include "zypp/base/UserRequestException.h"
00022 #include "zypp/parser/xml/Reader.h"
00023 #include "zypp/KeyContext.h"
00024 
00025 using namespace std;
00026 using namespace zypp::xml;
00027 using namespace zypp::parser::yum;
00028 
00029 namespace zypp
00030 {
00031 namespace repo
00032 {
00033 namespace yum
00034 {
00035 
00036 Downloader::Downloader( const RepoInfo &repoinfo , const Pathname &delta_dir)
00037   : repo::Downloader(repoinfo), _delta_dir(delta_dir), _media_ptr(0L)
00038 {
00039 }
00040 
00041 
00042 RepoStatus Downloader::status( MediaSetAccess &media )
00043 {
00044   Pathname repomd = media.provideFile( repoInfo().path() + "/repodata/repomd.xml");
00045   return RepoStatus(repomd);
00046 }
00047 
00048 static OnMediaLocation
00049 loc_with_path_prefix(const OnMediaLocation & loc,
00050                      const Pathname & prefix)
00051 {
00052   if (prefix.empty() || prefix == "/")
00053     return loc;
00054 
00055   OnMediaLocation loc_with_path(loc);
00056   loc_with_path.changeFilename(prefix / loc.filename());
00057   return loc_with_path;
00058 }
00059 
00060 // search old repository file file to run the delta algorithm on
00061 static Pathname search_deltafile( const Pathname &dir, const Pathname &file )
00062 {
00063   Pathname deltafile;
00064   if (!PathInfo(dir).isDir())
00065     return deltafile;
00066   string base = file.basename();
00067   size_t hypoff = base.find("-");
00068   if (hypoff != string::npos)
00069     base.replace(0, hypoff + 1, "");
00070   size_t basesize = base.size();
00071   std::list<Pathname> retlist;
00072   if (!filesystem::readdir(retlist, dir, false))
00073   {
00074     for_( it, retlist.begin(), retlist.end() )
00075     {
00076       string fn = it->asString();
00077       if (fn.size() >= basesize && fn.substr(fn.size() - basesize, basesize) == base)
00078         deltafile = *it;
00079     }
00080   }
00081   return deltafile;
00082 }
00083 
00084 bool Downloader::patches_Callback( const OnMediaLocation &loc,
00085                                    const string &id )
00086 {
00087   OnMediaLocation loc_with_path(loc_with_path_prefix(loc, repoInfo().path()));
00088   MIL << id << " : " << loc_with_path << endl;
00089   this->enqueueDigested(loc_with_path,  FileChecker(), search_deltafile(_delta_dir + "repodata", loc.filename()));
00090   return true;
00091 }
00092 
00093 bool Downloader::repomd_Callback( const OnMediaLocation &loc,
00094                                   const ResourceType &dtype )
00095 {
00096   OnMediaLocation loc_with_path(loc_with_path_prefix(loc, repoInfo().path()));
00097   MIL << dtype << " : " << loc_with_path << endl;
00098 
00100   // skip other
00101   if ( dtype == ResourceType::OTHER )
00102   {
00103     MIL << "Skipping other.xml" << endl;
00104     return true;
00105   }
00106   // skip filelists
00107   if ( dtype == ResourceType::FILELISTS )
00108   {
00109     MIL << "Skipping filelists.xml.gz" << endl;
00110     return true;
00111   }
00112 
00113   this->enqueueDigested(loc_with_path, FileChecker(), search_deltafile(_delta_dir + "repodata", loc.filename()));
00114 
00115   // We got a patches file we need to read, to add patches listed
00116   // there, so we transfer what we have in the queue, and
00117   // queue the patches in the patches callback
00118   if ( dtype == ResourceType::PATCHES )
00119   {
00120     this->start( _dest_dir, *_media_ptr );
00121     // now the patches.xml file must exists
00122     PatchesFileReader( _dest_dir + repoInfo().path() + loc.filename(),
00123                        bind( &Downloader::patches_Callback, this, _1, _2));
00124   }
00125 
00126   return true;
00127 }
00128 
00129 void Downloader::download( MediaSetAccess &media,
00130                            const Pathname &dest_dir,
00131                            const ProgressData::ReceiverFnc & progressrcv )
00132 {
00133   Pathname repomdpath =  repoInfo().path() + "/repodata/repomd.xml";
00134   Pathname keypath =  repoInfo().path() + "/repodata/repomd.xml.key";
00135   Pathname sigpath =  repoInfo().path() + "/repodata/repomd.xml.asc";
00136 
00137   _media_ptr = (&media);
00138 
00139   ProgressData progress;
00140   progress.sendTo(progressrcv);
00141   progress.toMin();
00142 
00143   //downloadMediaInfo( dest_dir, _media );
00144 
00145   _dest_dir = dest_dir;
00146 
00147 #warning Do we need SignatureFileChecker(string descr)?
00148   SignatureFileChecker sigchecker/*(repoInfo().name())*/;
00149 
00150   this->enqueue( OnMediaLocation(sigpath,1).setOptional(true) );
00151   this->start( dest_dir, *_media_ptr);
00152   // only add the signature if it exists
00153   if ( PathInfo(dest_dir / sigpath).isExist() )
00154       sigchecker = SignatureFileChecker(dest_dir / sigpath);
00155   this->reset();
00156 
00157   this->enqueue( OnMediaLocation(keypath,1).setOptional(true) );
00158   this->start( dest_dir, *_media_ptr);
00159 
00160   KeyContext context;
00161   context.setRepoInfo(repoInfo());
00162   // only add the key if it exists
00163   if ( PathInfo(dest_dir / keypath).isExist() )
00164     sigchecker.addPublicKey(dest_dir + keypath, context);
00165   // set the checker context even if the key is not known (unsigned repo, key
00166   // file missing; bnc #495977)
00167   else
00168     sigchecker.setKeyContext(context);
00169 
00170   this->reset();
00171 
00172   if ( ! progress.tick() )
00173     ZYPP_THROW(AbortRequestException());
00174 
00175   if ( ! repoInfo().gpgCheck() )
00176     WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
00177 
00178   this->enqueue( OnMediaLocation(repomdpath,1),
00179                  repoInfo().gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) );
00180   this->start( dest_dir, *_media_ptr);
00181 
00182   if ( ! progress.tick() )
00183         ZYPP_THROW(AbortRequestException());
00184 
00185   this->reset();
00186 
00187   Reader reader( dest_dir + repoInfo().path() + "/repodata/repomd.xml" );
00188   RepomdFileReader( dest_dir + repoInfo().path() + "/repodata/repomd.xml", bind( &Downloader::repomd_Callback, this, _1, _2));
00189 
00190   // ready, go!
00191   this->start( dest_dir, *_media_ptr);
00192   progress.toMax();
00193 }
00194 
00195 }// ns yum
00196 }// ns source
00197 } // ns zypp
00198 
00199 
00200