00001
00002
00003
00004
00005
00006
00007
00008
00012 #include "librpm.h"
00013 #if !defined(_RPM_4_4_COMPAT) && !defined(_RPM_5)
00014 #include <rpm/ugid.h>
00015 #else
00016
00017
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 return BinHeader::dumpOn( str ) << '{' << tag_name() << "-"
00270 << (tag_epoch()==0?"":(tag_epoch()+":"))
00271 << tag_version()
00272 << (tag_release().empty()?"":(std::string("-")+tag_release()))
00273 << ( isSrc() ? ".src}" : "}");
00274 }
00275
00276
00278
00279
00280
00281
00282
00283 bool RpmHeader::isSrc() const
00284 {
00285 return has_tag( RPMTAG_SOURCEPACKAGE );
00286 }
00287
00289
00290
00291
00292
00293
00294
00295
00296 std::string RpmHeader::tag_name() const
00297 {
00298 return string_val( RPMTAG_NAME );
00299 }
00300
00302
00303
00304
00305
00306
00307
00308
00309 Edition::epoch_t RpmHeader::tag_epoch() const
00310 {
00311 return int_val ( RPMTAG_EPOCH );
00312 }
00313
00315
00316
00317
00318
00319
00320
00321
00322 std::string RpmHeader::tag_version() const
00323 {
00324 return string_val ( RPMTAG_VERSION );
00325 }
00326
00328
00329
00330
00331
00332
00333
00334
00335 std::string RpmHeader::tag_release() const
00336 {
00337 return string_val( RPMTAG_RELEASE );
00338 }
00339
00341
00342
00343
00344
00345
00346
00347
00348 Edition RpmHeader::tag_edition () const
00349 {
00350 return Edition( tag_version(), tag_release(), tag_epoch() );
00351 }
00352
00354
00355
00356
00357
00358
00359
00360
00361 Arch RpmHeader::tag_arch() const
00362 {
00363 return Arch( string_val( RPMTAG_ARCH ) );
00364 }
00365
00367
00368
00369
00370
00371
00372
00373
00374 Date RpmHeader::tag_installtime() const
00375 {
00376 return int_val( RPMTAG_INSTALLTIME );
00377 }
00378
00380
00381
00382
00383
00384
00385
00386
00387 Date RpmHeader::tag_buildtime() const
00388 {
00389 return int_val( RPMTAG_BUILDTIME );
00390 }
00391 #warning CHECK IF FILE REQUIRES HANDLING IS OBSOLETE
00392
00393
00394
00395
00396
00397
00398
00399
00400 CapabilitySet RpmHeader::PkgRelList_val( tag tag_r, bool pre, std::set<std::string> * freq_r ) const
00401 {
00402 CapabilitySet ret;
00403
00404 rpmTag kindFlags = rpmTag(0);
00405 rpmTag kindVersion = rpmTag(0);
00406
00407 switch ( tag_r )
00408 {
00409 case RPMTAG_REQUIRENAME:
00410 kindFlags = RPMTAG_REQUIREFLAGS;
00411 kindVersion = RPMTAG_REQUIREVERSION;
00412 break;
00413 case RPMTAG_PROVIDENAME:
00414 kindFlags = RPMTAG_PROVIDEFLAGS;
00415 kindVersion = RPMTAG_PROVIDEVERSION;
00416 break;
00417 case RPMTAG_OBSOLETENAME:
00418 kindFlags = RPMTAG_OBSOLETEFLAGS;
00419 kindVersion = RPMTAG_OBSOLETEVERSION;
00420 break;
00421 case RPMTAG_CONFLICTNAME:
00422 kindFlags = RPMTAG_CONFLICTFLAGS;
00423 kindVersion = RPMTAG_CONFLICTVERSION;
00424 break;
00425 case RPMTAG_ENHANCESNAME:
00426 kindFlags = RPMTAG_ENHANCESFLAGS;
00427 kindVersion = RPMTAG_ENHANCESVERSION;
00428 break;
00429 case RPMTAG_SUGGESTSNAME:
00430 kindFlags = RPMTAG_SUGGESTSFLAGS;
00431 kindVersion = RPMTAG_SUGGESTSVERSION;
00432 break;
00433 default:
00434 INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
00435 return ret;
00436 break;
00437 }
00438
00439 stringList names;
00440 unsigned count = string_list( tag_r, names );
00441 if ( !count )
00442 return ret;
00443
00444 intList flags;
00445 int_list( kindFlags, flags );
00446
00447 stringList versions;
00448 string_list( kindVersion, versions );
00449
00450 for ( unsigned i = 0; i < count; ++i )
00451 {
00452
00453 std::string n( names[i] );
00454
00455 Rel op = Rel::ANY;
00456 int32_t f = flags[i];
00457 std::string v = versions[i];
00458
00459 if ( n[0] == '/' )
00460 {
00461 if ( freq_r )
00462 {
00463 freq_r->insert( n );
00464 }
00465 }
00466 else
00467 {
00468 if ( v.size() )
00469 {
00470 switch ( f & RPMSENSE_SENSEMASK )
00471 {
00472 case RPMSENSE_LESS:
00473 op = Rel::LT;
00474 break;
00475 case RPMSENSE_LESS|RPMSENSE_EQUAL:
00476 op = Rel::LE;
00477 break;
00478 case RPMSENSE_GREATER:
00479 op = Rel::GT;
00480 break;
00481 case RPMSENSE_GREATER|RPMSENSE_EQUAL:
00482 op = Rel::GE;
00483 break;
00484 case RPMSENSE_EQUAL:
00485 op = Rel::EQ;
00486 break;
00487 }
00488 }
00489 }
00490 if ((pre && (f & RPMSENSE_PREREQ))
00491 || ((! pre) && !(f & RPMSENSE_PREREQ)))
00492 {
00493 try
00494 {
00495 ret.insert( Capability( n, op, Edition(v) ) );
00496 }
00497 catch (Exception & excpt_r)
00498 {
00499 ZYPP_CAUGHT(excpt_r);
00500 WAR << "Invalid capability: " << n << " " << op << " "
00501 << v << endl;
00502 }
00503 }
00504 }
00505
00506 return ret;
00507 }
00508
00510
00511
00512
00513
00514
00515
00516
00517 CapabilitySet RpmHeader::tag_provides( std::set<std::string> * freq_r ) const
00518 {
00519 return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
00520 }
00521
00523
00524
00525
00526
00527
00528
00529
00530 CapabilitySet RpmHeader::tag_requires( std::set<std::string> * freq_r ) const
00531 {
00532 return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
00533 }
00534
00536
00537
00538
00539
00540
00541
00542
00543 CapabilitySet RpmHeader::tag_prerequires( std::set<std::string> * freq_r ) const
00544 {
00545 return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
00546 }
00547
00549
00550
00551
00552
00553
00554
00555
00556 CapabilitySet RpmHeader::tag_conflicts( std::set<std::string> * freq_r ) const
00557 {
00558 return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
00559 }
00560
00562
00563
00564
00565
00566
00567
00568
00569 CapabilitySet RpmHeader::tag_obsoletes( std::set<std::string> * freq_r ) const
00570 {
00571 return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
00572 }
00573
00575
00576
00577
00578
00579
00580
00581
00582 CapabilitySet RpmHeader::tag_enhances( std::set<std::string> * freq_r ) const
00583 {
00584 return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
00585 }
00586
00588
00589
00590
00591
00592
00593
00594
00595 CapabilitySet RpmHeader::tag_suggests( std::set<std::string> * freq_r ) const
00596 {
00597 return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r );
00598 }
00599
00601
00602
00603
00604
00605
00606
00607
00608 ByteCount RpmHeader::tag_size() const
00609 {
00610 return int_val( RPMTAG_SIZE );
00611 }
00612
00614
00615
00616
00617
00618
00619
00620
00621 ByteCount RpmHeader::tag_archivesize() const
00622 {
00623 return int_val( RPMTAG_ARCHIVESIZE );
00624 }
00625
00627
00628
00629
00630
00631
00632
00633
00634 std::string RpmHeader::tag_summary() const
00635 {
00636 return string_val( RPMTAG_SUMMARY );
00637 }
00638
00640
00641
00642
00643
00644
00645
00646
00647 std::string RpmHeader::tag_description() const
00648 {
00649 return string_val( RPMTAG_DESCRIPTION );
00650 }
00651
00653
00654
00655
00656
00657
00658
00659
00660 std::string RpmHeader::tag_group() const
00661 {
00662 return string_val( RPMTAG_GROUP );
00663 }
00664
00666
00667
00668
00669
00670
00671
00672
00673 std::string RpmHeader::tag_vendor() const
00674 {
00675 return string_val( RPMTAG_VENDOR );
00676 }
00677
00679
00680
00681
00682
00683
00684
00685
00686 std::string RpmHeader::tag_distribution() const
00687 {
00688 return string_val( RPMTAG_DISTRIBUTION );
00689 }
00690
00692
00693
00694
00695
00696
00697
00698
00699 std::string RpmHeader::tag_license() const
00700 {
00701 return string_val( RPMTAG_LICENSE );
00702 }
00703
00705
00706
00707
00708
00709
00710
00711
00712 std::string RpmHeader::tag_buildhost() const
00713 {
00714 return string_val( RPMTAG_BUILDHOST );
00715 }
00716
00718
00719
00720
00721
00722
00723
00724
00725 std::string RpmHeader::tag_packager() const
00726 {
00727 return string_val( RPMTAG_PACKAGER );
00728 }
00729
00731
00732
00733
00734
00735
00736
00737
00738 std::string RpmHeader::tag_url() const
00739 {
00740 return string_val( RPMTAG_URL );
00741 }
00742
00744
00745
00746
00747
00748
00749
00750
00751 std::string RpmHeader::tag_os() const
00752 {
00753 return string_val( RPMTAG_OS );
00754 }
00755
00757
00758
00759
00760
00761
00762
00763
00764 std::string RpmHeader::tag_prein() const
00765 {
00766 return string_val( RPMTAG_PREIN );
00767 }
00768
00770
00771
00772
00773
00774
00775
00776
00777 std::string RpmHeader::tag_postin() const
00778 {
00779 return string_val( RPMTAG_POSTIN );
00780 }
00781
00783
00784
00785
00786
00787
00788
00789
00790 std::string RpmHeader::tag_preun() const
00791 {
00792 return string_val( RPMTAG_PREUN );
00793 }
00794
00796
00797
00798
00799
00800
00801
00802
00803 std::string RpmHeader::tag_postun() const
00804 {
00805 return string_val( RPMTAG_POSTUN );
00806 }
00807
00809
00810
00811
00812
00813
00814
00815
00816 std::string RpmHeader::tag_sourcerpm() const
00817 {
00818 return string_val( RPMTAG_SOURCERPM );
00819 }
00820
00822
00823
00824
00825
00826
00827
00828
00829 std::list<std::string> RpmHeader::tag_filenames() const
00830 {
00831 std::list<std::string> ret;
00832
00833 stringList basenames;
00834 if ( string_list( RPMTAG_BASENAMES, basenames ) )
00835 {
00836 stringList dirnames;
00837 string_list( RPMTAG_DIRNAMES, dirnames );
00838 intList dirindexes;
00839 int_list( RPMTAG_DIRINDEXES, dirindexes );
00840 for ( unsigned i = 0; i < basenames.size(); ++ i )
00841 {
00842 ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
00843 }
00844 }
00845
00846 return ret;
00847 }
00848
00850
00851
00852
00853
00854
00855
00856
00857 std::list<FileInfo> RpmHeader::tag_fileinfos() const
00858 {
00859 std::list<FileInfo> ret;
00860
00861 stringList basenames;
00862 if ( string_list( RPMTAG_BASENAMES, basenames ) )
00863 {
00864 stringList dirnames;
00865 string_list( RPMTAG_DIRNAMES, dirnames );
00866 intList dirindexes;
00867 int_list( RPMTAG_DIRINDEXES, dirindexes );
00868 intList filesizes;
00869 int_list( RPMTAG_FILESIZES, filesizes );
00870 stringList md5sums;
00871 string_list( RPMTAG_FILEMD5S, md5sums );
00872 stringList usernames;
00873 string_list( RPMTAG_FILEUSERNAME, usernames );
00874 stringList groupnames;
00875 string_list( RPMTAG_FILEGROUPNAME, groupnames );
00876 intList uids;
00877 int_list( RPMTAG_FILEUIDS, uids );
00878 intList gids;
00879 int_list( RPMTAG_FILEGIDS, gids );
00880 intList filemodes;
00881 int_list( RPMTAG_FILEMODES, filemodes );
00882 intList filemtimes;
00883 int_list( RPMTAG_FILEMTIMES, filemtimes );
00884 intList fileflags;
00885 int_list( RPMTAG_FILEFLAGS, fileflags );
00886 stringList filelinks;
00887 string_list( RPMTAG_FILELINKTOS, filelinks );
00888
00889 for ( unsigned i = 0; i < basenames.size(); ++ i )
00890 {
00891 uid_t uid;
00892 if (uids.empty())
00893 {
00894 uid = unameToUid( usernames[i].c_str(), &uid );
00895 }
00896 else
00897 {
00898 uid =uids[i];
00899 }
00900
00901 gid_t gid;
00902 if (gids.empty())
00903 {
00904 gid = gnameToGid( groupnames[i].c_str(), &gid );
00905 }
00906 else
00907 {
00908 gid = gids[i];
00909 }
00910
00911 FileInfo info = {
00912 dirnames[dirindexes[i]] + basenames[i],
00913 filesizes[i],
00914 md5sums[i],
00915 uid,
00916 gid,
00917 filemodes[i],
00918 filemtimes[i],
00919 fileflags[i] & RPMFILE_GHOST,
00920 filelinks[i]
00921 };
00922
00923 ret.push_back( info );
00924 }
00925 }
00926
00927 return ret;
00928 }
00929
00931
00932
00933
00934
00935
00936
00937
00938 Changelog RpmHeader::tag_changelog() const
00939 {
00940 Changelog ret;
00941
00942 intList times;
00943 if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
00944 {
00945 stringList names;
00946 string_list( RPMTAG_CHANGELOGNAME, names );
00947 stringList texts;
00948 string_list( RPMTAG_CHANGELOGTEXT, texts );
00949 for ( unsigned i = 0; i < times.size(); ++ i )
00950 {
00951 ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
00952 }
00953 }
00954
00955 return ret;
00956 }
00957
00959
00960
00961
00962
00963
00964
00965
00966 DiskUsage & RpmHeader::tag_du( DiskUsage & dudata_r ) const
00967 {
00968 dudata_r.clear();
00969 stringList basenames;
00970 if ( string_list( RPMTAG_BASENAMES, basenames ) )
00971 {
00972 stringList dirnames;
00973 string_list( RPMTAG_DIRNAMES, dirnames );
00974 intList dirindexes;
00975 int_list( RPMTAG_DIRINDEXES, dirindexes );
00976
00977 intList filedevices;
00978 int_list( RPMTAG_FILEDEVICES, filedevices );
00979 intList fileinodes;
00980 int_list( RPMTAG_FILEINODES, fileinodes );
00981 intList filesizes;
00982 int_list( RPMTAG_FILESIZES, filesizes );
00983 intList filemodes;
00984 int_list( RPMTAG_FILEMODES, filemodes );
00985
00987
00988
00990 filesystem::DevInoCache trace;
00991 std::vector<DiskUsage::Entry> entries;
00992 entries.resize( dirnames.size() );
00993 for ( unsigned i = 0; i < dirnames.size(); ++i )
00994 {
00995 entries[i] = DiskUsage::Entry( dirnames[i] );
00996
00997
00998 unsigned level = 3;
00999 std::string::size_type pos = 0;
01000 while ( --level && pos != std::string::npos )
01001 {
01002 pos = entries[i].path.find( "/", pos+1 );
01003 }
01004 if ( pos != std::string::npos )
01005 {
01006 entries[i].path.erase( pos+1 );
01007 }
01008 }
01009
01010 for ( unsigned i = 0; i < basenames.size(); ++ i )
01011 {
01012 filesystem::StatMode mode( filemodes[i] );
01013 if ( mode.isFile() )
01014 {
01015 if ( trace.insert( filedevices[i], fileinodes[i] ) )
01016 {
01017
01018 entries[dirindexes[i]]._size += ByteCount( filesizes[i] ).blocks( ByteCount::K );
01019 ++(entries[dirindexes[i]]._files);
01020 }
01021
01022 }
01023 }
01024
01026
01027
01028
01030 DiskUsage tmpdata;
01031 for ( unsigned i = 0; i < entries.size(); ++i )
01032 {
01033 if ( entries[i]._size )
01034 tmpdata.add( entries[i] );
01035 }
01036
01037 for_( it, tmpdata.begin(), tmpdata.end() )
01038 {
01039 DiskUsage::Entry ent( *it );
01040
01041 do {
01042 dudata_r.add( ent );
01043 if ( ent.path.size() <= 1 )
01044 break;
01045
01046
01047
01048 std::string::size_type rstart = ent.path.size() - 2;
01049 std::string::size_type lpos = ent.path.rfind( '/', rstart );
01050 if ( lpos == std::string::npos )
01051 break;
01052
01053 ent.path.erase( lpos + 1 );
01054 } while( true );
01055 }
01056 }
01057 return dudata_r;
01058 }
01059
01060 }
01061 }
01062 }