1
/*---------------------------------------------------------------------\
3
| |__ / \ / / . \ . \ |
8
\---------------------------------------------------------------------*/
9
/** \file zypp/target/rpm/RpmHeader.cc
16
////////////////////////////////////////////////////////////////////
17
// unameToUid and gnameToGid are shamelessly stolen from rpm-4.4.
18
// (rpmio/ugid.c) Those functions were dropped in RPM_4_7
24
/* unameToUid(), uidTouname() and the group variants are really poorly
25
implemented. They really ought to use hash tables. I just made the
26
guess that most files would be owned by root or the same person/group
27
who owned the last file. Those two values are cached, everything else
28
is looked up via getpw() and getgr() functions. If this performs
29
too poorly I'll have to implement it properly :-( */
31
int unameToUid(const char * thisUname, uid_t * uid)
33
/*@only@*/ static char * lastUname = NULL;
34
static size_t lastUnameLen = 0;
35
static size_t lastUnameAlloced;
37
struct passwd * pwent;
43
} else if (strcmp(thisUname, "root") == 0) {
50
thisUnameLen = strlen(thisUname);
51
if (lastUname == NULL || thisUnameLen != lastUnameLen ||
52
strcmp(thisUname, lastUname) != 0)
54
if (lastUnameAlloced < thisUnameLen + 1) {
55
lastUnameAlloced = thisUnameLen + 10;
56
lastUname = (char *)realloc(lastUname, lastUnameAlloced); /* XXX memory leak */
59
strcpy(lastUname, thisUname);
62
pwent = getpwnam(thisUname);
64
/*@-internalglobs@*/ /* FIX: shrug */
67
pwent = getpwnam(thisUname);
68
if (pwent == NULL) return -1;
71
lastUid = pwent->pw_uid;
81
int gnameToGid(const char * thisGname, gid_t * gid)
83
/*@only@*/ static char * lastGname = NULL;
84
static size_t lastGnameLen = 0;
85
static size_t lastGnameAlloced;
90
if (thisGname == NULL) {
93
} else if (strcmp(thisGname, "root") == 0) {
100
thisGnameLen = strlen(thisGname);
101
if (lastGname == NULL || thisGnameLen != lastGnameLen ||
102
strcmp(thisGname, lastGname) != 0)
104
if (lastGnameAlloced < thisGnameLen + 1) {
105
lastGnameAlloced = thisGnameLen + 10;
106
lastGname = (char *)realloc(lastGname, lastGnameAlloced); /* XXX memory leak */
109
strcpy(lastGname, thisGname);
112
grent = getgrnam(thisGname);
114
/*@-internalglobs@*/ /* FIX: shrug */
117
grent = getgrnam(thisGname);
119
/* XXX The filesystem package needs group/lock w/o getgrnam. */
120
if (strcmp(thisGname, "lock") == 0) {
126
if (strcmp(thisGname, "mail") == 0) {
135
lastGid = grent->gr_gid;
144
////////////////////////////////////////////////////////////////////
152
#include "zypp/base/Easy.h"
153
#include "zypp/base/Logger.h"
154
#include "zypp/base/Exception.h"
156
#include "zypp/target/rpm/librpmDb.h"
157
#include "zypp/target/rpm/RpmHeader.h"
158
#include "zypp/Package.h"
159
#include "zypp/PathInfo.h"
170
///////////////////////////////////////////////////////////////////
172
///////////////////////////////////////////////////////////////////
175
// METHOD NAME : RpmHeader::RpmHeader
176
// METHOD TYPE : Constructor
180
RpmHeader::RpmHeader( Header h_r )
184
///////////////////////////////////////////////////////////////////
187
// METHOD NAME : RpmHeader::RpmHeader
188
// METHOD TYPE : Constructor
190
RpmHeader::RpmHeader( BinHeader::Ptr & rhs )
194
///////////////////////////////////////////////////////////////////
197
// METHOD NAME : RpmHeader::~RpmHeader
198
// METHOD TYPE : Destructor
202
RpmHeader::~RpmHeader()
205
///////////////////////////////////////////////////////////////////
208
// METHOD NAME : RpmHeader::readPackage
209
// METHOD TYPE : constRpmHeaderPtr
211
RpmHeader::constPtr RpmHeader::readPackage( const Pathname & path_r,
212
VERIFICATION verification_r )
214
PathInfo file( path_r );
215
if ( ! file.isFile() )
217
ERR << "Not a file: " << file << endl;
218
return (RpmHeader*)0;
221
FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" );
222
if ( fd == 0 || ::Ferror(fd) )
224
ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl;
227
return (RpmHeader*)0;
230
librpmDb::globalInit();
231
rpmts ts = ::rpmtsCreate();
232
unsigned vsflag = RPMVSF_DEFAULT;
233
if ( verification_r & NODIGEST )
234
vsflag |= _RPMVSF_NODIGESTS;
235
if ( verification_r & NOSIGNATURE )
236
vsflag |= _RPMVSF_NOSIGNATURES;
237
::rpmtsSetVSFlags( ts, rpmVSFlags(vsflag) );
240
int res = ::rpmReadPackageFile( ts, fd, path_r.asString().c_str(), &nh );
248
WAR << "Error reading header from " << path_r << " error(" << res << ")" << endl;
249
return (RpmHeader*)0;
252
RpmHeader::constPtr h( new RpmHeader( nh ) );
253
headerFree( nh ); // clear the reference set in ReadPackageFile
255
MIL << h << " from " << path_r << endl;
259
///////////////////////////////////////////////////////////////////
262
// METHOD NAME : RpmHeader::dumpOn
263
// METHOD TYPE : std::ostream &
267
std::ostream & RpmHeader::dumpOn( std::ostream & str ) const
269
return BinHeader::dumpOn( str ) << '{' << tag_name() << "-"
270
<< (tag_epoch()==0?"":(tag_epoch()+":"))
272
<< (tag_release().empty()?"":(std::string("-")+tag_release()))
273
<< ( isSrc() ? ".src}" : "}");
277
///////////////////////////////////////////////////////////////////
280
// METHOD NAME : RpmHeader::isSrc
281
// METHOD TYPE : bool
283
bool RpmHeader::isSrc() const
285
return has_tag( RPMTAG_SOURCEPACKAGE );
288
bool RpmHeader::isNosrc() const
290
return has_tag( RPMTAG_SOURCEPACKAGE ) && ( has_tag( RPMTAG_NOSOURCE ) || has_tag( RPMTAG_NOPATCH ) );
293
///////////////////////////////////////////////////////////////////
296
// METHOD NAME : RpmHeader::tag_name
297
// METHOD TYPE : std::string
301
std::string RpmHeader::tag_name() const
303
return string_val( RPMTAG_NAME );
306
///////////////////////////////////////////////////////////////////
309
// METHOD NAME : RpmHeader::tag_epoch
310
// METHOD TYPE : Edition::epoch_t
314
Edition::epoch_t RpmHeader::tag_epoch() const
316
return int_val ( RPMTAG_EPOCH );
319
///////////////////////////////////////////////////////////////////
322
// METHOD NAME : RpmHeader::tag_version
323
// METHOD TYPE : std::string
327
std::string RpmHeader::tag_version() const
329
return string_val ( RPMTAG_VERSION );
332
///////////////////////////////////////////////////////////////////
335
// METHOD NAME : RpmHeader::tag_release
336
// METHOD TYPE : std::string
340
std::string RpmHeader::tag_release() const
342
return string_val( RPMTAG_RELEASE );
345
///////////////////////////////////////////////////////////////////
348
// METHOD NAME : RpmHeader::tag_edition
349
// METHOD TYPE : Edition
353
Edition RpmHeader::tag_edition () const
355
return Edition( tag_version(), tag_release(), tag_epoch() );
358
///////////////////////////////////////////////////////////////////
361
// METHOD NAME : RpmHeader::tag_arch
362
// METHOD TYPE : Arch
366
Arch RpmHeader::tag_arch() const
368
return Arch( string_val( RPMTAG_ARCH ) );
371
///////////////////////////////////////////////////////////////////
374
// METHOD NAME : RpmHeader::tag_installtime
375
// METHOD TYPE : Date
379
Date RpmHeader::tag_installtime() const
381
return int_val( RPMTAG_INSTALLTIME );
384
///////////////////////////////////////////////////////////////////
387
// METHOD NAME : RpmHeader::tag_buildtime
388
// METHOD TYPE : Date
392
Date RpmHeader::tag_buildtime() const
394
return int_val( RPMTAG_BUILDTIME );
396
#warning CHECK IF FILE REQUIRES HANDLING IS OBSOLETE
397
///////////////////////////////////////////////////////////////////
400
// METHOD NAME : RpmHeader::PkgRelList_val
401
// METHOD TYPE : CapabilitySet
405
CapabilitySet RpmHeader::PkgRelList_val( tag tag_r, bool pre, std::set<std::string> * freq_r ) const
409
rpmTag kindFlags = rpmTag(0);
410
rpmTag kindVersion = rpmTag(0);
414
case RPMTAG_REQUIRENAME:
415
kindFlags = RPMTAG_REQUIREFLAGS;
416
kindVersion = RPMTAG_REQUIREVERSION;
418
case RPMTAG_PROVIDENAME:
419
kindFlags = RPMTAG_PROVIDEFLAGS;
420
kindVersion = RPMTAG_PROVIDEVERSION;
422
case RPMTAG_OBSOLETENAME:
423
kindFlags = RPMTAG_OBSOLETEFLAGS;
424
kindVersion = RPMTAG_OBSOLETEVERSION;
426
case RPMTAG_CONFLICTNAME:
427
kindFlags = RPMTAG_CONFLICTFLAGS;
428
kindVersion = RPMTAG_CONFLICTVERSION;
430
case RPMTAG_ENHANCESNAME:
431
kindFlags = RPMTAG_ENHANCESFLAGS;
432
kindVersion = RPMTAG_ENHANCESVERSION;
434
case RPMTAG_SUGGESTSNAME:
435
kindFlags = RPMTAG_SUGGESTSFLAGS;
436
kindVersion = RPMTAG_SUGGESTSVERSION;
439
INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
445
unsigned count = string_list( tag_r, names );
450
int_list( kindFlags, flags );
453
string_list( kindVersion, versions );
455
for ( unsigned i = 0; i < count; ++i )
458
std::string n( names[i] );
461
int32_t f = flags[i];
462
std::string v = versions[i];
475
switch ( f & RPMSENSE_SENSEMASK )
480
case RPMSENSE_LESS|RPMSENSE_EQUAL:
483
case RPMSENSE_GREATER:
486
case RPMSENSE_GREATER|RPMSENSE_EQUAL:
495
if ((pre && (f & RPMSENSE_PREREQ))
496
|| ((! pre) && !(f & RPMSENSE_PREREQ)))
500
ret.insert( Capability( n, op, Edition(v) ) );
502
catch (Exception & excpt_r)
504
ZYPP_CAUGHT(excpt_r);
505
WAR << "Invalid capability: " << n << " " << op << " "
514
///////////////////////////////////////////////////////////////////
517
// METHOD NAME : RpmHeader::tag_provides
518
// METHOD TYPE : CapabilitySet
522
CapabilitySet RpmHeader::tag_provides( std::set<std::string> * freq_r ) const
524
return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
527
///////////////////////////////////////////////////////////////////
530
// METHOD NAME : RpmHeader::tag_requires
531
// METHOD TYPE : CapabilitySet
535
CapabilitySet RpmHeader::tag_requires( std::set<std::string> * freq_r ) const
537
return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
540
///////////////////////////////////////////////////////////////////
543
// METHOD NAME : RpmHeader::tag_requires
544
// METHOD TYPE : CapabilitySet
548
CapabilitySet RpmHeader::tag_prerequires( std::set<std::string> * freq_r ) const
550
return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
553
///////////////////////////////////////////////////////////////////
556
// METHOD NAME : RpmHeader::tag_conflicts
557
// METHOD TYPE : CapabilitySet
561
CapabilitySet RpmHeader::tag_conflicts( std::set<std::string> * freq_r ) const
563
return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
566
///////////////////////////////////////////////////////////////////
569
// METHOD NAME : RpmHeader::tag_obsoletes
570
// METHOD TYPE : CapabilitySet
574
CapabilitySet RpmHeader::tag_obsoletes( std::set<std::string> * freq_r ) const
576
return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
579
///////////////////////////////////////////////////////////////////
582
// METHOD NAME : RpmHeader::tag_enhances
583
// METHOD TYPE : CapabilitySet
587
CapabilitySet RpmHeader::tag_enhances( std::set<std::string> * freq_r ) const
589
return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
592
///////////////////////////////////////////////////////////////////
595
// METHOD NAME : RpmHeader::tag_suggests
596
// METHOD TYPE : CapabilitySet
600
CapabilitySet RpmHeader::tag_suggests( std::set<std::string> * freq_r ) const
602
return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r );
605
///////////////////////////////////////////////////////////////////
608
// METHOD NAME : RpmHeader::tag_size
609
// METHOD TYPE : ByteCount
613
ByteCount RpmHeader::tag_size() const
615
return int_val( RPMTAG_SIZE );
618
///////////////////////////////////////////////////////////////////
621
// METHOD NAME : RpmHeader::tag_archivesize
622
// METHOD TYPE : ByteCount
626
ByteCount RpmHeader::tag_archivesize() const
628
return int_val( RPMTAG_ARCHIVESIZE );
631
///////////////////////////////////////////////////////////////////
634
// METHOD NAME : RpmHeader::tag_summary
635
// METHOD TYPE : std::string
639
std::string RpmHeader::tag_summary() const
641
return string_val( RPMTAG_SUMMARY );
644
///////////////////////////////////////////////////////////////////
647
// METHOD NAME : RpmHeader::tag_description
648
// METHOD TYPE : std::string
652
std::string RpmHeader::tag_description() const
654
return string_val( RPMTAG_DESCRIPTION );
657
///////////////////////////////////////////////////////////////////
660
// METHOD NAME : RpmHeader::tag_group
661
// METHOD TYPE : std::string
665
std::string RpmHeader::tag_group() const
667
return string_val( RPMTAG_GROUP );
670
///////////////////////////////////////////////////////////////////
673
// METHOD NAME : RpmHeader::tag_vendor
674
// METHOD TYPE : std::string
678
std::string RpmHeader::tag_vendor() const
680
return string_val( RPMTAG_VENDOR );
683
///////////////////////////////////////////////////////////////////
686
// METHOD NAME : RpmHeader::tag_distribution
687
// METHOD TYPE : std::string
691
std::string RpmHeader::tag_distribution() const
693
return string_val( RPMTAG_DISTRIBUTION );
696
///////////////////////////////////////////////////////////////////
699
// METHOD NAME : RpmHeader::tag_license
700
// METHOD TYPE : std::string
704
std::string RpmHeader::tag_license() const
706
return string_val( RPMTAG_LICENSE );
709
///////////////////////////////////////////////////////////////////
712
// METHOD NAME : RpmHeader::tag_buildhost
713
// METHOD TYPE : std::string
717
std::string RpmHeader::tag_buildhost() const
719
return string_val( RPMTAG_BUILDHOST );
722
///////////////////////////////////////////////////////////////////
725
// METHOD NAME : RpmHeader::tag_packager
726
// METHOD TYPE : std::string
730
std::string RpmHeader::tag_packager() const
732
return string_val( RPMTAG_PACKAGER );
735
///////////////////////////////////////////////////////////////////
738
// METHOD NAME : RpmHeader::tag_url
739
// METHOD TYPE : std::string
743
std::string RpmHeader::tag_url() const
745
return string_val( RPMTAG_URL );
748
///////////////////////////////////////////////////////////////////
751
// METHOD NAME : RpmHeader::tag_os
752
// METHOD TYPE : std::string
756
std::string RpmHeader::tag_os() const
758
return string_val( RPMTAG_OS );
762
std::string RpmHeader::tag_prein() const
763
{ return string_val( RPMTAG_PREIN ); }
765
std::string RpmHeader::tag_preinprog() const
766
{ return string_val( RPMTAG_PREINPROG ); }
768
std::string RpmHeader::tag_postin() const
769
{ return string_val( RPMTAG_POSTIN ); }
771
std::string RpmHeader::tag_postinprog() const
772
{ return string_val( RPMTAG_POSTINPROG ); }
774
std::string RpmHeader::tag_preun() const
775
{ return string_val( RPMTAG_PREUN ); }
777
std::string RpmHeader::tag_preunprog() const
778
{ return string_val( RPMTAG_PREUNPROG ); }
780
std::string RpmHeader::tag_postun() const
781
{ return string_val( RPMTAG_POSTUN ); }
783
std::string RpmHeader::tag_postunprog() const
784
{ return string_val( RPMTAG_POSTUNPROG ); }
786
std::string RpmHeader::tag_pretrans() const
787
{ return string_val( RPMTAG_PRETRANS ); }
789
std::string RpmHeader::tag_pretransprog() const
790
{ return string_val( RPMTAG_PRETRANSPROG ); }
792
std::string RpmHeader::tag_posttrans() const
793
{ return string_val( RPMTAG_POSTTRANS ); }
795
std::string RpmHeader::tag_posttransprog() const
796
{ return string_val( RPMTAG_POSTTRANSPROG ); }
798
///////////////////////////////////////////////////////////////////
801
// METHOD NAME : RpmHeader::tag_sourcerpm
802
// METHOD TYPE : std::string
806
std::string RpmHeader::tag_sourcerpm() const
808
return string_val( RPMTAG_SOURCERPM );
811
///////////////////////////////////////////////////////////////////
814
// METHOD NAME : RpmHeader::tag_filenames
815
// METHOD TYPE : std::list<std::string>
819
std::list<std::string> RpmHeader::tag_filenames() const
821
std::list<std::string> ret;
823
stringList basenames;
824
if ( string_list( RPMTAG_BASENAMES, basenames ) )
827
string_list( RPMTAG_DIRNAMES, dirnames );
829
int_list( RPMTAG_DIRINDEXES, dirindexes );
830
for ( unsigned i = 0; i < basenames.size(); ++ i )
832
ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
839
///////////////////////////////////////////////////////////////////
842
// METHOD NAME : RpmHeader::tag_fileinfos
843
// METHOD TYPE : std::list<FileInfo>
847
std::list<FileInfo> RpmHeader::tag_fileinfos() const
849
std::list<FileInfo> ret;
851
stringList basenames;
852
if ( string_list( RPMTAG_BASENAMES, basenames ) )
855
string_list( RPMTAG_DIRNAMES, dirnames );
857
int_list( RPMTAG_DIRINDEXES, dirindexes );
859
int_list( RPMTAG_FILESIZES, filesizes );
861
string_list( RPMTAG_FILEMD5S, md5sums );
862
stringList usernames;
863
string_list( RPMTAG_FILEUSERNAME, usernames );
864
stringList groupnames;
865
string_list( RPMTAG_FILEGROUPNAME, groupnames );
867
int_list( RPMTAG_FILEUIDS, uids );
869
int_list( RPMTAG_FILEGIDS, gids );
871
int_list( RPMTAG_FILEMODES, filemodes );
873
int_list( RPMTAG_FILEMTIMES, filemtimes );
875
int_list( RPMTAG_FILEFLAGS, fileflags );
876
stringList filelinks;
877
string_list( RPMTAG_FILELINKTOS, filelinks );
879
for ( unsigned i = 0; i < basenames.size(); ++ i )
884
uid = unameToUid( usernames[i].c_str(), &uid );
894
gid = gnameToGid( groupnames[i].c_str(), &gid );
902
dirnames[dirindexes[i]] + basenames[i],
907
mode_t(filemodes[i]),
909
bool(fileflags[i] & RPMFILE_GHOST),
913
ret.push_back( info );
920
///////////////////////////////////////////////////////////////////
923
// METHOD NAME : RpmHeader::tag_changelog
924
// METHOD TYPE : Changelog
928
Changelog RpmHeader::tag_changelog() const
933
if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
936
string_list( RPMTAG_CHANGELOGNAME, names );
938
string_list( RPMTAG_CHANGELOGTEXT, texts );
939
for ( unsigned i = 0; i < times.size(); ++ i )
941
ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
949
} // namespace target