YUMSourceImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00013 #include "zypp/source/yum/YUMSourceImpl.h"
00014 #include "zypp/source/yum/YUMAtomImpl.h"
00015 #include "zypp/source/yum/YUMPackageImpl.h"
00016 #include "zypp/source/yum/YUMScriptImpl.h"
00017 #include "zypp/source/yum/YUMMessageImpl.h"
00018 #include "zypp/source/yum/YUMPatchImpl.h"
00019 #include "zypp/source/yum/YUMProductImpl.h"
00020 #include "zypp/source/yum/YUMGroupImpl.h"
00021 #include "zypp/source/yum/YUMPatternImpl.h"
00022 
00023 #include "zypp/NVRA.h"
00024 #include "zypp/PathInfo.h"
00025 #include "zypp/base/Logger.h"
00026 #include "zypp/base/Exception.h"
00027 #include "zypp/CapFactory.h"
00028 #include "zypp/Digest.h"
00029 #include "zypp/ExternalProgram.h"
00030 #include "zypp/TmpPath.h"
00031 #include "zypp/ZYppFactory.h"
00032 #include "zypp/KeyRing.h"
00033 
00034 #include "zypp/parser/yum/YUMParser.h"
00035 #include "zypp/SourceFactory.h"
00036 #include "zypp/ZYppCallbacks.h"
00037 #include "zypp/SilentCallbacks.h"
00038 
00039 #include "zypp/base/GzStream.h"
00040 #include "zypp/base/Gettext.h"
00041 #include "zypp/PathInfo.h"
00042 
00043 #include <fstream>
00044 
00045 using namespace std;
00046 using namespace zypp::detail;
00047 using namespace zypp::parser::yum;
00048 
00050 namespace zypp
00051 { 
00052 
00053   namespace source
00054   { 
00055     namespace yum
00056     {
00058       //
00059       //        CLASS NAME : YUMSourceImpl
00060       //
00062 
00063       YUMSourceImpl::YUMSourceImpl()
00064       {}
00065 
00066       Date YUMSourceImpl::timestamp() const
00067       {
00068         return PathInfo(repomdFile()).mtime();
00069       }
00070 
00071       bool YUMSourceImpl::cacheExists()
00072       {
00073         bool exists = PathInfo(repomdFile()).isExist();
00074         if (exists)
00075           MIL << "YUM cache found at " << _cache_dir << std::endl;
00076         else
00077           MIL << "YUM cache not found" << std::endl;
00078 
00079         return exists;
00080       }
00081 
00082       const Pathname YUMSourceImpl::metadataRoot() const
00083       {
00084         return _cache_dir.empty() ? tmpMetadataDir() : _cache_dir;
00085       }
00086 
00087       const Pathname YUMSourceImpl::repomdFile() const
00088       {
00089         return metadataRoot() + "/repodata/repomd.xml";
00090       }
00091 
00092       const Pathname YUMSourceImpl::repomdFileSignature() const
00093       {
00094         return metadataRoot() + "/repodata/repomd.xml.asc";
00095       }
00096 
00097       const Pathname YUMSourceImpl::repomdFileKey() const
00098       {
00099         return metadataRoot() + "/repodata/repomd.xml.key";
00100       }
00101 
00102       const TmpDir YUMSourceImpl::downloadMetadata()
00103       {
00104         TmpDir tmpdir;
00105         int copy_result;
00106         MIL << "Downloading metadata to " << tmpdir.path() << std::endl;
00107 
00108         Pathname local_dir = tmpdir.path();
00109         if (0 != assert_dir(local_dir + "/repodata" , 0755))
00110           ZYPP_THROW(Exception("Cannot create /repodata in download directory"));
00111 
00112         MIL << "Storing data to tmp dir " << local_dir << endl;
00113 
00114         // first read list of all files in the repository
00115         Pathname remote_repomd;
00116         try
00117         {
00118           remote_repomd = provideFile(_path + "/repodata/repomd.xml");
00119         }
00120         catch(Exception &e)
00121         {
00122           ZYPP_THROW(Exception("Can't provide " + _path.asString() + "/repodata/repomd.xml from " + url().asString() ));
00123         }
00124 
00125         // provide optional files
00126         Pathname remote_repomd_key;
00127         Pathname remote_repomd_signature;
00128         try {
00129           remote_repomd_key = tryToProvideFile( _path + "/repodata/repomd.xml.key");
00130         }
00131         catch( const Exception &e ) {
00132           WAR << "Repository does not contain repomd signing key" << std::endl;
00133         }
00134 
00135         try {
00136           remote_repomd_signature = tryToProvideFile( _path + "/repodata/repomd.xml.asc");
00137         }
00138         catch( const Exception &e ) {
00139           WAR << "Repository does not contain repomd signature" << std::endl;
00140         }
00141 
00142         copy_result = filesystem::copy( remote_repomd, local_dir + "/repodata/repomd.xml");
00143         if ( copy_result != 0 )
00144           ZYPP_THROW(Exception("Can't copy " + remote_repomd.asString() + " to " + local_dir.asString() + "/repodata/repomd.xml"));
00145 
00146         if (PathInfo(remote_repomd_key).isExist())
00147         {
00148           copy_result = filesystem::copy( remote_repomd_key, local_dir + "/repodata/repomd.xml.key");
00149           if ( copy_result != 0 )
00150             ZYPP_THROW(Exception("Can't copy " + remote_repomd_key.asString() + " to " + local_dir.asString() + "/repodata/repomd.xml.key"));
00151           getZYpp()->keyRing()->importKey(local_dir + "/repodata/repomd.xml.key" , false);
00152         }
00153 
00154         if (PathInfo(remote_repomd_signature).isExist())
00155         {
00156           copy_result = filesystem::copy( remote_repomd_signature, local_dir + "/repodata/repomd.xml.asc");
00157           if ( copy_result != 0 )
00158             ZYPP_THROW(Exception("Can't copy " + remote_repomd_signature.asString() + " to " + local_dir.asString() + "/repodata/repomd.xml.asc"));
00159         }
00160 
00161         DBG << "Reading file " << remote_repomd << endl;
00162         ifstream repo_st(remote_repomd.asString().c_str());
00163         YUMRepomdParser repomd(repo_st, "");
00164 
00165         for(; ! repomd.atEnd(); ++repomd)
00166         {
00167           if ((*repomd)->type == "other")     // don't parse 'other.xml' (#159316)
00168             continue;
00169 
00170           Pathname src;
00171           try
00172           {
00173             src = provideFile(_path + (*repomd)->location);
00174           }
00175           catch (const Exception &e)
00176           {
00177             ZYPP_THROW(Exception("Can't provide " + _path.asString() + (*repomd)->location + " from " + url().asString() ));
00178           }
00179 
00180           Pathname dst = local_dir + (*repomd)->location;
00181 
00182           //if (0 != assert_dir(dst, 0755))
00183           //  ZYPP_THROW(Exception("Cannot create directory: " + dst.asString()));
00184 
00185           if ( filesystem::copy(src, dst) != 0 )
00186             ZYPP_THROW(Exception("Can't copy " + src.asString() + " to " + dst.asString()));
00187 
00188           if (! checkCheckSum( dst, (*repomd)->checksumType, (*repomd)->checksum))
00189             ZYPP_THROW(Exception( (*repomd)->location + " " + N_(" fails checksum verification.") ));
00190 
00191 
00192           // if it is a patch, we read the patches individually
00193           if ((*repomd)->type == "patches")
00194           {
00195             // use the local copy now
00196             Pathname patches_list = dst;
00197             MIL << "Reading patches file " << patches_list << std::endl;
00198             ifgzstream st ( patches_list.asString().c_str() );
00199             YUMPatchesParser patch(st, "");
00200             for (; !patch.atEnd(); ++patch)
00201             {
00202               string filename = (*patch)->location;
00203               Pathname patch_src;
00204               Pathname patch_dst;
00205               try
00206               {
00207                 patch_src = provideFile(_path + filename);
00208               }
00209               catch (const Exception &e)
00210               {
00211                 ZYPP_CAUGHT(e);
00212                 ZYPP_THROW(Exception("Can't provide patch " + _path.asString() + (*repomd)->location + " from " + url().asString()));
00213               }
00214 
00215               patch_dst = local_dir + filename;
00216 
00217               if ( filesystem::copy(patch_src, patch_dst) != 0 )
00218                 ZYPP_THROW(Exception("Can't copy patch file " + patch_src.asString() + " to " + patch_dst.asString()));
00219 
00220               // check patch checksum
00221               if (! checkCheckSum( patch_dst, (*patch)->checksumType, (*patch)->checksum))
00222                 ZYPP_THROW(Exception( (*repomd)->location + " " + N_(" fails checksum verification.") ));
00223             } // end of single patch parsing
00224           }// end of patches file parsing
00225         } // end of copying
00226 
00227         // check signature
00228         MIL << "Checking [" << (local_dir + "/repodata/repomd.xml") << "] signature"  << endl;
00229         if (! getZYpp()->keyRing()->verifyFileSignatureWorkflow(local_dir + "/repodata/repomd.xml", (_path + "/repodata/repomd.xml").asString()+ " (" + url().asString() + ")", local_dir + "/repodata/repomd.xml.asc"))
00230           ZYPP_THROW(Exception(N_("Signed repomd.xml file fails signature check")));
00231 
00232         // ok, now we have a consistent repo in the tmpdir.
00233         return tmpdir;
00234       }
00235 
00236       void YUMSourceImpl::factoryInit()
00237       {
00238         resetMediaVerifier();
00239 
00240         bool cache = cacheExists();
00241         if ( cache )
00242         {
00243           DBG << "Cached metadata found in [" << _cache_dir << "]." << endl;
00244           if ( autorefresh() )
00245             storeMetadata(_cache_dir);
00246         }
00247         else
00248         {
00249           if ( _cache_dir.empty() || !PathInfo(_cache_dir).isExist() )
00250           {
00251             DBG << "Cache dir not set. Downloading to temp dir: " << tmpMetadataDir() << std::endl;
00252             // as we have no local dir set we use a tmp one, but we use a member variable because
00253             // it cant go out of scope while the source exists.
00254             saveMetadataTo(tmpMetadataDir());
00255           }
00256           else
00257           {
00258             DBG << "Cached metadata not found in [" << _cache_dir << "]. Will download." << std::endl;
00259             saveMetadataTo(_cache_dir);
00260           }
00261         }
00262 
00263         MIL << "YUM source initialized." << std::endl;
00264         MIL << "   Url      : " << url() << std::endl;
00265         MIL << "   Path     : " << path() << std::endl;
00266         MIL << "   Metadata : " << metadataRoot() << (_cache_dir.empty() ? " [TMP]" : " [CACHE]") << std::endl;
00267       }
00268 
00269       void YUMSourceImpl::checkMetadataChecksums() const
00270       {
00271         DBG << "Reading file " << repomdFile() << " to check integrity of metadata." << endl;
00272         ifstream repo_st(repomdFile().asString().c_str());
00273         YUMRepomdParser repomd(repo_st, "");
00274 
00275         for(; ! repomd.atEnd(); ++repomd)
00276         {
00277           if ((*repomd)->type == "other")
00278           {             // dont parse other.xml (#159316)
00279             continue;
00280           }
00281           else
00282           {
00283             Pathname file_to_check = metadataRoot() + _path + (*repomd)->location;
00284             if (! checkCheckSum( file_to_check, (*repomd)->checksumType, (*repomd)->checksum))
00285             {
00286               ZYPP_THROW(Exception( (*repomd)->location + " " + N_("fails checksum verification.") ));
00287             }
00288 
00289             // now parse patches mentioned if we are in patches.xml
00290 
00291             if ((*repomd)->type == "patches")
00292             {
00293               Pathname patch_index = file_to_check;
00294               DBG << "reading patches from file " << patch_index << endl;
00295               ifgzstream st ( patch_index.asString().c_str() );
00296               YUMPatchesParser patch(st, "");
00297               for (; !patch.atEnd(); ++patch)
00298               {
00299                 Pathname patch_filename = metadataRoot() + _path + (*patch)->location;
00300                 if (! checkCheckSum(patch_filename, (*patch)->checksumType, (*patch)->checksum))
00301                 {
00302                   ZYPP_THROW(Exception( (*patch)->location + " " + N_("fails checksum verification.") ));
00303                 }
00304               }
00305             }
00306           }
00307         }
00308       }
00309 
00310       bool YUMSourceImpl::downloadNeeded(const Pathname & localdir)
00311       {
00312         // we can only assume repomd intact means the source changed if the source is signed.
00313         if ( cacheExists() && PathInfo( repomdFileSignature() ).isExist() )
00314         {
00315           Pathname remote_repomd;
00316           try
00317           {
00318             remote_repomd = provideFile(_path + "/repodata/repomd.xml");
00319           }
00320           catch(Exception &e)
00321           {
00322             ZYPP_THROW(Exception("Can't provide " + _path.asString() + "/repodata/repomd.xml from " + url().asString() ));
00323           }
00324 
00325           CheckSum old_repomd_checksum( "SHA1", filesystem::sha1sum(localdir + "/repodata/repomd.xml"));
00326           CheckSum new_repomd_checksum( "SHA1", filesystem::sha1sum(remote_repomd));
00327           if ( (new_repomd_checksum == old_repomd_checksum) && (!new_repomd_checksum.empty()) && (! old_repomd_checksum.empty()))
00328           {
00329             return false;
00330           }
00331         }
00332         return true;
00333       }
00334 
00335       void YUMSourceImpl::storeMetadata(const Pathname & cache_dir_r)
00336       {
00337         if ( !_cache_dir.empty() )
00338         {
00339           saveMetadataTo(cache_dir_r);
00340         }
00341         else
00342         {
00343           // no previous cache, use the data read temporarely
00344           copyLocalMetadata(tmpMetadataDir(), cache_dir_r);
00345         }
00346 
00347         MIL << "Metadata saved in " << cache_dir_r << ". Setting as cache." << std::endl;
00348         _cache_dir = cache_dir_r;
00349       }
00350 
00351       void YUMSourceImpl::saveMetadataTo(const Pathname & dir_r)
00352       {
00353         TmpDir download_tmp_dir;
00354 
00355         bool need_to_refresh = true;
00356         try
00357         {
00358           need_to_refresh = downloadNeeded(dir_r);
00359         }
00360         catch(Exception &e)
00361         {
00362           ZYPP_THROW(Exception("Can't check if source has changed or not. Aborting refresh."));
00363         }
00364 
00365         if ( need_to_refresh )
00366         {
00367           MIL << "YUM source '" << alias() << "' has changed since last download. Re-reading metadata into " << dir_r << endl;
00368         }
00369         else
00370         {
00371           MIL << "YUM source '" << alias() << "' has not changed. Refresh completed. SHA1 of repomd.xml file is  the same." << std::endl;
00372           return;
00373         }
00374 
00375         try
00376         {
00377           download_tmp_dir = downloadMetadata();
00378         }
00379         catch(Exception &e)
00380         {
00381           ZYPP_THROW(Exception("Downloading metadata failed (is YUM source?) or user did not accept remote source. Aborting refresh."));
00382         }
00383 
00384         copyLocalMetadata(download_tmp_dir, dir_r);
00385 
00386         // download_tmp_dir go out of scope now but it is ok as we already copied the content.
00387       }
00388 
00389       void YUMSourceImpl::createResolvables(Source_Ref source_r)
00390       {
00391         std::list<YUMRepomdData_Ptr> repo_primary;
00392         std::list<YUMRepomdData_Ptr> repo_files;
00393         //std::list<YUMRepomdData_Ptr> repo_other;
00394         std::list<YUMRepomdData_Ptr> repo_group;
00395         std::list<YUMRepomdData_Ptr> repo_pattern;
00396         std::list<YUMRepomdData_Ptr> repo_product;
00397         std::list<YUMRepomdData_Ptr> repo_patches;
00398 
00399         callback::SendReport<CreateSourceReport> report;
00400 
00401         report->startData( url() );
00402 
00403         //---------------------------------
00404         // repomd
00405 
00406         try
00407         {
00408           DBG << "Reading ifgz file " << repomdFile() << endl;
00409           ifgzstream repo_st(repomdFile().asString().c_str());
00410           YUMRepomdParser repomd(repo_st, "");
00411           for(; ! repomd.atEnd(); ++repomd)
00412           {
00413             // note that we skip adding other.xml to the list of files to provide
00414             if ((*repomd)->type == "primary")
00415               repo_primary.push_back(*repomd);
00416             else if ((*repomd)->type == "filelists")
00417               repo_files.push_back(*repomd);
00418             else if ((*repomd)->type == "group")
00419               repo_group.push_back(*repomd);
00420             else if ((*repomd)->type == "pattern")
00421               repo_pattern.push_back(*repomd);
00422             else if ((*repomd)->type == "product")
00423               repo_product.push_back(*repomd);
00424             else if ((*repomd)->type == "patches")
00425               repo_patches.push_back(*repomd);
00426             else if ((*repomd)->type != "other")        // type "other" is ok, anything else not
00427               ERR << "Unknown type of repo file: " << (*repomd)->type << endl;
00428            }
00429         }
00430         catch( const Exception &  excpt_r )
00431         {
00432           ZYPP_CAUGHT( excpt_r );       // log the caught exception
00433           ZYPP_THROW( Exception("Cannot read repomd file, cannot initialize source") );
00434         }
00435 
00436         //---------------------------------
00437         // files mentioned within repomd
00438 
00439         try
00440         {
00441           // now put other and filelist data to structures for easier find
00442           map<NVRA, YUMFileListData_Ptr> files_data;
00443           map<NVRA, YUMOtherData_Ptr> other_data;
00444           for (std::list<YUMRepomdData_Ptr>::const_iterator it
00445                   = repo_files.begin();
00446               it != repo_files.end();
00447               it++)
00448           {
00449             Pathname filename = metadataRoot() + (*it)->location;
00450             DBG << "Reading ifgz file " << filename << endl;
00451             ifgzstream st( filename.asString().c_str() );
00452 
00453             YUMFileListParser filelist ( st, "" );
00454             for (; ! filelist.atEnd(); ++filelist)
00455             {
00456               if (*filelist == NULL) continue;  // skip incompatible archs
00457                 NVRA nvra( (*filelist)->name,
00458                            Edition( (*filelist)->ver, (*filelist)->rel, str::strtonum<int>( (*filelist)->epoch ) ),
00459                            Arch ( (*filelist)->arch ) );
00460                 files_data[nvra] = *filelist;
00461             }
00462             if (filelist.errorStatus())
00463               ZYPP_THROW(Exception(filelist.errorStatus()->msg()));
00464           }
00465 
00466 #if 0   // don't parse 'other.xml' (#159316)
00467 
00468           for (std::list<YUMRepomdData_Ptr>::const_iterator it
00469                   = repo_other.begin();
00470               it != repo_other.end();
00471               it++)
00472           {
00473             Pathname filename = cacheExists()
00474               ? _cache_dir + (*it)->location
00475               : provideFile(_path + (*it)->location);
00476             if (!cacheExists())
00477             {
00478               if (! checkCheckSum(filename, (*it)->checksumType, (*it)->checksum))
00479               {
00480                 ZYPP_THROW(Exception(N_("Failed check for the metadata file check sum")));
00481               }
00482             }
00483             _metadata_files.push_back((*it)->location);
00484             DBG << "Reading file " << filename << endl;
00485 
00486             ifgzstream st ( filename.asString().c_str() );
00487             YUMOtherParser other(st, "");
00488             for (;
00489                   ! other.atEnd();
00490                   ++other)
00491             {
00492                 if (*other == NULL) continue;   // skip incompatible archs
00493                 Arch arch;
00494                 if (!(*other)->arch.empty())
00495                   arch = Arch((*other)->arch);
00496 
00497                 NVRA nvra( (*other)->name,
00498                            Edition( (*other)->ver, (*other)->rel, str::strtonum<int>( (*other)->epoch ) ),
00499                            arch );
00500                 other_data[nvra] = *other;
00501             }
00502             if (other.errorStatus())
00503               throw *other.errorStatus();
00504         }
00505 #endif
00506 
00507         // now read primary data, merge them with filelist and changelog
00508           for (std::list<YUMRepomdData_Ptr>::const_iterator it = repo_primary.begin(); it != repo_primary.end(); it++)
00509           {
00510             Pathname filename = metadataRoot() + (*it)->location;
00511             DBG << "Reading file " << filename << endl;
00512             ifgzstream st ( filename.asString().c_str() );
00513             YUMPrimaryParser prim(st, "");
00514             for (; !prim.atEnd(); ++prim)
00515             {
00516               if (*prim == NULL) continue;      // incompatible arch detected during parsing
00517 
00518               Arch arch;
00519               if (!(*prim)->arch.empty())
00520                 arch = Arch((*prim)->arch);
00521 
00522               NVRA nvra( (*prim)->name,
00523                            Edition( (*prim)->ver, (*prim)->rel, str::strtonum<int>( (*prim)->epoch ) ),
00524                            arch );
00525               map<NVRA, YUMOtherData_Ptr>::iterator found_other = other_data.find( nvra );
00526               map<NVRA, YUMFileListData_Ptr>::iterator found_files = files_data.find( nvra );
00527 
00528               YUMFileListData filelist_empty;
00529               YUMOtherData other_empty;
00530               ResImplTraits<YUMPackageImpl>::Ptr impl;
00531               Package::Ptr p = createPackage( source_r, **prim, found_files != files_data.end()
00532                     ? *(found_files->second)
00533                     : filelist_empty,
00534                   found_other != other_data.end()
00535                     ? *(found_other->second)
00536                      : other_empty,
00537                   impl
00538                 );
00539                 ImplAndPackage iap = { impl, p };
00540                 _package_impl[nvra] = iap;
00541 //                MIL << "inserting package "<< p->name() << std::endl;
00542                 _store.insert (p);
00543              }
00544              if (prim.errorStatus())
00545               ZYPP_THROW(Exception(prim.errorStatus()->msg()));
00546            }
00547         }
00548         catch (...)
00549         {
00550          ERR << "Cannot read package information" << endl;
00551         }
00552 
00553         //---------------------------------
00554         // groups
00555         try
00556         {
00557           for (std::list<YUMRepomdData_Ptr>::const_iterator it = repo_group.begin();
00558                 it != repo_group.end();
00559                 it++)
00560           {
00561             Pathname filename = metadataRoot() + (*it)->location;
00562             DBG << "Reading file " << filename << endl;
00563             ifgzstream st ( filename.asString().c_str() );
00564             YUMGroupParser group(st, "");
00565             for (; !group.atEnd(); ++group)
00566             {
00567               Selection::Ptr p = createGroup( source_r, **group );
00568               _store.insert (p);
00569             }
00570             if (group.errorStatus())
00571               ZYPP_THROW(Exception(group.errorStatus()->msg()));
00572           }
00573         }
00574         catch (...)
00575         {
00576           ERR << "Cannot read package groups information" << endl;
00577         }
00578 
00579         //---------------------------------
00580         // patterns
00581 
00582         try
00583         {
00584           for (std::list<YUMRepomdData_Ptr>::const_iterator it = repo_pattern.begin();
00585                it != repo_pattern.end(); it++)
00586           {
00587             Pathname filename = metadataRoot() + (*it)->location;
00588 
00589             DBG << "Reading file " << filename << endl;
00590             ifgzstream st ( filename.asString().c_str() );
00591             YUMPatternParser pattern(st, "");
00592             for (; !pattern.atEnd(); ++pattern)
00593             {
00594               Pattern::Ptr p = createPattern( source_r, **pattern );
00595               _store.insert (p);
00596             }
00597             if (pattern.errorStatus())
00598               ZYPP_THROW(Exception(pattern.errorStatus()->msg()));
00599           }
00600         }
00601         catch (...) {
00602           ERR << "Cannot read installation patterns information" << endl;
00603         }
00604 
00605         //---------------------------------
00606         // products
00607         try
00608         {
00609           for (std::list<YUMRepomdData_Ptr>::const_iterator it = repo_product.begin();
00610             it != repo_product.end();
00611             it++)
00612           {
00613             Pathname filename = metadataRoot() + (*it)->location;
00614             ifgzstream st ( filename.asString().c_str() );
00615             YUMProductParser product(st, "");
00616             for (; !product.atEnd(); ++product)
00617             {
00618               Product::Ptr p = createProduct( source_r, **product );
00619               _store.insert (p);
00620             }
00621             if (product.errorStatus())
00622               ZYPP_THROW(Exception(product.errorStatus()->msg()));
00623           }
00624         }
00625         catch (...) {
00626         ERR << "Cannot read products information" << endl;
00627         }
00628 
00629         //---------------------------------
00630         // patches, first the patches.xml index
00631         try
00632         {
00633           std::list<std::string> patch_files;
00634           for (std::list<YUMRepomdData_Ptr>::const_iterator it = repo_patches.begin();
00635               it != repo_patches.end();
00636               it++)
00637           {
00638             Pathname filename = metadataRoot() + (*it)->location;
00639 
00640             DBG << "Reading file " << filename << endl;
00641             ifgzstream st ( filename.asString().c_str() );
00642             YUMPatchesParser patch(st, "");
00643 
00644             for (; !patch.atEnd(); ++patch)
00645             {
00646               string filename = (*patch)->location;
00647               patch_files.push_back(filename);
00648             }
00649 
00650             if (patch.errorStatus())
00651               ZYPP_THROW(Exception(patch.errorStatus()->msg()));
00652            }
00653 
00654             //---------------------------------
00655             // now the individual patch files
00656 
00657            for (std::list<std::string>::const_iterator it = patch_files.begin();
00658               it != patch_files.end();
00659               it++)
00660            {
00661              Pathname filename = metadataRoot() + *it;
00662                 DBG << "Reading file " << filename << endl;
00663                 ifgzstream st ( filename.asString().c_str() );
00664                 YUMPatchParser ptch(st, "");
00665                 for(;
00666                         !ptch.atEnd();
00667                         ++ptch)
00668                 {
00669                       Patch::Ptr p = createPatch(
00670                         source_r,
00671                         **ptch
00672                       );
00673                       _store.insert (p);
00674                       Patch::AtomList atoms = p->atoms();
00675                       for (Patch::AtomList::iterator at = atoms.begin();
00676                           at != atoms.end();
00677                           at++)
00678                       {
00679                         _store.insert (*at);
00680                       }
00681                 }
00682                 if (ptch.errorStatus())
00683                   ZYPP_THROW(Exception(ptch.errorStatus()->msg()));
00684            }
00685          }
00686         catch (...)
00687         {
00688             ERR << "Cannot read patch metadata" << endl;
00689         }
00690 
00691         report->finishData( url(), CreateSourceReport::NO_ERROR, "" );
00692       }
00693 
00694 
00695   Package::Ptr YUMSourceImpl::createPackage(
00696     Source_Ref source_r,
00697     const zypp::parser::yum::YUMPrimaryData & parsed,
00698     const zypp::parser::yum::YUMFileListData & filelist,
00699     const zypp::parser::yum::YUMOtherData & other,
00700     ResImplTraits<YUMPackageImpl>::Ptr & impl
00701   )
00702   {
00703     try
00704     {
00705       impl = new YUMPackageImpl( source_r, parsed, filelist, other );
00706 
00707       Dependencies deps( createDependencies( parsed, ResTraits<Package>::kind ) );
00708 
00709       CapFactory f;
00710 
00711         for (std::list<FileData>::const_iterator it = filelist.files.begin();
00712              it != filelist.files.end();
00713              it++)
00714         {
00715             deps[Dep::PROVIDES].insert( f.parse( ResTraits<Package>::kind, it->name ) );
00716         }
00717 
00718       Arch arch;
00719       if (!parsed.arch.empty())
00720         arch = Arch(parsed.arch);
00721 
00722       // Collect basic Resolvable data
00723       NVRAD dataCollect( parsed.name,
00724                          Edition( parsed.ver, parsed.rel, parsed.epoch ),
00725                          arch,
00726                          deps
00727                        );
00728       Package::Ptr package = detail::makeResolvableFromImpl(
00729         dataCollect, impl
00730       );
00731       return package;
00732     }
00733     catch (const Exception & excpt_r)
00734     {
00735       ZYPP_CAUGHT(excpt_r);
00736       ZYPP_THROW(Exception("Cannot create package object"));
00737     }
00738     return 0L;
00739   }
00740 
00741   Atom::Ptr YUMSourceImpl::augmentPackage(
00742     Source_Ref source_r,
00743     const zypp::parser::yum::YUMPatchPackage & parsed
00744   )
00745   {
00746     try
00747     {
00748         Arch arch;
00749         if (!parsed.arch.empty())
00750           arch = Arch( parsed.arch );
00751 
00752         Edition edition( parsed.ver, parsed.rel, parsed.epoch );
00753         NVRA nvra( parsed.name,
00754                    edition,
00755                    arch );
00756 
00757         DBG << "augmentPackage(" << nvra << ")" << endl;
00758 
00759         // create Atom
00760         CapFactory f;
00761         Dependencies deps = createDependencies( parsed, ResTraits<Package>::kind );
00762 //        deps[Dep::REQUIRES].insert( f.parse( ResTraits<Package>::kind, parsed.name, Rel::EQ, edition ) );
00763         NVRAD atomdata( nvra, deps );
00764         ResImplTraits<YUMAtomImpl>::Ptr atomimpl = new YUMAtomImpl( source_r );
00765         Atom::Ptr atom = detail::makeResolvableFromImpl( atomdata, atomimpl );
00766 
00767         //source_r
00768         PackageImplMapT::const_iterator it = _package_impl.find( nvra );
00769         if (it == _package_impl.end()) {
00770             WAR << "Patch augments non-existant package " << nvra << endl;
00771         }
00772         else
00773         {
00774           ResImplTraits<YUMPackageImpl>::Ptr impl = it->second.impl;
00775 
00776           if (!parsed.location.empty()) {
00777               impl->_location = parsed.location;
00778               impl->_mediaNumber = str::strtonum<unsigned>( parsed.media );
00779               impl->_checksum = CheckSum(parsed.checksumType, parsed.checksum);
00780           }
00781           impl->_install_only = parsed.installOnly;
00782 
00783           //DBG << "Inserting patch RPMs" << endl;
00784           impl->_patch_rpms = std::list<YUMPackageImpl::PatchRpm>();
00785           for ( std::list<YUMPatchRpm>::const_iterator it = parsed.patchRpms.begin();
00786                 it != parsed.patchRpms.end(); ++it )
00787             {
00788               YUMPackageImpl::PatchRpm patch_rpm;
00789 
00790               patch_rpm.location( source::OnMediaLocation()
00791                                   .medianr( str::strtonum<unsigned>( it->media ) )
00792                                   .filename( it->location )
00793                                   .checksum( CheckSum( it->checksumType, it->checksum ) )
00794                                   .downloadsize( str::strtonum<ByteCount::SizeType>( it->downloadsize ) ) );
00795 
00796               for ( std::list<YUMPatchBaseVersion>::const_iterator bvit = it->baseVersions.begin();
00797                     bvit != it->baseVersions.end(); ++bvit )
00798                 {
00799                   patch_rpm.baseversion( Edition( bvit->edition.ver,
00800                                                   bvit->edition.rel,
00801                                                   bvit->edition.epoch ) );
00802                 }
00803 
00804               patch_rpm.buildtime( str::strtonum<Date::ValueType>( it->buildtime ) );
00805 
00806              impl->_patch_rpms.push_back( patch_rpm );
00807             }
00808 
00809           //DBG << "Inserting delta RPMs" << endl;
00810           impl->_delta_rpms = std::list<YUMPackageImpl::DeltaRpm>();
00811           for ( std::list<YUMDeltaRpm>::const_iterator it = parsed.deltaRpms.begin();
00812                 it != parsed.deltaRpms.end(); ++it )
00813             {
00814               YUMPackageImpl::DeltaRpm delta_rpm;
00815 
00816               delta_rpm.location( source::OnMediaLocation()
00817                                   .medianr( str::strtonum<unsigned>( it->media ) )
00818                                   .filename( it->location )
00819                                   .checksum( CheckSum( it->checksumType, it->checksum ) )
00820                                   .downloadsize( str::strtonum<ByteCount::SizeType>( it->downloadsize ) ) );
00821 
00822               const YUMDeltaBaseVersion & ybv( it->baseVersion );
00823               delta_rpm.baseversion( YUMPackageImpl::DeltaRpm::BaseVersion()
00824                                      .edition( Edition( ybv.edition.ver,
00825                                                         ybv.edition.rel,
00826                                                         ybv.edition.epoch ) )
00827                                      .buildtime( str::strtonum<Date::ValueType>( ybv.buildtime ) )
00828                                      .checksum( CheckSum::md5( ybv.md5sum ) )
00829                                      .sequenceinfo( ybv.sequence_info )
00830                                      );
00831 
00832               delta_rpm.buildtime( str::strtonum<Date::ValueType>( it->buildtime ) );
00833 
00834               impl->_delta_rpms.push_back( delta_rpm );
00835             }
00836         }
00837         return atom;
00838     }
00839     catch (const Exception & excpt_r)
00840     {
00841       ZYPP_CAUGHT(excpt_r);
00842       ZYPP_THROW(Exception("Cannot create augmented package object"));
00843     }
00844     return 0L;
00845   }
00846 
00847   Selection::Ptr YUMSourceImpl::createGroup(
00848     Source_Ref source_r,
00849     const zypp::parser::yum::YUMGroupData & parsed
00850   )
00851   {
00852     try
00853     {
00854       ResImplTraits<YUMGroupImpl>::Ptr impl(new YUMGroupImpl(source_r, parsed));
00855       // Collect basic Resolvable data
00856       NVRAD dataCollect( parsed.groupId,
00857                          Edition::noedition,                    // group has just a name,
00858                          Arch_noarch,                           //   pattern has edition & arch
00859                          createGroupDependencies(parsed));
00860       Selection::Ptr group = detail::makeResolvableFromImpl(
00861         dataCollect, impl
00862       );
00863       return group;
00864     }
00865     catch (const Exception & excpt_r)
00866     {
00867       ZYPP_CAUGHT(excpt_r);
00868       ZYPP_THROW(Exception("Cannot create package group object"));
00869     }
00870     return 0L;
00871   }
00872 
00873   Pattern::Ptr YUMSourceImpl::createPattern(
00874     Source_Ref source_r,
00875     const zypp::parser::yum::YUMPatternData & parsed
00876   )
00877   {
00878     try
00879     {
00880       ResImplTraits<YUMPatternImpl>::Ptr impl(new YUMPatternImpl(source_r, parsed));
00881       // Collect basic Resolvable data
00882       Arch arch;
00883       if (!parsed.arch.empty())
00884         arch = Arch(parsed.arch);
00885 
00886       NVRAD dataCollect( parsed.name,
00887                          Edition( parsed.ver, parsed.rel, parsed.epoch ),
00888                          arch,
00889                          createDependencies(parsed, ResTraits<Pattern>::kind));
00890       Pattern::Ptr pattern = detail::makeResolvableFromImpl(
00891         dataCollect, impl
00892       );
00893       return pattern;
00894     }
00895     catch (const Exception & excpt_r)
00896     {
00897       ZYPP_CAUGHT(excpt_r);
00898       ZYPP_THROW(Exception("Cannot create installation pattern object"));
00899     }
00900     return 0L;
00901   }
00902 
00903   Message::Ptr YUMSourceImpl::createMessage(
00904     Source_Ref source_r,
00905     const zypp::parser::yum::YUMPatchMessage & parsed,
00906     Patch::constPtr patch
00907   )
00908   {
00909     try
00910     {
00911       ResImplTraits<YUMMessageImpl>::Ptr impl(new YUMMessageImpl(source_r, parsed, patch));
00912       Arch arch;
00913       if (!parsed.arch.empty())
00914         arch = Arch(parsed.arch);
00915       // Collect basic Resolvable data
00916       NVRAD dataCollect( parsed.name,
00917                               Edition( parsed.ver, parsed.rel, parsed.epoch ),
00918                               arch,
00919                               createDependencies(parsed,
00920                                                   ResTraits<Message>::kind)
00921                             );
00922       Message::Ptr message = detail::makeResolvableFromImpl(
00923         dataCollect, impl
00924       );
00925       return message;
00926     }
00927     catch (const Exception & excpt_r)
00928     {
00929       ZYPP_CAUGHT(excpt_r);
00930       ZYPP_THROW(Exception("Cannot create message object"));
00931     }
00932     return 0L;
00933   }
00934 
00935   Script::Ptr YUMSourceImpl::createScript(
00936     Source_Ref source_r,
00937     const zypp::parser::yum::YUMPatchScript & parsed
00938   )
00939   {
00940     try
00941     {
00942       ResImplTraits<YUMScriptImpl>::Ptr impl(new YUMScriptImpl(source_r, parsed));
00943       Arch arch;
00944       if (!parsed.arch.empty())
00945         arch = Arch(parsed.arch);
00946       // Collect basic Resolvable data
00947       NVRAD dataCollect( parsed.name,
00948                       Edition( parsed.ver, parsed.rel, parsed.epoch ),
00949                       arch,
00950                       createDependencies(parsed,
00951                                           ResTraits<Script>::kind)
00952                     );
00953       Script::Ptr script = detail::makeResolvableFromImpl(
00954         dataCollect, impl
00955       );
00956       return script;
00957     }
00958     catch (const Exception & excpt_r)
00959     {
00960       ZYPP_CAUGHT(excpt_r);
00961       ZYPP_THROW(Exception("Cannot create script object"));
00962     }
00963     return 0L;
00964   }
00965 
00966   Product::Ptr YUMSourceImpl::createProduct(
00967     Source_Ref source_r,
00968     const zypp::parser::yum::YUMProductData & parsed
00969   )
00970   {
00971     try
00972     {
00973       ResImplTraits<YUMProductImpl>::Ptr impl(new YUMProductImpl(source_r, parsed));
00974 
00975             // Collect basic Resolvable data
00976       Arch arch;
00977       if (!parsed.arch.empty())
00978         arch = Arch(parsed.arch);
00979       NVRAD dataCollect( parsed.name,
00980                               Edition( parsed.ver, parsed.rel, parsed.epoch ),
00981                               arch,
00982                               createDependencies(parsed,
00983                                                   ResTraits<Product>::kind)
00984                             );
00985       Product::Ptr product = detail::makeResolvableFromImpl(
00986         dataCollect, impl
00987       );
00988       return product;
00989     }
00990     catch (const Exception & excpt_r)
00991     {
00992       ZYPP_CAUGHT(excpt_r);
00993       ZYPP_THROW(Exception("Cannot create product object"));
00994     }
00995     return 0L;
00996   }
00997 
00998   Patch::Ptr YUMSourceImpl::createPatch(
00999     Source_Ref source_r,
01000     const zypp::parser::yum::YUMPatchData & parsed
01001   )
01002   {
01003     try
01004     {
01005       ResImplTraits<YUMPatchImpl>::Ptr impl(new YUMPatchImpl(source_r, parsed, *this));
01006 
01007       Arch arch;
01008       if (!parsed.arch.empty())
01009         arch = Arch(parsed.arch);
01010 
01011       // Collect basic Resolvable data
01012       NVRAD dataCollect( parsed.name,
01013                       Edition( parsed.ver, parsed.rel, parsed.epoch ),
01014                       arch,
01015                       createDependencies( parsed,
01016                                           ResTraits<Patch>::kind)
01017                     );
01018       Patch::Ptr patch = detail::makeResolvableFromImpl(
01019         dataCollect, impl
01020       );
01021         // now process the atoms
01022         CapFactory _f;
01023         Capability cap( _f.parse(
01024           Patch::TraitsType::kind,
01025           parsed.name,
01026           Rel::EQ,
01027           Edition(parsed.ver, parsed.rel, parsed.epoch)
01028           ));
01029 
01030         // maps name to parser data in order to find 'best' architectureC
01031         typedef std::map<std::string, shared_ptr<YUMPatchPackage> > PkgAtomsMap;
01032         PkgAtomsMap pkg_atoms;
01033 
01034         for (std::list<shared_ptr<YUMPatchAtom> >::const_iterator it
01035                                         = parsed.atoms.begin();
01036              it != parsed.atoms.end();
01037              it++)
01038         {
01039           switch ((*it)->atomType())
01040           {
01041             // for packages, try to find best architecture for name-version-release first (#168840)
01042             // we can't use the name alone as there might be different editions for the same name
01043             // with different architecture.
01044             // So we only choose the best architecture if name-version-edition matches (#170098)
01045 
01046             case YUMPatchAtom::Package: {
01047               shared_ptr<YUMPatchPackage> package_data
01048                 = dynamic_pointer_cast<YUMPatchPackage>(*it);
01049               string atomkey( package_data->name + "-" + package_data->epoch + ":" + package_data->ver + "-" + package_data->rel );
01050 
01051               // check if atomkey is already known
01052               PkgAtomsMap::iterator pa_pos = pkg_atoms.find( atomkey );
01053               if (pa_pos != pkg_atoms.end()) {
01054                 try {
01055                   Arch oldarch, newarch;
01056                   if (!(pa_pos->second->arch.empty())) oldarch = Arch( pa_pos->second->arch );
01057                   if (!(package_data->arch.empty())) newarch = Arch( package_data->arch );
01058                   if (newarch.compatibleWith( getZYpp()->architecture() ) ) {                   // new one is compatible (if not, we don't care)
01059 
01060                     if (!oldarch.compatibleWith( getZYpp()->architecture() )                    // old one is not compatible
01061                         || oldarch.compare( newarch ) < 0)                                      //  or compatible but worse
01062                     {
01063                       pa_pos->second = package_data;                            // new one is it !
01064                     }
01065                   }
01066                 }
01067                 catch( const Exception & excpt_r ) {
01068                     ZYPP_CAUGHT( excpt_r );
01069                     ERR << "Package " << package_data->name << " in patch's atomlist has bad architecture '" << package_data->arch << "'" << endl;
01070                 }
01071               }
01072               else {
01073                 pkg_atoms[atomkey] = package_data;                                      // first occurence of this atomkey
01074               }
01075               break;
01076             }
01077             case YUMPatchAtom::Message: {
01078               shared_ptr<YUMPatchMessage> message_data
01079                 = dynamic_pointer_cast<YUMPatchMessage>(*it);
01080               Message::Ptr message = createMessage(source_r, *message_data, patch);
01081               impl->_atoms.push_back(message);
01082               break;
01083             }
01084             case YUMPatchAtom::Script: {
01085               shared_ptr<YUMPatchScript> script_data
01086                 = dynamic_pointer_cast<YUMPatchScript>(*it);
01087               Script::Ptr script = createScript(source_r, *script_data);
01088               impl->_atoms.push_back(script);
01089               break;
01090             }
01091             default:
01092               ERR << "Unknown type of atom" << endl;
01093           }
01094 #if 0                                   // atoms require their patch, why ?
01095           for (Patch::AtomList::iterator it = impl->_atoms.begin();
01096                it != impl->_atoms.end();
01097                it++)
01098           {
01099             (*it)->injectRequires(cap);
01100           }
01101 #endif
01102         }
01103 
01104         for (PkgAtomsMap::const_iterator pa_pos = pkg_atoms.begin(); pa_pos != pkg_atoms.end(); ++pa_pos) {
01105           Atom::Ptr atom = augmentPackage( source_r, *(pa_pos->second) );
01106           impl->_atoms.push_back(atom);
01107         }
01108 
01109       return patch;
01110     }
01111     catch (const Exception & excpt_r)
01112     {
01113       ZYPP_CAUGHT(excpt_r);
01114       ZYPP_THROW(Exception("Cannot create patch object"));
01115     }
01116     return 0L;
01117   }
01118 
01119   Dependencies YUMSourceImpl::createDependencies(
01120     const zypp::parser::yum::YUMObjectData & parsed,
01121     const Resolvable::Kind my_kind
01122   )
01123   {
01124     Dependencies _deps;
01125     for (std::list<YUMDependency>::const_iterator it = parsed.provides.begin();
01126         it != parsed.provides.end();
01127         it++)
01128     {
01129       _deps[Dep::PROVIDES].insert(createCapability(*it, my_kind));
01130     }
01131 
01132     for (std::list<YUMDependency>::const_iterator it = parsed.conflicts.begin();
01133         it != parsed.conflicts.end();
01134         it++)
01135     {
01136       _deps[Dep::CONFLICTS].insert(createCapability(*it, my_kind));
01137     }
01138 
01139     for (std::list<YUMDependency>::const_iterator it = parsed.obsoletes.begin();
01140         it != parsed.obsoletes.end();
01141         it++)
01142     {
01143       _deps[Dep::OBSOLETES].insert(createCapability(*it, my_kind));
01144     }
01145 
01146     for (std::list<YUMDependency>::const_iterator it = parsed.freshens.begin();
01147         it != parsed.freshens.end();
01148         it++)
01149     {
01150       _deps[Dep::FRESHENS].insert(createCapability(*it, my_kind));
01151     }
01152 
01153     for (std::list<YUMDependency>::const_iterator it = parsed.recommends.begin();
01154         it != parsed.recommends.end();
01155         it++)
01156     {
01157       _deps[Dep::RECOMMENDS].insert(createCapability(*it, my_kind));
01158     }
01159 
01160     for (std::list<YUMDependency>::const_iterator it = parsed.suggests.begin();
01161         it != parsed.suggests.end();
01162         it++)
01163     {
01164       _deps[Dep::SUGGESTS].insert(createCapability(*it, my_kind));
01165     }
01166 
01167     for (std::list<YUMDependency>::const_iterator it = parsed.supplements.begin();
01168         it != parsed.supplements.end();
01169         it++)
01170     {
01171       _deps[Dep::SUPPLEMENTS].insert(createCapability(*it, my_kind));
01172     }
01173 
01174     for (std::list<YUMDependency>::const_iterator it = parsed.enhances.begin();
01175         it != parsed.enhances.end();
01176         it++)
01177     {
01178       _deps[Dep::ENHANCES].insert(createCapability(*it, my_kind));
01179     }
01180 
01181     for (std::list<YUMDependency>::const_iterator it = parsed.prerequires.begin();
01182          it != parsed.prerequires.end();
01183          it++)
01184     {
01185         _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01186     }
01187 
01188     for (std::list<YUMDependency>::const_iterator it = parsed.requires.begin();
01189         it != parsed.requires.end();
01190         it++)
01191     {
01192       if (it->pre == "1")
01193         _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01194       else
01195         _deps[Dep::REQUIRES].insert(createCapability(*it, my_kind));
01196     }
01197 
01198     return _deps;
01199   }
01200 
01201   Dependencies YUMSourceImpl::createGroupDependencies(
01202     const zypp::parser::yum::YUMGroupData & parsed
01203   )
01204   {
01205     Dependencies _deps;
01206 
01207     for (std::list<PackageReq>::const_iterator it = parsed.packageList.begin();
01208       it != parsed.packageList.end();
01209       it++)
01210     {
01211       Dep _dep_kind = Dep::REQUIRES;
01212       if (it->type == "mandatory" || it->type == "")
01213       {
01214         _dep_kind = Dep::REQUIRES;
01215       }
01216       else if (it->type == "default")
01217       {
01218         _dep_kind = Dep::RECOMMENDS;
01219       }
01220       else if (it->type == "optional")
01221       {
01222         _dep_kind = Dep::SUGGESTS;
01223       }
01224       _deps[_dep_kind].insert(createCapability(YUMDependency(
01225       "",
01226       it->name,
01227       "EQ",
01228       it->epoch,
01229       it->ver,
01230       it->rel,
01231       ""
01232         ),
01233         ResTraits<Package>::kind));
01234     }
01235     for (std::list<MetaPkg>::const_iterator it = parsed.grouplist.begin();
01236       it != parsed.grouplist.end();
01237       it++)
01238     {
01239       Dep _dep_kind = Dep::REQUIRES;
01240       if (it->type == "mandatory" || it->type == "")
01241       {
01242         _dep_kind = Dep::REQUIRES;
01243       }
01244       else if (it->type == "default")
01245       {
01246         _dep_kind = Dep::RECOMMENDS;
01247       }
01248       else if (it->type == "optional")
01249       {
01250         _dep_kind = Dep::SUGGESTS;
01251       }
01252       _deps[_dep_kind].insert(createCapability(YUMDependency(
01253       "",
01254       it->name,
01255       "",
01256       "",
01257       "",
01258       "",
01259       ""
01260         ),
01261         ResTraits<Selection>::kind));
01262     }
01263     return _deps;
01264   }
01265 
01266   Capability YUMSourceImpl::createCapability(const YUMDependency & dep,
01267                 const Resolvable::Kind & my_kind)
01268   {
01269     CapFactory _f;
01270     Resolvable::Kind _kind = dep.kind == "" ? my_kind : Resolvable::Kind(dep.kind);
01271     Capability cap;
01272     if ( ! dep.isEncoded() )
01273     {
01274       cap = _f.parse(
01275       _kind,
01276       dep.name,
01277       Rel(dep.flags),
01278       Edition(dep.ver, dep.rel, dep.epoch)
01279       );
01280     }
01281     else
01282     {
01283       cap = _f.parse( _kind, dep.encoded );
01284     }
01285     return cap;
01286   }
01287 
01288 
01289 
01290 
01291       bool YUMSourceImpl::checkCheckSum (const Pathname & filename, std::string csum_type, const std::string & csum)
01292       {
01293         MIL << "Checking checksum for " << filename << " as type: " << csum_type << "; value: " << csum << endl;
01294         if (str::toLower(csum_type) == "sha")
01295         {
01296           if (csum.size() == 40)
01297             csum_type = "sha1";
01298           else if (csum.size() == 64)
01299             csum_type = "sha256";
01300           //DBG << "Checksum size is " << csum.size() << ", checksum type set to " << csum_type << endl;
01301         }
01302         ifstream st(filename.asString().c_str());
01303         std::string dig = Digest::digest (csum_type, st, 4096);
01304         if (dig == "")
01305         {
01306           ERR << "Cannot compute the checksum" << endl;
01307           return false;
01308         }
01309         dig = str::toLower (dig);
01310         bool ret = (dig == str::toLower(csum));
01311         if (ret)
01312         {
01313           //MIL << "Checksums are the same" << endl;
01314           return true;
01315         }
01316         else
01317         {
01318           WAR << "Checksum missmatch: metadata: " << csum << "; real: " << dig << endl;
01319           return false;
01320         }
01321         return false;
01322       }
01323 
01324     } // namespace yum
01326   } // namespace source
01329 } // namespace zypp

Generated on Thu Sep 14 15:38:50 2006 for zypp by  doxygen 1.4.6