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