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