libzypp
10.5.0
|
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