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 #ifdef RPMTAG_OLDSUGGESTS
431 case RPMTAG_OLDENHANCESNAME:
432 kindFlags = RPMTAG_OLDENHANCESFLAGS;
433 kindVersion = RPMTAG_OLDENHANCESVERSION;
435 case RPMTAG_OLDSUGGESTSNAME:
436 kindFlags = RPMTAG_OLDSUGGESTSFLAGS;
437 kindVersion = RPMTAG_OLDSUGGESTSVERSION;
439 case RPMTAG_RECOMMENDNAME:
440 kindFlags = RPMTAG_RECOMMENDFLAGS;
441 kindVersion = RPMTAG_RECOMMENDVERSION;
443 case RPMTAG_SUPPLEMENTNAME:
444 kindFlags = RPMTAG_SUPPLEMENTFLAGS;
445 kindVersion = RPMTAG_SUPPLEMENTVERSION;
447 case RPMTAG_SUGGESTNAME:
448 kindFlags = RPMTAG_SUGGESTFLAGS;
449 kindVersion = RPMTAG_SUGGESTVERSION;
451 case RPMTAG_ENHANCENAME:
452 kindFlags = RPMTAG_ENHANCEFLAGS;
453 kindVersion = RPMTAG_ENHANCEVERSION;
456 case RPMTAG_ENHANCESNAME:
457 kindFlags = RPMTAG_ENHANCESFLAGS;
458 kindVersion = RPMTAG_ENHANCESVERSION;
460 case RPMTAG_SUGGESTSNAME:
461 kindFlags = RPMTAG_SUGGESTSFLAGS;
462 kindVersion = RPMTAG_SUGGESTSVERSION;
466 INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
472 unsigned count = string_list( tag_r, names );
477 int_list( kindFlags, flags );
480 string_list( kindVersion, versions );
482 for ( unsigned i = 0; i < count; ++i )
485 std::string n( names[i] );
488 int32_t f = flags[i];
489 std::string v = versions[i];
502 switch ( f & RPMSENSE_SENSEMASK )
507 case RPMSENSE_LESS|RPMSENSE_EQUAL:
510 case RPMSENSE_GREATER:
513 case RPMSENSE_GREATER|RPMSENSE_EQUAL:
522 if ((pre && (f & RPMSENSE_PREREQ))
523 || ((! pre) && !(f & RPMSENSE_PREREQ)))
527 ret.insert( Capability( n, op, Edition(v) ) );
529 catch (Exception & excpt_r)
531 ZYPP_CAUGHT(excpt_r);
532 WAR << "Invalid capability: " << n << " " << op << " "
541 ///////////////////////////////////////////////////////////////////
544 // METHOD NAME : RpmHeader::tag_provides
545 // METHOD TYPE : CapabilitySet
549 CapabilitySet RpmHeader::tag_provides( std::set<std::string> * freq_r ) const
551 return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
554 ///////////////////////////////////////////////////////////////////
557 // METHOD NAME : RpmHeader::tag_requires
558 // METHOD TYPE : CapabilitySet
562 CapabilitySet RpmHeader::tag_requires( std::set<std::string> * freq_r ) const
564 return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
567 ///////////////////////////////////////////////////////////////////
570 // METHOD NAME : RpmHeader::tag_requires
571 // METHOD TYPE : CapabilitySet
575 CapabilitySet RpmHeader::tag_prerequires( std::set<std::string> * freq_r ) const
577 return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
580 ///////////////////////////////////////////////////////////////////
583 // METHOD NAME : RpmHeader::tag_conflicts
584 // METHOD TYPE : CapabilitySet
588 CapabilitySet RpmHeader::tag_conflicts( std::set<std::string> * freq_r ) const
590 return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
593 ///////////////////////////////////////////////////////////////////
596 // METHOD NAME : RpmHeader::tag_obsoletes
597 // METHOD TYPE : CapabilitySet
601 CapabilitySet RpmHeader::tag_obsoletes( std::set<std::string> * freq_r ) const
603 return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
606 ///////////////////////////////////////////////////////////////////
609 // METHOD NAME : RpmHeader::tag_enhances
610 // METHOD TYPE : CapabilitySet
614 CapabilitySet RpmHeader::tag_enhances( std::set<std::string> * freq_r ) const
616 #ifdef RPMTAG_OLDSUGGESTS
617 return PkgRelList_val( RPMTAG_ENHANCENAME, false, freq_r );
619 return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
623 ///////////////////////////////////////////////////////////////////
626 // METHOD NAME : RpmHeader::tag_suggests
627 // METHOD TYPE : CapabilitySet
631 CapabilitySet RpmHeader::tag_suggests( std::set<std::string> * freq_r ) const
633 #ifdef RPMTAG_OLDSUGGESTS
634 return PkgRelList_val( RPMTAG_SUGGESTNAME, false, freq_r );
636 return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r );
640 ///////////////////////////////////////////////////////////////////
643 // METHOD NAME : RpmHeader::tag_supplements
644 // METHOD TYPE : CapabilitySet
648 CapabilitySet RpmHeader::tag_supplements( std::set<std::string> * freq_r ) const
650 #ifdef RPMTAG_OLDSUGGESTS
651 return PkgRelList_val( RPMTAG_SUPPLEMENTNAME, false, freq_r );
653 return CapabilitySet();
657 ///////////////////////////////////////////////////////////////////
660 // METHOD NAME : RpmHeader::tag_recommends
661 // METHOD TYPE : CapabilitySet
665 CapabilitySet RpmHeader::tag_recommends( std::set<std::string> * freq_r ) const
667 #ifdef RPMTAG_OLDSUGGESTS
668 return PkgRelList_val( RPMTAG_RECOMMENDNAME, false, freq_r );
670 return CapabilitySet();
674 ///////////////////////////////////////////////////////////////////
677 // METHOD NAME : RpmHeader::tag_size
678 // METHOD TYPE : ByteCount
682 ByteCount RpmHeader::tag_size() const
684 return int_val( RPMTAG_SIZE );
687 ///////////////////////////////////////////////////////////////////
690 // METHOD NAME : RpmHeader::tag_archivesize
691 // METHOD TYPE : ByteCount
695 ByteCount RpmHeader::tag_archivesize() const
697 return int_val( RPMTAG_ARCHIVESIZE );
700 ///////////////////////////////////////////////////////////////////
703 // METHOD NAME : RpmHeader::tag_summary
704 // METHOD TYPE : std::string
708 std::string RpmHeader::tag_summary() const
710 return string_val( RPMTAG_SUMMARY );
713 ///////////////////////////////////////////////////////////////////
716 // METHOD NAME : RpmHeader::tag_description
717 // METHOD TYPE : std::string
721 std::string RpmHeader::tag_description() const
723 return string_val( RPMTAG_DESCRIPTION );
726 ///////////////////////////////////////////////////////////////////
729 // METHOD NAME : RpmHeader::tag_group
730 // METHOD TYPE : std::string
734 std::string RpmHeader::tag_group() const
736 return string_val( RPMTAG_GROUP );
739 ///////////////////////////////////////////////////////////////////
742 // METHOD NAME : RpmHeader::tag_vendor
743 // METHOD TYPE : std::string
747 std::string RpmHeader::tag_vendor() const
749 return string_val( RPMTAG_VENDOR );
752 ///////////////////////////////////////////////////////////////////
755 // METHOD NAME : RpmHeader::tag_distribution
756 // METHOD TYPE : std::string
760 std::string RpmHeader::tag_distribution() const
762 return string_val( RPMTAG_DISTRIBUTION );
765 ///////////////////////////////////////////////////////////////////
768 // METHOD NAME : RpmHeader::tag_license
769 // METHOD TYPE : std::string
773 std::string RpmHeader::tag_license() const
775 return string_val( RPMTAG_LICENSE );
778 ///////////////////////////////////////////////////////////////////
781 // METHOD NAME : RpmHeader::tag_buildhost
782 // METHOD TYPE : std::string
786 std::string RpmHeader::tag_buildhost() const
788 return string_val( RPMTAG_BUILDHOST );
791 ///////////////////////////////////////////////////////////////////
794 // METHOD NAME : RpmHeader::tag_packager
795 // METHOD TYPE : std::string
799 std::string RpmHeader::tag_packager() const
801 return string_val( RPMTAG_PACKAGER );
804 ///////////////////////////////////////////////////////////////////
807 // METHOD NAME : RpmHeader::tag_url
808 // METHOD TYPE : std::string
812 std::string RpmHeader::tag_url() const
814 return string_val( RPMTAG_URL );
817 ///////////////////////////////////////////////////////////////////
820 // METHOD NAME : RpmHeader::tag_os
821 // METHOD TYPE : std::string
825 std::string RpmHeader::tag_os() const
827 return string_val( RPMTAG_OS );
831 std::string RpmHeader::tag_prein() const
832 { return string_val( RPMTAG_PREIN ); }
834 std::string RpmHeader::tag_preinprog() const
835 { return string_val( RPMTAG_PREINPROG ); }
837 std::string RpmHeader::tag_postin() const
838 { return string_val( RPMTAG_POSTIN ); }
840 std::string RpmHeader::tag_postinprog() const
841 { return string_val( RPMTAG_POSTINPROG ); }
843 std::string RpmHeader::tag_preun() const
844 { return string_val( RPMTAG_PREUN ); }
846 std::string RpmHeader::tag_preunprog() const
847 { return string_val( RPMTAG_PREUNPROG ); }
849 std::string RpmHeader::tag_postun() const
850 { return string_val( RPMTAG_POSTUN ); }
852 std::string RpmHeader::tag_postunprog() const
853 { return string_val( RPMTAG_POSTUNPROG ); }
855 std::string RpmHeader::tag_pretrans() const
856 { return string_val( RPMTAG_PRETRANS ); }
858 std::string RpmHeader::tag_pretransprog() const
859 { return string_val( RPMTAG_PRETRANSPROG ); }
861 std::string RpmHeader::tag_posttrans() const
862 { return string_val( RPMTAG_POSTTRANS ); }
864 std::string RpmHeader::tag_posttransprog() const
865 { return string_val( RPMTAG_POSTTRANSPROG ); }
867 ///////////////////////////////////////////////////////////////////
870 // METHOD NAME : RpmHeader::tag_sourcerpm
871 // METHOD TYPE : std::string
875 std::string RpmHeader::tag_sourcerpm() const
877 return string_val( RPMTAG_SOURCERPM );
880 ///////////////////////////////////////////////////////////////////
883 // METHOD NAME : RpmHeader::tag_filenames
884 // METHOD TYPE : std::list<std::string>
888 std::list<std::string> RpmHeader::tag_filenames() const
890 std::list<std::string> ret;
892 stringList basenames;
893 if ( string_list( RPMTAG_BASENAMES, basenames ) )
896 string_list( RPMTAG_DIRNAMES, dirnames );
898 int_list( RPMTAG_DIRINDEXES, dirindexes );
899 for ( unsigned i = 0; i < basenames.size(); ++ i )
901 ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
908 ///////////////////////////////////////////////////////////////////
911 // METHOD NAME : RpmHeader::tag_fileinfos
912 // METHOD TYPE : std::list<FileInfo>
916 std::list<FileInfo> RpmHeader::tag_fileinfos() const
918 std::list<FileInfo> ret;
920 stringList basenames;
921 if ( string_list( RPMTAG_BASENAMES, basenames ) )
924 string_list( RPMTAG_DIRNAMES, dirnames );
926 int_list( RPMTAG_DIRINDEXES, dirindexes );
928 int_list( RPMTAG_FILESIZES, filesizes );
930 string_list( RPMTAG_FILEMD5S, md5sums );
931 stringList usernames;
932 string_list( RPMTAG_FILEUSERNAME, usernames );
933 stringList groupnames;
934 string_list( RPMTAG_FILEGROUPNAME, groupnames );
936 int_list( RPMTAG_FILEUIDS, uids );
938 int_list( RPMTAG_FILEGIDS, gids );
940 int_list( RPMTAG_FILEMODES, filemodes );
942 int_list( RPMTAG_FILEMTIMES, filemtimes );
944 int_list( RPMTAG_FILEFLAGS, fileflags );
945 stringList filelinks;
946 string_list( RPMTAG_FILELINKTOS, filelinks );
948 for ( unsigned i = 0; i < basenames.size(); ++ i )
953 uid = unameToUid( usernames[i].c_str(), &uid );
963 gid = gnameToGid( groupnames[i].c_str(), &gid );
971 dirnames[dirindexes[i]] + basenames[i],
976 mode_t(filemodes[i]),
978 bool(fileflags[i] & RPMFILE_GHOST),
982 ret.push_back( info );
989 ///////////////////////////////////////////////////////////////////
992 // METHOD NAME : RpmHeader::tag_changelog
993 // METHOD TYPE : Changelog
997 Changelog RpmHeader::tag_changelog() const
1002 if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
1005 string_list( RPMTAG_CHANGELOGNAME, names );
1007 string_list( RPMTAG_CHANGELOGTEXT, texts );
1008 for ( unsigned i = 0; i < times.size(); ++ i )
1010 ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
1018 } // namespace target