00001
00002
00003
00004
00005
00006
00007
00008
00012 #include "librpm.h"
00013
00014 #include <iostream>
00015 #include <map>
00016 #include <set>
00017 #include <vector>
00018
00019 #include "zypp/base/Easy.h"
00020 #include "zypp/base/Logger.h"
00021 #include "zypp/PathInfo.h"
00022
00023 #include "zypp/target/rpm/RpmHeader.h"
00024 #include "zypp/CapFactory.h"
00025 #include "zypp/Rel.h"
00026 #include "zypp/Package.h"
00027 #include "zypp/base/Exception.h"
00028
00029 using namespace std;
00030 using namespace zypp::capability;
00031
00032 namespace zypp
00033 {
00034 namespace target
00035 {
00036 namespace rpm
00037 {
00038
00040
00042
00043
00044
00045
00046
00047
00048
00049 RpmHeader::RpmHeader( Header h_r )
00050 : BinHeader( h_r )
00051 {}
00052
00054
00055
00056
00057
00058
00059 RpmHeader::RpmHeader( BinHeader::Ptr & rhs )
00060 : BinHeader( rhs )
00061 {}
00062
00064
00065
00066
00067
00068
00069
00070
00071 RpmHeader::~RpmHeader()
00072 {}
00073
00075
00076
00077
00078
00079
00080 RpmHeader::constPtr RpmHeader::readPackage( const Pathname & path_r,
00081 VERIFICATION verification_r )
00082 {
00083 PathInfo file( path_r );
00084 if ( ! file.isFile() )
00085 {
00086 ERR << "Not a file: " << file << endl;
00087 return (RpmHeader*)0;
00088 }
00089
00090 FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" );
00091 if ( fd == 0 || ::Ferror(fd) )
00092 {
00093 ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl;
00094 if ( fd )
00095 ::Fclose( fd );
00096 return (RpmHeader*)0;
00097 }
00098
00099 rpmts ts = ::rpmtsCreate();
00100 unsigned vsflag = RPMVSF_DEFAULT;
00101 if ( verification_r & NODIGEST )
00102 vsflag |= _RPMVSF_NODIGESTS;
00103 if ( verification_r & NOSIGNATURE )
00104 vsflag |= _RPMVSF_NOSIGNATURES;
00105 ::rpmtsSetVSFlags( ts, rpmVSFlags(vsflag) );
00106
00107 Header nh = 0;
00108 int res = ::rpmReadPackageFile( ts, fd, path_r.asString().c_str(), &nh );
00109
00110 ts = ::rpmtsFree(ts);
00111
00112 ::Fclose( fd );
00113
00114 if ( ! nh )
00115 {
00116 WAR << "Error reading header from " << path_r << " error(" << res << ")" << endl;
00117 return (RpmHeader*)0;
00118 }
00119
00120 RpmHeader::constPtr h( new RpmHeader( nh ) );
00121 headerFree( nh );
00122
00123 MIL << h << " from " << path_r << endl;
00124 return h;
00125 }
00126
00128
00129
00130
00131
00132
00133
00134
00135 ostream & RpmHeader::dumpOn( ostream & str ) const
00136 {
00137 return BinHeader::dumpOn( str ) << '{' << tag_name() << "-"
00138 << (tag_epoch().empty()?"":(tag_epoch()+":"))
00139 << tag_version()
00140 << (tag_release().empty()?"":(string("-")+tag_release()))
00141 << ( isSrc() ? ".src}" : "}");
00142 }
00143
00144
00146
00147
00148
00149
00150
00151 bool RpmHeader::isSrc() const
00152 {
00153 return has_tag( RPMTAG_SOURCEPACKAGE );
00154 }
00155
00157
00158
00159
00160
00161
00162
00163
00164 string RpmHeader::tag_name() const
00165 {
00166 return string_val( RPMTAG_NAME );
00167 }
00168
00170
00171
00172
00173
00174
00175
00176
00177 string RpmHeader::tag_epoch() const
00178 {
00179 return string_val ( RPMTAG_EPOCH );
00180 }
00181
00183
00184
00185
00186
00187
00188
00189
00190 string RpmHeader::tag_version() const
00191 {
00192 return string_val ( RPMTAG_VERSION );
00193 }
00194
00196
00197
00198
00199
00200
00201
00202
00203 string RpmHeader::tag_release() const
00204 {
00205 return string_val( RPMTAG_RELEASE );
00206 }
00207
00209
00210
00211
00212
00213
00214
00215
00216 Edition RpmHeader::tag_edition () const
00217 {
00218 try
00219 {
00220 return Edition( tag_version(), tag_release(), tag_epoch());
00221 }
00222 catch (Exception & excpt_r)
00223 {
00224 WAR << "Package " << tag_name() << "has an invalid edition";
00225 ZYPP_CAUGHT (excpt_r);
00226 }
00227 return Edition();
00228 }
00229
00231
00232
00233
00234
00235
00236
00237
00238 string RpmHeader::tag_arch() const
00239 {
00240 return string_val( RPMTAG_ARCH );
00241 }
00242
00244
00245
00246
00247
00248
00249
00250
00251 Date RpmHeader::tag_installtime() const
00252 {
00253 return int_val( RPMTAG_INSTALLTIME );
00254 }
00255
00257
00258
00259
00260
00261
00262
00263
00264 Date RpmHeader::tag_buildtime() const
00265 {
00266 return int_val( RPMTAG_BUILDTIME );
00267 }
00268
00270
00271
00272
00273
00274
00275
00276
00277 CapabilityImplPtrSet RpmHeader::PkgRelList_val( tag tag_r, bool pre, set<string> * freq_r ) const
00278 {
00279 CapabilityImplPtrSet ret;
00280
00281 int_32 kindFlags = 0;
00282 int_32 kindVersion = 0;
00283
00284 switch ( tag_r )
00285 {
00286 case RPMTAG_REQUIRENAME:
00287 kindFlags = RPMTAG_REQUIREFLAGS;
00288 kindVersion = RPMTAG_REQUIREVERSION;
00289 break;
00290 case RPMTAG_PROVIDENAME:
00291 kindFlags = RPMTAG_PROVIDEFLAGS;
00292 kindVersion = RPMTAG_PROVIDEVERSION;
00293 break;
00294 case RPMTAG_OBSOLETENAME:
00295 kindFlags = RPMTAG_OBSOLETEFLAGS;
00296 kindVersion = RPMTAG_OBSOLETEVERSION;
00297 break;
00298 case RPMTAG_CONFLICTNAME:
00299 kindFlags = RPMTAG_CONFLICTFLAGS;
00300 kindVersion = RPMTAG_CONFLICTVERSION;
00301 break;
00302 #ifdef HAVE_RPM_ENHANCES
00303 case RPMTAG_ENHANCESNAME:
00304 kindFlags = RPMTAG_ENHANCESFLAGS;
00305 kindVersion = RPMTAG_ENHANCESVERSION;
00306 break;
00307 #endif
00308 #warning NEEDS RPMTAG_SUPPLEMENTSNAME
00309 #if 0
00310 case RPMTAG_SUPPLEMENTSNAME:
00311 kindFlags = RPMTAG_SUPPLEMENTSFLAGS;
00312 kindVersion = RPMTAG_SUPPLEMENTSVERSION;
00313 break;
00314 #endif
00315 default:
00316 INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
00317 return ret;
00318 break;
00319 }
00320
00321 stringList names;
00322 unsigned count = string_list( tag_r, names );
00323 if ( !count )
00324 return ret;
00325
00326 intList flags;
00327 int_list( kindFlags, flags );
00328
00329 stringList versions;
00330 string_list( kindVersion, versions );
00331
00332 for ( unsigned i = 0; i < count; ++i )
00333 {
00334
00335 string n( names[i] );
00336
00337 Rel op = Rel::ANY;
00338 int_32 f = flags[i];
00339 string v = versions[i];
00340
00341 if ( n[0] == '/' )
00342 {
00343 if ( freq_r )
00344 {
00345 freq_r->insert( n );
00346 }
00347 }
00348 else
00349 {
00350 if ( v.size() )
00351 {
00352 switch ( f & RPMSENSE_SENSEMASK )
00353 {
00354 case RPMSENSE_LESS:
00355 op = Rel::LT;
00356 break;
00357 case RPMSENSE_LESS|RPMSENSE_EQUAL:
00358 op = Rel::LE;
00359 break;
00360 case RPMSENSE_GREATER:
00361 op = Rel::GT;
00362 break;
00363 case RPMSENSE_GREATER|RPMSENSE_EQUAL:
00364 op = Rel::GE;
00365 break;
00366 case RPMSENSE_EQUAL:
00367 op = Rel::EQ;
00368 break;
00369 }
00370 }
00371 }
00372 if ((pre && (f & RPMSENSE_PREREQ))
00373 || ((! pre) && !(f & RPMSENSE_PREREQ)))
00374 {
00375 try
00376 {
00377 CapabilityImpl::Ptr cap = capability::buildVersioned(
00378 ResTraits<Package>::kind,
00379 n,
00380 op,
00381 Edition(v)
00382 );
00383 ret.insert(cap);
00384 }
00385 catch (Exception & excpt_r)
00386 {
00387 ZYPP_CAUGHT(excpt_r);
00388 WAR << "Invalid capability: " << n << " " << op << " "
00389 << v << endl;
00390 }
00391 }
00392 }
00393
00394 return ret;
00395 }
00396
00398
00399
00400
00401
00402
00403
00404
00405 CapabilityImplPtrSet RpmHeader::tag_provides( set<string> * freq_r ) const
00406 {
00407 return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
00408 }
00409
00411
00412
00413
00414
00415
00416
00417
00418 CapabilityImplPtrSet RpmHeader::tag_requires( set<string> * freq_r ) const
00419 {
00420 return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
00421 }
00422
00424
00425
00426
00427
00428
00429
00430
00431 CapabilityImplPtrSet RpmHeader::tag_prerequires( set<string> * freq_r ) const
00432 {
00433 return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
00434 }
00435
00437
00438
00439
00440
00441
00442
00443
00444 CapabilityImplPtrSet RpmHeader::tag_conflicts( set<string> * freq_r ) const
00445 {
00446 return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
00447 }
00448
00450
00451
00452
00453
00454
00455
00456
00457 CapabilityImplPtrSet RpmHeader::tag_obsoletes( set<string> * freq_r ) const
00458 {
00459 return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
00460 }
00461
00463
00464
00465
00466
00467
00468
00469
00470 CapabilityImplPtrSet RpmHeader::tag_enhances( set<string> * freq_r ) const
00471 {
00472 #ifdef HAVE_RPM_ENHANCES
00473 return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
00474 #else
00475 return CapabilityImplPtrSet();
00476 #endif
00477 }
00478
00480
00481
00482
00483
00484
00485
00486
00487 CapabilityImplPtrSet RpmHeader::tag_supplements( set<string> * freq_r ) const
00488 {
00489 return CapabilityImplPtrSet();
00490 #warning NEEDS RPMTAG_SUPPLEMENTSNAME
00491 #if 0
00492 return PkgRelList_val( RPMTAG_SUPPLEMENTSNAME, false, freq_r );
00493 #endif
00494 }
00495
00497
00498
00499
00500
00501
00502
00503
00504 ByteCount RpmHeader::tag_size() const
00505 {
00506 return int_val( RPMTAG_SIZE );
00507 }
00508
00510
00511
00512
00513
00514
00515
00516
00517 ByteCount RpmHeader::tag_archivesize() const
00518 {
00519 return int_val( RPMTAG_ARCHIVESIZE );
00520 }
00521
00523
00524
00525
00526
00527
00528
00529
00530 std::string RpmHeader::tag_summary() const
00531 {
00532 return string_val( RPMTAG_SUMMARY );
00533 }
00534
00536
00537
00538
00539
00540
00541
00542
00543 std::string RpmHeader::tag_description() const
00544 {
00545 return string_val( RPMTAG_DESCRIPTION );
00546 }
00547
00549
00550
00551
00552
00553
00554
00555
00556 std::string RpmHeader::tag_group() const
00557 {
00558 return string_val( RPMTAG_GROUP );
00559 }
00560
00562
00563
00564
00565
00566
00567
00568
00569 std::string RpmHeader::tag_vendor() const
00570 {
00571 return string_val( RPMTAG_VENDOR );
00572 }
00573
00575
00576
00577
00578
00579
00580
00581
00582 std::string RpmHeader::tag_distribution() const
00583 {
00584 return string_val( RPMTAG_DISTRIBUTION );
00585 }
00586
00588
00589
00590
00591
00592
00593
00594
00595 std::string RpmHeader::tag_license() const
00596 {
00597 return string_val( RPMTAG_LICENSE );
00598 }
00599
00601
00602
00603
00604
00605
00606
00607
00608 std::string RpmHeader::tag_buildhost() const
00609 {
00610 return string_val( RPMTAG_BUILDHOST );
00611 }
00612
00614
00615
00616
00617
00618
00619
00620
00621 std::string RpmHeader::tag_packager() const
00622 {
00623 return string_val( RPMTAG_PACKAGER );
00624 }
00625
00627
00628
00629
00630
00631
00632
00633
00634 std::string RpmHeader::tag_url() const
00635 {
00636 return string_val( RPMTAG_URL );
00637 }
00638
00640
00641
00642
00643
00644
00645
00646
00647 std::string RpmHeader::tag_os() const
00648 {
00649 return string_val( RPMTAG_OS );
00650 }
00651
00653
00654
00655
00656
00657
00658
00659
00660 std::string RpmHeader::tag_prein() const
00661 {
00662 return string_val( RPMTAG_PREIN );
00663 }
00664
00666
00667
00668
00669
00670
00671
00672
00673 std::string RpmHeader::tag_postin() const
00674 {
00675 return string_val( RPMTAG_POSTIN );
00676 }
00677
00679
00680
00681
00682
00683
00684
00685
00686 std::string RpmHeader::tag_preun() const
00687 {
00688 return string_val( RPMTAG_PREUN );
00689 }
00690
00692
00693
00694
00695
00696
00697
00698
00699 std::string RpmHeader::tag_postun() const
00700 {
00701 return string_val( RPMTAG_POSTUN );
00702 }
00703
00705
00706
00707
00708
00709
00710
00711
00712 std::string RpmHeader::tag_sourcerpm() const
00713 {
00714 return string_val( RPMTAG_SOURCERPM );
00715 }
00716
00718
00719
00720
00721
00722
00723
00724
00725 std::list<std::string> RpmHeader::tag_filenames() const
00726 {
00727 std::list<std::string> ret;
00728
00729 stringList basenames;
00730 if ( string_list( RPMTAG_BASENAMES, basenames ) )
00731 {
00732 stringList dirnames;
00733 string_list( RPMTAG_DIRNAMES, dirnames );
00734 intList dirindexes;
00735 int_list( RPMTAG_DIRINDEXES, dirindexes );
00736 for ( unsigned i = 0; i < basenames.size(); ++ i )
00737 {
00738 ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
00739 }
00740 }
00741
00742 return ret;
00743 }
00744
00746
00747
00748
00749
00750
00751
00752
00753 std::list<FileInfo> RpmHeader::tag_fileinfos() const
00754 {
00755 std::list<FileInfo> ret;
00756
00757 stringList basenames;
00758 if ( string_list( RPMTAG_BASENAMES, basenames ) )
00759 {
00760 stringList dirnames;
00761 string_list( RPMTAG_DIRNAMES, dirnames );
00762 intList dirindexes;
00763 int_list( RPMTAG_DIRINDEXES, dirindexes );
00764 intList filesizes;
00765 int_list( RPMTAG_FILESIZES, filesizes );
00766 stringList md5sums;
00767 string_list( RPMTAG_FILEMD5S, md5sums );
00768 stringList usernames;
00769 string_list( RPMTAG_FILEUSERNAME, usernames );
00770 stringList groupnames;
00771 string_list( RPMTAG_FILEGROUPNAME, groupnames );
00772 intList uids;
00773 int_list( RPMTAG_FILEUIDS, uids );
00774 intList gids;
00775 int_list( RPMTAG_FILEGIDS, gids );
00776 intList filemodes;
00777 int_list( RPMTAG_FILEMODES, filemodes );
00778 intList filemtimes;
00779 int_list( RPMTAG_FILEMTIMES, filemtimes );
00780 intList fileflags;
00781 int_list( RPMTAG_FILEFLAGS, fileflags );
00782 stringList filelinks;
00783 string_list( RPMTAG_FILELINKTOS, filelinks );
00784
00785 for ( unsigned i = 0; i < basenames.size(); ++ i )
00786 {
00787 uid_t uid;
00788 if (uids.empty())
00789 {
00790 uid = unameToUid( usernames[i].c_str(), &uid );
00791 }
00792 else
00793 {
00794 uid =uids[i];
00795 }
00796
00797 gid_t gid;
00798 if (gids.empty())
00799 {
00800 gid = gnameToGid( groupnames[i].c_str(), &gid );
00801 }
00802 else
00803 {
00804 gid = gids[i];
00805 }
00806
00807 FileInfo info = {
00808 dirnames[dirindexes[i]] + basenames[i],
00809 filesizes[i],
00810 md5sums[i],
00811 uid,
00812 gid,
00813 filemodes[i],
00814 filemtimes[i],
00815 fileflags[i] & RPMFILE_GHOST,
00816 filelinks[i]
00817 };
00818
00819 ret.push_back( info );
00820 }
00821 }
00822
00823 return ret;
00824 }
00825
00827
00828
00829
00830
00831
00832
00833
00834 Changelog RpmHeader::tag_changelog() const
00835 {
00836 Changelog ret;
00837
00838 intList times;
00839 if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
00840 {
00841 stringList names;
00842 string_list( RPMTAG_CHANGELOGNAME, names );
00843 stringList texts;
00844 string_list( RPMTAG_CHANGELOGTEXT, texts );
00845 for ( unsigned i = 0; i < times.size(); ++ i )
00846 {
00847 ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
00848 }
00849 }
00850
00851 return ret;
00852 }
00853
00855
00856
00857
00858
00859
00860
00861
00862 DiskUsage & RpmHeader::tag_du( DiskUsage & dudata_r ) const
00863 {
00864 dudata_r.clear();
00865 stringList basenames;
00866 if ( string_list( RPMTAG_BASENAMES, basenames ) )
00867 {
00868 stringList dirnames;
00869 string_list( RPMTAG_DIRNAMES, dirnames );
00870 intList dirindexes;
00871 int_list( RPMTAG_DIRINDEXES, dirindexes );
00872
00873 intList filedevices;
00874 int_list( RPMTAG_FILEDEVICES, filedevices );
00875 intList fileinodes;
00876 int_list( RPMTAG_FILEINODES, fileinodes );
00877 intList filesizes;
00878 int_list( RPMTAG_FILESIZES, filesizes );
00879 intList filemodes;
00880 int_list( RPMTAG_FILEMODES, filemodes );
00881
00883
00884
00886 filesystem::DevInoCache trace;
00887 vector<DiskUsage::Entry> entries;
00888 entries.resize( dirnames.size() );
00889 for ( unsigned i = 0; i < dirnames.size(); ++i )
00890 {
00891 entries[i] = DiskUsage::Entry( dirnames[i] );
00892
00893
00894 unsigned level = 3;
00895 std::string::size_type pos = 0;
00896 while ( --level && pos != std::string::npos )
00897 {
00898 pos = entries[i].path.find( "/", pos+1 );
00899 }
00900 if ( pos != std::string::npos )
00901 {
00902 entries[i].path.erase( pos+1 );
00903 }
00904 }
00905
00906 for ( unsigned i = 0; i < basenames.size(); ++ i )
00907 {
00908 filesystem::StatMode mode( filemodes[i] );
00909 if ( mode.isFile() )
00910 {
00911 if ( trace.insert( filedevices[i], fileinodes[i] ) )
00912 {
00913
00914 entries[dirindexes[i]]._size += ByteCount( filesizes[i] ).blocks( ByteCount::K );
00915 ++(entries[dirindexes[i]]._files);
00916 }
00917
00918 }
00919 }
00920
00922
00923
00924
00926 DiskUsage tmpdata;
00927 for ( unsigned i = 0; i < entries.size(); ++i )
00928 {
00929 if ( entries[i]._size )
00930 tmpdata.add( entries[i] );
00931 }
00932
00933 for_( it, tmpdata.begin(), tmpdata.end() )
00934 {
00935 DiskUsage::Entry ent( *it );
00936
00937 do {
00938 dudata_r.add( ent );
00939 if ( ent.path.size() <= 1 )
00940 break;
00941
00942
00943
00944 std::string::size_type rstart = ent.path.size() - 2;
00945 std::string::size_type lpos = ent.path.rfind( '/', rstart );
00946 if ( lpos == std::string::npos )
00947 break;
00948
00949 ent.path.erase( lpos + 1 );
00950 } while( true );
00951 }
00952 }
00953 return dudata_r;
00954 }
00955
00956 }
00957 }
00958 }