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