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 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
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
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")
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
00183
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
00193 if ((*repomd)->type == "patches")
00194 {
00195
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
00221 if (! checkCheckSum( patch_dst, (*patch)->checksumType, (*patch)->checksum))
00222 ZYPP_THROW(Exception( (*repomd)->location + " " + N_(" fails checksum verification.") ));
00223 }
00224 }
00225 }
00226
00227
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
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
00253
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 {
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
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
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
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
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
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
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
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")
00427 ERR << "Unknown type of repo file: " << (*repomd)->type << endl;
00428 }
00429 }
00430 catch( const Exception & excpt_r )
00431 {
00432 ZYPP_CAUGHT( excpt_r );
00433 ZYPP_THROW( Exception("Cannot read repomd file, cannot initialize source") );
00434 }
00435
00436
00437
00438
00439 try
00440 {
00441
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;
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;
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
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;
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
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
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
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
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
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
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
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
00760 CapFactory f;
00761 Dependencies deps = createDependencies( parsed, ResTraits<Package>::kind );
00762
00763 NVRAD atomdata( nvra, deps );
00764 ResImplTraits<YUMAtomImpl>::Ptr atomimpl = new YUMAtomImpl( source_r );
00765 Atom::Ptr atom = detail::makeResolvableFromImpl( atomdata, atomimpl );
00766
00767
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
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 std::list<YUMPackageImpl::BaseVersion> bv_list;
00789 for (std::list<YUMBaseVersion>::const_iterator bvit = it->baseVersions.begin();
00790 bvit != it->baseVersions.end(); ++bvit)
00791 {
00792 YUMPackageImpl::BaseVersion bv(
00793 Edition (bvit->ver, bvit->rel, bvit->epoch),
00794 CheckSum("md5", bvit->md5sum),
00795 strtol(bvit->buildtime.c_str(), 0, 10)
00796 );
00797 bv_list.push_back(bv);
00798 }
00799 YUMPackageImpl::PatchRpm patch_rpm(
00800 Arch(it->arch),
00801 Pathname(it->location),
00802 strtol(it->downloadsize.c_str(), 0, 10),
00803 CheckSum (it->checksumType, it->checksum),
00804 strtol(it->buildtime.c_str(), 0, 10),
00805 bv_list,
00806 strtol(it->media.c_str(), 0, 10)
00807 );
00808 impl->_patch_rpms.push_back(patch_rpm);
00809 }
00810
00811
00812
00813 impl->_delta_rpms = std::list<YUMPackageImpl::DeltaRpm>();
00814 for (std::list<YUMDeltaRpm>::const_iterator it = parsed.deltaRpms.begin();
00815 it != parsed.deltaRpms.end(); ++it)
00816 {
00817 YUMPackageImpl::DeltaRpm delta_rpm(
00818 Arch(it->arch),
00819 Pathname(it->location),
00820 strtol(it->downloadsize.c_str(), 0, 10),
00821 CheckSum (it->checksumType, it->checksum),
00822 strtol(it->buildtime.c_str(), 0, 10),
00823 YUMPackageImpl::BaseVersion(
00824 Edition (it->baseVersion.ver, it->baseVersion.rel, it->baseVersion.epoch),
00825 CheckSum("md5", it->baseVersion.md5sum),
00826 strtol(it->baseVersion.buildtime.c_str(), 0, 10)
00827 ),
00828 strtol(it->media.c_str(), 0, 10)
00829 );
00830 impl->_delta_rpms.push_back(delta_rpm);
00831 }
00832 }
00833 return atom;
00834 }
00835 catch (const Exception & excpt_r)
00836 {
00837 ZYPP_CAUGHT(excpt_r);
00838 ZYPP_THROW(Exception("Cannot create augmented package object"));
00839 }
00840 return 0L;
00841 }
00842
00843 Selection::Ptr YUMSourceImpl::createGroup(
00844 Source_Ref source_r,
00845 const zypp::parser::yum::YUMGroupData & parsed
00846 )
00847 {
00848 try
00849 {
00850 ResImplTraits<YUMGroupImpl>::Ptr impl(new YUMGroupImpl(source_r, parsed));
00851
00852 NVRAD dataCollect( parsed.groupId,
00853 Edition::noedition,
00854 Arch_noarch,
00855 createGroupDependencies(parsed));
00856 Selection::Ptr group = detail::makeResolvableFromImpl(
00857 dataCollect, impl
00858 );
00859 return group;
00860 }
00861 catch (const Exception & excpt_r)
00862 {
00863 ZYPP_CAUGHT(excpt_r);
00864 ZYPP_THROW(Exception("Cannot create package group object"));
00865 }
00866 return 0L;
00867 }
00868
00869 Pattern::Ptr YUMSourceImpl::createPattern(
00870 Source_Ref source_r,
00871 const zypp::parser::yum::YUMPatternData & parsed
00872 )
00873 {
00874 try
00875 {
00876 ResImplTraits<YUMPatternImpl>::Ptr impl(new YUMPatternImpl(source_r, parsed));
00877
00878 Arch arch;
00879 if (!parsed.arch.empty())
00880 arch = Arch(parsed.arch);
00881
00882 NVRAD dataCollect( parsed.name,
00883 Edition( parsed.ver, parsed.rel, parsed.epoch ),
00884 arch,
00885 createDependencies(parsed, ResTraits<Pattern>::kind));
00886 Pattern::Ptr pattern = detail::makeResolvableFromImpl(
00887 dataCollect, impl
00888 );
00889 return pattern;
00890 }
00891 catch (const Exception & excpt_r)
00892 {
00893 ZYPP_CAUGHT(excpt_r);
00894 ZYPP_THROW(Exception("Cannot create installation pattern object"));
00895 }
00896 return 0L;
00897 }
00898
00899 Message::Ptr YUMSourceImpl::createMessage(
00900 Source_Ref source_r,
00901 const zypp::parser::yum::YUMPatchMessage & parsed,
00902 Patch::constPtr patch
00903 )
00904 {
00905 try
00906 {
00907 ResImplTraits<YUMMessageImpl>::Ptr impl(new YUMMessageImpl(source_r, parsed, patch));
00908 Arch arch;
00909 if (!parsed.arch.empty())
00910 arch = Arch(parsed.arch);
00911
00912 NVRAD dataCollect( parsed.name,
00913 Edition( parsed.ver, parsed.rel, parsed.epoch ),
00914 arch,
00915 createDependencies(parsed,
00916 ResTraits<Message>::kind)
00917 );
00918 Message::Ptr message = detail::makeResolvableFromImpl(
00919 dataCollect, impl
00920 );
00921 return message;
00922 }
00923 catch (const Exception & excpt_r)
00924 {
00925 ZYPP_CAUGHT(excpt_r);
00926 ZYPP_THROW(Exception("Cannot create message object"));
00927 }
00928 return 0L;
00929 }
00930
00931 Script::Ptr YUMSourceImpl::createScript(
00932 Source_Ref source_r,
00933 const zypp::parser::yum::YUMPatchScript & parsed
00934 )
00935 {
00936 try
00937 {
00938 ResImplTraits<YUMScriptImpl>::Ptr impl(new YUMScriptImpl(source_r, parsed));
00939 Arch arch;
00940 if (!parsed.arch.empty())
00941 arch = Arch(parsed.arch);
00942
00943 NVRAD dataCollect( parsed.name,
00944 Edition( parsed.ver, parsed.rel, parsed.epoch ),
00945 arch,
00946 createDependencies(parsed,
00947 ResTraits<Script>::kind)
00948 );
00949 Script::Ptr script = detail::makeResolvableFromImpl(
00950 dataCollect, impl
00951 );
00952 return script;
00953 }
00954 catch (const Exception & excpt_r)
00955 {
00956 ZYPP_CAUGHT(excpt_r);
00957 ZYPP_THROW(Exception("Cannot create script object"));
00958 }
00959 return 0L;
00960 }
00961
00962 Product::Ptr YUMSourceImpl::createProduct(
00963 Source_Ref source_r,
00964 const zypp::parser::yum::YUMProductData & parsed
00965 )
00966 {
00967 try
00968 {
00969 ResImplTraits<YUMProductImpl>::Ptr impl(new YUMProductImpl(source_r, parsed));
00970
00971
00972 Arch arch;
00973 if (!parsed.arch.empty())
00974 arch = Arch(parsed.arch);
00975 NVRAD dataCollect( parsed.name,
00976 Edition( parsed.ver, parsed.rel, parsed.epoch ),
00977 arch,
00978 createDependencies(parsed,
00979 ResTraits<Product>::kind)
00980 );
00981 Product::Ptr product = detail::makeResolvableFromImpl(
00982 dataCollect, impl
00983 );
00984 return product;
00985 }
00986 catch (const Exception & excpt_r)
00987 {
00988 ZYPP_CAUGHT(excpt_r);
00989 ZYPP_THROW(Exception("Cannot create product object"));
00990 }
00991 return 0L;
00992 }
00993
00994 Patch::Ptr YUMSourceImpl::createPatch(
00995 Source_Ref source_r,
00996 const zypp::parser::yum::YUMPatchData & parsed
00997 )
00998 {
00999 try
01000 {
01001 ResImplTraits<YUMPatchImpl>::Ptr impl(new YUMPatchImpl(source_r, parsed, *this));
01002
01003 Arch arch;
01004 if (!parsed.arch.empty())
01005 arch = Arch(parsed.arch);
01006
01007
01008 NVRAD dataCollect( parsed.name,
01009 Edition( parsed.ver, parsed.rel, parsed.epoch ),
01010 arch,
01011 createDependencies( parsed,
01012 ResTraits<Patch>::kind)
01013 );
01014 Patch::Ptr patch = detail::makeResolvableFromImpl(
01015 dataCollect, impl
01016 );
01017
01018 CapFactory _f;
01019 Capability cap( _f.parse(
01020 Patch::TraitsType::kind,
01021 parsed.name,
01022 Rel::EQ,
01023 Edition(parsed.ver, parsed.rel, parsed.epoch)
01024 ));
01025
01026
01027 typedef std::map<std::string, shared_ptr<YUMPatchPackage> > PkgAtomsMap;
01028 PkgAtomsMap pkg_atoms;
01029
01030 for (std::list<shared_ptr<YUMPatchAtom> >::const_iterator it
01031 = parsed.atoms.begin();
01032 it != parsed.atoms.end();
01033 it++)
01034 {
01035 switch ((*it)->atomType())
01036 {
01037
01038
01039
01040
01041
01042 case YUMPatchAtom::Package: {
01043 shared_ptr<YUMPatchPackage> package_data
01044 = dynamic_pointer_cast<YUMPatchPackage>(*it);
01045 string atomkey( package_data->name + "-" + package_data->epoch + ":" + package_data->ver + "-" + package_data->rel );
01046
01047
01048 PkgAtomsMap::iterator pa_pos = pkg_atoms.find( atomkey );
01049 if (pa_pos != pkg_atoms.end()) {
01050 try {
01051 Arch oldarch, newarch;
01052 if (!(pa_pos->second->arch.empty())) oldarch = Arch( pa_pos->second->arch );
01053 if (!(package_data->arch.empty())) newarch = Arch( package_data->arch );
01054 if (newarch.compatibleWith( getZYpp()->architecture() ) ) {
01055
01056 if (!oldarch.compatibleWith( getZYpp()->architecture() )
01057 || oldarch.compare( newarch ) < 0)
01058 {
01059 pa_pos->second = package_data;
01060 }
01061 }
01062 }
01063 catch( const Exception & excpt_r ) {
01064 ZYPP_CAUGHT( excpt_r );
01065 ERR << "Package " << package_data->name << " in patch's atomlist has bad architecture '" << package_data->arch << "'" << endl;
01066 }
01067 }
01068 else {
01069 pkg_atoms[atomkey] = package_data;
01070 }
01071 break;
01072 }
01073 case YUMPatchAtom::Message: {
01074 shared_ptr<YUMPatchMessage> message_data
01075 = dynamic_pointer_cast<YUMPatchMessage>(*it);
01076 Message::Ptr message = createMessage(source_r, *message_data, patch);
01077 impl->_atoms.push_back(message);
01078 break;
01079 }
01080 case YUMPatchAtom::Script: {
01081 shared_ptr<YUMPatchScript> script_data
01082 = dynamic_pointer_cast<YUMPatchScript>(*it);
01083 Script::Ptr script = createScript(source_r, *script_data);
01084 impl->_atoms.push_back(script);
01085 break;
01086 }
01087 default:
01088 ERR << "Unknown type of atom" << endl;
01089 }
01090 #if 0 // atoms require their patch, why ?
01091 for (Patch::AtomList::iterator it = impl->_atoms.begin();
01092 it != impl->_atoms.end();
01093 it++)
01094 {
01095 (*it)->injectRequires(cap);
01096 }
01097 #endif
01098 }
01099
01100 for (PkgAtomsMap::const_iterator pa_pos = pkg_atoms.begin(); pa_pos != pkg_atoms.end(); ++pa_pos) {
01101 Atom::Ptr atom = augmentPackage( source_r, *(pa_pos->second) );
01102 impl->_atoms.push_back(atom);
01103 }
01104
01105 return patch;
01106 }
01107 catch (const Exception & excpt_r)
01108 {
01109 ZYPP_CAUGHT(excpt_r);
01110 ZYPP_THROW(Exception("Cannot create patch object"));
01111 }
01112 return 0L;
01113 }
01114
01115 Dependencies YUMSourceImpl::createDependencies(
01116 const zypp::parser::yum::YUMObjectData & parsed,
01117 const Resolvable::Kind my_kind
01118 )
01119 {
01120 Dependencies _deps;
01121 for (std::list<YUMDependency>::const_iterator it = parsed.provides.begin();
01122 it != parsed.provides.end();
01123 it++)
01124 {
01125 _deps[Dep::PROVIDES].insert(createCapability(*it, my_kind));
01126 }
01127
01128 for (std::list<YUMDependency>::const_iterator it = parsed.conflicts.begin();
01129 it != parsed.conflicts.end();
01130 it++)
01131 {
01132 _deps[Dep::CONFLICTS].insert(createCapability(*it, my_kind));
01133 }
01134
01135 for (std::list<YUMDependency>::const_iterator it = parsed.obsoletes.begin();
01136 it != parsed.obsoletes.end();
01137 it++)
01138 {
01139 _deps[Dep::OBSOLETES].insert(createCapability(*it, my_kind));
01140 }
01141
01142 for (std::list<YUMDependency>::const_iterator it = parsed.freshens.begin();
01143 it != parsed.freshens.end();
01144 it++)
01145 {
01146 _deps[Dep::FRESHENS].insert(createCapability(*it, my_kind));
01147 }
01148
01149 for (std::list<YUMDependency>::const_iterator it = parsed.recommends.begin();
01150 it != parsed.recommends.end();
01151 it++)
01152 {
01153 _deps[Dep::RECOMMENDS].insert(createCapability(*it, my_kind));
01154 }
01155
01156 for (std::list<YUMDependency>::const_iterator it = parsed.suggests.begin();
01157 it != parsed.suggests.end();
01158 it++)
01159 {
01160 _deps[Dep::SUGGESTS].insert(createCapability(*it, my_kind));
01161 }
01162
01163 for (std::list<YUMDependency>::const_iterator it = parsed.supplements.begin();
01164 it != parsed.supplements.end();
01165 it++)
01166 {
01167 _deps[Dep::SUPPLEMENTS].insert(createCapability(*it, my_kind));
01168 }
01169
01170 for (std::list<YUMDependency>::const_iterator it = parsed.enhances.begin();
01171 it != parsed.enhances.end();
01172 it++)
01173 {
01174 _deps[Dep::ENHANCES].insert(createCapability(*it, my_kind));
01175 }
01176
01177 for (std::list<YUMDependency>::const_iterator it = parsed.prerequires.begin();
01178 it != parsed.prerequires.end();
01179 it++)
01180 {
01181 _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01182 }
01183
01184 for (std::list<YUMDependency>::const_iterator it = parsed.requires.begin();
01185 it != parsed.requires.end();
01186 it++)
01187 {
01188 if (it->pre == "1")
01189 _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01190 else
01191 _deps[Dep::REQUIRES].insert(createCapability(*it, my_kind));
01192 }
01193
01194 return _deps;
01195 }
01196
01197 Dependencies YUMSourceImpl::createGroupDependencies(
01198 const zypp::parser::yum::YUMGroupData & parsed
01199 )
01200 {
01201 Dependencies _deps;
01202
01203 for (std::list<PackageReq>::const_iterator it = parsed.packageList.begin();
01204 it != parsed.packageList.end();
01205 it++)
01206 {
01207 Dep _dep_kind = Dep::REQUIRES;
01208 if (it->type == "mandatory" || it->type == "")
01209 {
01210 _dep_kind = Dep::REQUIRES;
01211 }
01212 else if (it->type == "default")
01213 {
01214 _dep_kind = Dep::RECOMMENDS;
01215 }
01216 else if (it->type == "optional")
01217 {
01218 _dep_kind = Dep::SUGGESTS;
01219 }
01220 _deps[_dep_kind].insert(createCapability(YUMDependency(
01221 "",
01222 it->name,
01223 "EQ",
01224 it->epoch,
01225 it->ver,
01226 it->rel,
01227 ""
01228 ),
01229 ResTraits<Package>::kind));
01230 }
01231 for (std::list<MetaPkg>::const_iterator it = parsed.grouplist.begin();
01232 it != parsed.grouplist.end();
01233 it++)
01234 {
01235 Dep _dep_kind = Dep::REQUIRES;
01236 if (it->type == "mandatory" || it->type == "")
01237 {
01238 _dep_kind = Dep::REQUIRES;
01239 }
01240 else if (it->type == "default")
01241 {
01242 _dep_kind = Dep::RECOMMENDS;
01243 }
01244 else if (it->type == "optional")
01245 {
01246 _dep_kind = Dep::SUGGESTS;
01247 }
01248 _deps[_dep_kind].insert(createCapability(YUMDependency(
01249 "",
01250 it->name,
01251 "",
01252 "",
01253 "",
01254 "",
01255 ""
01256 ),
01257 ResTraits<Selection>::kind));
01258 }
01259 return _deps;
01260 }
01261
01262 Capability YUMSourceImpl::createCapability(const YUMDependency & dep,
01263 const Resolvable::Kind & my_kind)
01264 {
01265 CapFactory _f;
01266 Resolvable::Kind _kind = dep.kind == "" ? my_kind : Resolvable::Kind(dep.kind);
01267 Capability cap;
01268 if ( ! dep.isEncoded() )
01269 {
01270 cap = _f.parse(
01271 _kind,
01272 dep.name,
01273 Rel(dep.flags),
01274 Edition(dep.ver, dep.rel, dep.epoch)
01275 );
01276 }
01277 else
01278 {
01279 cap = _f.parse( _kind, dep.encoded );
01280 }
01281 return cap;
01282 }
01283
01284
01285
01286
01287 bool YUMSourceImpl::checkCheckSum (const Pathname & filename, std::string csum_type, const std::string & csum)
01288 {
01289 MIL << "Checking checksum for " << filename << " as type: " << csum_type << "; value: " << csum << endl;
01290 if (str::toLower(csum_type) == "sha")
01291 {
01292 if (csum.size() == 40)
01293 csum_type = "sha1";
01294 else if (csum.size() == 64)
01295 csum_type = "sha256";
01296 DBG << "Checksum size is " << csum.size() << ", checksum type set to " << csum_type << endl;
01297 }
01298 ifstream st(filename.asString().c_str());
01299 std::string dig = Digest::digest (csum_type, st, 4096);
01300 if (dig == "")
01301 {
01302 ERR << "Cannot compute the checksum" << endl;
01303 return false;
01304 }
01305 dig = str::toLower (dig);
01306 bool ret = (dig == str::toLower(csum));
01307 if (ret)
01308 {
01309 MIL << "Checksums are the same" << endl;
01310 return true;
01311 }
01312 else
01313 {
01314 WAR << "Checksum missmatch: metadata: " << csum << "; real: " << dig << endl;
01315 return false;
01316 }
01317 return false;
01318 }
01319
01320 }
01322 }
01325 }