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 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
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
00856 NVRAD dataCollect( parsed.groupId,
00857 Edition::noedition,
00858 Arch_noarch,
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
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
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
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
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
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
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
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
01042
01043
01044
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
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() ) ) {
01059
01060 if (!oldarch.compatibleWith( getZYpp()->architecture() )
01061 || oldarch.compare( newarch ) < 0)
01062 {
01063 pa_pos->second = package_data;
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;
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
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
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 }
01326 }
01329 }