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 case RPMTAG_ENHANCESNAME:
00295 kindFlags = RPMTAG_ENHANCESFLAGS;
00296 kindVersion = RPMTAG_ENHANCESVERSION;
00297 break;
00298 #warning NEEDS RPMTAG_SUPPLEMENTSNAME
00299 #if 0
00300 case RPMTAG_SUPPLEMENTSNAME:
00301 kindFlags = RPMTAG_SUPPLEMENTSFLAGS;
00302 kindVersion = RPMTAG_SUPPLEMENTSVERSION;
00303 break;
00304 #endif
00305 default:
00306 INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
00307 return ret;
00308 break;
00309 }
00310
00311 stringList names;
00312 unsigned count = string_list( tag_r, names );
00313 if ( !count )
00314 return ret;
00315
00316 intList flags;
00317 int_list( kindFlags, flags );
00318
00319 stringList versions;
00320 string_list( kindVersion, versions );
00321
00322 for ( unsigned i = 0; i < count; ++i ) {
00323
00324 string n( names[i] );
00325
00326 Rel op = Rel::ANY;
00327 int_32 f = flags[i];
00328 string v = versions[i];
00329
00330 if ( n[0] == '/' ) {
00331 if ( freq_r ) {
00332 freq_r->insert( n );
00333 }
00334 } else {
00335 if ( v.size() ) {
00336 switch ( f & RPMSENSE_SENSEMASK ) {
00337 case RPMSENSE_LESS:
00338 op = Rel::LT;
00339 break;
00340 case RPMSENSE_LESS|RPMSENSE_EQUAL:
00341 op = Rel::LE;
00342 break;
00343 case RPMSENSE_GREATER:
00344 op = Rel::GT;
00345 break;
00346 case RPMSENSE_GREATER|RPMSENSE_EQUAL:
00347 op = Rel::GE;
00348 break;
00349 case RPMSENSE_EQUAL:
00350 op = Rel::EQ;
00351 break;
00352 }
00353 }
00354 }
00355 if ((pre && (f & RPMSENSE_PREREQ))
00356 || ((! pre) && !(f & RPMSENSE_PREREQ)))
00357 {
00358 CapFactory _f;
00359 try {
00360 Capability cap = _f.parse(
00361 ResTraits<Package>::kind,
00362 n,
00363 op,
00364 Edition(v)
00365 );
00366 ret.insert(cap);
00367 }
00368 catch (Exception & excpt_r)
00369 {
00370 ZYPP_CAUGHT(excpt_r);
00371 WAR << "Invalid capability: " << n << " " << op << " "
00372 << v << endl;
00373 }
00374 }
00375 }
00376
00377 return ret;
00378 }
00379
00381
00382
00383
00384
00385
00386
00387
00388 CapSet RpmHeader::tag_provides( set<string> * freq_r ) const
00389 {
00390 return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
00391 }
00392
00394
00395
00396
00397
00398
00399
00400
00401 CapSet RpmHeader::tag_requires( set<string> * freq_r ) const
00402 {
00403 return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
00404 }
00405
00407
00408
00409
00410
00411
00412
00413
00414 CapSet RpmHeader::tag_prerequires( set<string> * freq_r ) const
00415 {
00416 return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
00417 }
00418
00420
00421
00422
00423
00424
00425
00426
00427 CapSet RpmHeader::tag_conflicts( set<string> * freq_r ) const
00428 {
00429 return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
00430 }
00431
00433
00434
00435
00436
00437
00438
00439
00440 CapSet RpmHeader::tag_obsoletes( set<string> * freq_r ) const
00441 {
00442 return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
00443 }
00444
00446
00447
00448
00449
00450
00451
00452
00453 CapSet RpmHeader::tag_enhances( set<string> * freq_r ) const
00454 {
00455 return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
00456 }
00457
00459
00460
00461
00462
00463
00464
00465
00466 CapSet RpmHeader::tag_supplements( set<string> * freq_r ) const
00467 {
00468 return CapSet();
00469 #warning NEEDS RPMTAG_SUPPLEMENTSNAME
00470 #if 0
00471 return PkgRelList_val( RPMTAG_SUPPLEMENTSNAME, false, freq_r );
00472 #endif
00473 }
00474
00476
00477
00478
00479
00480
00481
00482
00483 ByteCount RpmHeader::tag_size() const
00484 {
00485 return int_val( RPMTAG_SIZE );
00486 }
00487
00489
00490
00491
00492
00493
00494
00495
00496 ByteCount RpmHeader::tag_archivesize() const
00497 {
00498 return int_val( RPMTAG_ARCHIVESIZE );
00499 }
00500
00502
00503
00504
00505
00506
00507
00508
00509 std::string RpmHeader::tag_summary() const
00510 {
00511 return string_val( RPMTAG_SUMMARY );
00512 }
00513
00515
00516
00517
00518
00519
00520
00521
00522 std::string RpmHeader::tag_description() const
00523 {
00524 return string_val( RPMTAG_DESCRIPTION );
00525 }
00526
00528
00529
00530
00531
00532
00533
00534
00535 std::string RpmHeader::tag_group() const
00536 {
00537 return string_val( RPMTAG_GROUP );
00538 }
00539
00541
00542
00543
00544
00545
00546
00547
00548 std::string RpmHeader::tag_vendor() const
00549 {
00550 return string_val( RPMTAG_VENDOR );
00551 }
00552
00554
00555
00556
00557
00558
00559
00560
00561 std::string RpmHeader::tag_distribution() const
00562 {
00563 return string_val( RPMTAG_DISTRIBUTION );
00564 }
00565
00567
00568
00569
00570
00571
00572
00573
00574 std::string RpmHeader::tag_license() const
00575 {
00576 return string_val( RPMTAG_LICENSE );
00577 }
00578
00580
00581
00582
00583
00584
00585
00586
00587 std::string RpmHeader::tag_buildhost() const
00588 {
00589 return string_val( RPMTAG_BUILDHOST );
00590 }
00591
00593
00594
00595
00596
00597
00598
00599
00600 std::string RpmHeader::tag_packager() const
00601 {
00602 return string_val( RPMTAG_PACKAGER );
00603 }
00604
00606
00607
00608
00609
00610
00611
00612
00613 std::string RpmHeader::tag_url() const
00614 {
00615 return string_val( RPMTAG_URL );
00616 }
00617
00619
00620
00621
00622
00623
00624
00625
00626 std::string RpmHeader::tag_os() const
00627 {
00628 return string_val( RPMTAG_OS );
00629 }
00630
00632
00633
00634
00635
00636
00637
00638
00639 std::string RpmHeader::tag_prein() const
00640 {
00641 return string_val( RPMTAG_PREIN );
00642 }
00643
00645
00646
00647
00648
00649
00650
00651
00652 std::string RpmHeader::tag_postin() const
00653 {
00654 return string_val( RPMTAG_POSTIN );
00655 }
00656
00658
00659
00660
00661
00662
00663
00664
00665 std::string RpmHeader::tag_preun() const
00666 {
00667 return string_val( RPMTAG_PREUN );
00668 }
00669
00671
00672
00673
00674
00675
00676
00677
00678 std::string RpmHeader::tag_postun() const
00679 {
00680 return string_val( RPMTAG_POSTUN );
00681 }
00682
00684
00685
00686
00687
00688
00689
00690
00691 std::string RpmHeader::tag_sourcerpm() const
00692 {
00693 return string_val( RPMTAG_SOURCERPM );
00694 }
00695
00697
00698
00699
00700
00701
00702
00703
00704 std::list<std::string> RpmHeader::tag_filenames() const
00705 {
00706 std::list<std::string> ret;
00707
00708 stringList basenames;
00709 if ( string_list( RPMTAG_BASENAMES, basenames ) ) {
00710 stringList dirnames;
00711 string_list( RPMTAG_DIRNAMES, dirnames );
00712 intList dirindexes;
00713 int_list( RPMTAG_DIRINDEXES, dirindexes );
00714 for ( unsigned i = 0; i < basenames.size(); ++ i ) {
00715 ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
00716 }
00717 }
00718
00719 return ret;
00720 }
00721
00723
00724
00725
00726
00727
00728
00729
00730 std::list<FileInfo> RpmHeader::tag_fileinfos() const
00731 {
00732 std::list<FileInfo> ret;
00733
00734 stringList basenames;
00735 if ( string_list( RPMTAG_BASENAMES, basenames ) ) {
00736 stringList dirnames;
00737 string_list( RPMTAG_DIRNAMES, dirnames );
00738 intList dirindexes;
00739 int_list( RPMTAG_DIRINDEXES, dirindexes );
00740 intList filesizes;
00741 int_list( RPMTAG_FILESIZES, filesizes );
00742 stringList md5sums;
00743 string_list( RPMTAG_FILEMD5S, md5sums );
00744 stringList usernames;
00745 string_list( RPMTAG_FILEUSERNAME, usernames );
00746 stringList groupnames;
00747 string_list( RPMTAG_FILEGROUPNAME, groupnames );
00748 intList uids;
00749 int_list( RPMTAG_FILEUIDS, uids );
00750 intList gids;
00751 int_list( RPMTAG_FILEGIDS, gids );
00752 intList filemodes;
00753 int_list( RPMTAG_FILEMODES, filemodes );
00754 intList filemtimes;
00755 int_list( RPMTAG_FILEMTIMES, filemtimes );
00756 intList fileflags;
00757 int_list( RPMTAG_FILEFLAGS, fileflags );
00758 stringList filelinks;
00759 string_list( RPMTAG_FILELINKTOS, filelinks );
00760
00761 for ( unsigned i = 0; i < basenames.size(); ++ i ) {
00762 uid_t uid;
00763 if (uids.empty()) {
00764 uid = unameToUid( usernames[i].c_str(), &uid );
00765 }
00766 else {
00767 uid =uids[i];
00768 }
00769
00770 gid_t gid;
00771 if (gids.empty()) {
00772 gid = gnameToGid( groupnames[i].c_str(), &gid );
00773 }
00774 else {
00775 gid = gids[i];
00776 }
00777
00778 FileInfo info = {
00779 dirnames[dirindexes[i]] + basenames[i],
00780 filesizes[i],
00781 md5sums[i],
00782 uid,
00783 gid,
00784 filemodes[i],
00785 filemtimes[i],
00786 fileflags[i] & RPMFILE_GHOST,
00787 filelinks[i]
00788 };
00789
00790 ret.push_back( info );
00791 }
00792 }
00793
00794 return ret;
00795 }
00796
00798
00799
00800
00801
00802
00803
00804
00805 Changelog RpmHeader::tag_changelog() const
00806 {
00807 Changelog ret;
00808
00809 intList times;
00810 if ( int_list( RPMTAG_CHANGELOGTIME, times ) ) {
00811 stringList names;
00812 string_list( RPMTAG_CHANGELOGNAME, names );
00813 stringList texts;
00814 string_list( RPMTAG_CHANGELOGTEXT, texts );
00815 for ( unsigned i = 0; i < times.size(); ++ i ) {
00816 ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
00817 }
00818 }
00819
00820 return ret;
00821 }
00822
00824
00825
00826
00827
00828
00829
00830
00831 DiskUsage & RpmHeader::tag_du( DiskUsage & dudata_r ) const
00832 {
00833 dudata_r.clear();
00834 stringList basenames;
00835 if ( string_list( RPMTAG_BASENAMES, basenames ) ) {
00836 stringList dirnames;
00837 string_list( RPMTAG_DIRNAMES, dirnames );
00838 intList dirindexes;
00839 int_list( RPMTAG_DIRINDEXES, dirindexes );
00840
00841 intList filedevices;
00842 int_list( RPMTAG_FILEDEVICES, filedevices );
00843 intList fileinodes;
00844 int_list( RPMTAG_FILEINODES, fileinodes );
00845 intList filesizes;
00846 int_list( RPMTAG_FILESIZES, filesizes );
00847 intList filemodes;
00848 int_list( RPMTAG_FILEMODES, filemodes );
00849
00851
00852
00854 filesystem::DevInoCache trace;
00855 vector<DiskUsage::Entry> entries;
00856 entries.resize( dirnames.size() );
00857 for ( unsigned i = 0; i < dirnames.size(); ++i ) {
00858 entries[i] = DiskUsage::Entry(dirnames[i]);
00859 }
00860
00861 for ( unsigned i = 0; i < basenames.size(); ++ i ) {
00862 filesystem::StatMode mode( filemodes[i] );
00863 if ( mode.isFile() ) {
00864 if ( trace.insert( filedevices[i], fileinodes[i] ) ) {
00865
00866 entries[dirindexes[i]]._size += ByteCount( filesizes[i] ).fillBlock();
00867 ++(entries[dirindexes[i]]._files);
00868 }
00869
00870 }
00871 }
00872
00874
00875
00877 for ( unsigned i = 0; i < entries.size(); ++i ) {
00878 if ( entries[i]._size ) {
00879 dudata_r.add( entries[i] );
00880 }
00881 }
00882 }
00883 return dudata_r;
00884 }
00885
00886 }
00887 }
00888 }