Downloader.cc
Go to the documentation of this file.00001
00002
00003
00004
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
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
00101 if ( dtype == ResourceType::OTHER )
00102 {
00103 MIL << "Skipping other.xml" << endl;
00104 return true;
00105 }
00106
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
00116
00117
00118 if ( dtype == ResourceType::PATCHES )
00119 {
00120 this->start( _dest_dir, *_media_ptr );
00121
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
00144
00145 _dest_dir = dest_dir;
00146
00147 #warning Do we need SignatureFileChecker(string descr)?
00148 SignatureFileChecker sigchecker;
00149
00150 this->enqueue( OnMediaLocation(sigpath,1).setOptional(true) );
00151 this->start( dest_dir, *_media_ptr);
00152
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
00163 if ( PathInfo(dest_dir / keypath).isExist() )
00164 sigchecker.addPublicKey(dest_dir + keypath, context);
00165
00166
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
00191 this->start( dest_dir, *_media_ptr);
00192 progress.toMax();
00193 }
00194
00195 }
00196 }
00197 }
00198
00199
00200