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