1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/rpm/RpmHeader.cc
14 ////////////////////////////////////////////////////////////////////
15 // unameToUid and gnameToGid are shamelessly stolen from rpm-4.4.
16 // (rpmio/ugid.c) Those functions were dropped in RPM_4_7
22 /* unameToUid(), uidTouname() and the group variants are really poorly
23 implemented. They really ought to use hash tables. I just made the
24 guess that most files would be owned by root or the same person/group
25 who owned the last file. Those two values are cached, everything else
26 is looked up via getpw() and getgr() functions. If this performs
27 too poorly I'll have to implement it properly :-( */
29 int unameToUid(const char * thisUname, uid_t * uid)
31 /*@only@*/ static char * lastUname = NULL;
32 static size_t lastUnameLen = 0;
33 static size_t lastUnameAlloced;
35 struct passwd * pwent;
41 } else if (strcmp(thisUname, "root") == 0) {
48 thisUnameLen = strlen(thisUname);
49 if (lastUname == NULL || thisUnameLen != lastUnameLen ||
50 strcmp(thisUname, lastUname) != 0)
52 if (lastUnameAlloced < thisUnameLen + 1) {
53 lastUnameAlloced = thisUnameLen + 10;
54 lastUname = (char *)realloc(lastUname, lastUnameAlloced); /* XXX memory leak */
57 strcpy(lastUname, thisUname);
60 pwent = getpwnam(thisUname);
62 /*@-internalglobs@*/ /* FIX: shrug */
65 pwent = getpwnam(thisUname);
66 if (pwent == NULL) return -1;
69 lastUid = pwent->pw_uid;
79 int gnameToGid(const char * thisGname, gid_t * gid)
81 /*@only@*/ static char * lastGname = NULL;
82 static size_t lastGnameLen = 0;
83 static size_t lastGnameAlloced;
88 if (thisGname == NULL) {
91 } else if (strcmp(thisGname, "root") == 0) {
98 thisGnameLen = strlen(thisGname);
99 if (lastGname == NULL || thisGnameLen != lastGnameLen ||
100 strcmp(thisGname, lastGname) != 0)
102 if (lastGnameAlloced < thisGnameLen + 1) {
103 lastGnameAlloced = thisGnameLen + 10;
104 lastGname = (char *)realloc(lastGname, lastGnameAlloced); /* XXX memory leak */
107 strcpy(lastGname, thisGname);
110 grent = getgrnam(thisGname);
112 /*@-internalglobs@*/ /* FIX: shrug */
115 grent = getgrnam(thisGname);
117 /* XXX The filesystem package needs group/lock w/o getgrnam. */
118 if (strcmp(thisGname, "lock") == 0) {
124 if (strcmp(thisGname, "mail") == 0) {
133 lastGid = grent->gr_gid;
142 ////////////////////////////////////////////////////////////////////
149 #include <zypp/base/Easy.h>
150 #include <zypp/base/Logger.h>
151 #include <zypp/base/Exception.h>
153 #include <zypp/target/rpm/librpmDb.h>
154 #include <zypp/target/rpm/RpmHeader.h>
155 #include <zypp/Package.h>
156 #include <zypp/PathInfo.h>
167 ///////////////////////////////////////////////////////////////////
169 ///////////////////////////////////////////////////////////////////
172 // METHOD NAME : RpmHeader::RpmHeader
173 // METHOD TYPE : Constructor
177 RpmHeader::RpmHeader( Header h_r )
181 ///////////////////////////////////////////////////////////////////
184 // METHOD NAME : RpmHeader::RpmHeader
185 // METHOD TYPE : Constructor
187 RpmHeader::RpmHeader( BinHeader::Ptr & rhs )
191 ///////////////////////////////////////////////////////////////////
194 // METHOD NAME : RpmHeader::~RpmHeader
195 // METHOD TYPE : Destructor
199 RpmHeader::~RpmHeader()
202 ///////////////////////////////////////////////////////////////////
205 // METHOD NAME : RpmHeader::readPackage
206 // METHOD TYPE : constRpmHeaderPtr
208 RpmHeader::constPtr RpmHeader::readPackage( const Pathname & path_r,
209 VERIFICATION verification_r )
211 PathInfo file( path_r );
212 if ( ! file.isFile() )
214 ERR << "Not a file: " << file << endl;
215 return (RpmHeader*)0;
218 FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" );
219 if ( fd == 0 || ::Ferror(fd) )
221 ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl;
224 return (RpmHeader*)0;
227 librpmDb::globalInit();
228 rpmts ts = ::rpmtsCreate();
229 unsigned vsflag = RPMVSF_DEFAULT;
230 if ( verification_r & NODIGEST )
231 vsflag |= _RPMVSF_NODIGESTS;
232 if ( verification_r & NOSIGNATURE )
233 vsflag |= _RPMVSF_NOSIGNATURES;
234 ::rpmtsSetVSFlags( ts, rpmVSFlags(vsflag) );
237 int res = ::rpmReadPackageFile( ts, fd, path_r.asString().c_str(), &nh );
245 WAR << "Error reading header from " << path_r << " error(" << res << ")" << endl;
246 return (RpmHeader*)0;
249 RpmHeader::constPtr h( new RpmHeader( nh ) );
250 headerFree( nh ); // clear the reference set in ReadPackageFile
252 MIL << h << " from " << path_r << endl;
256 ///////////////////////////////////////////////////////////////////
259 // METHOD NAME : RpmHeader::dumpOn
260 // METHOD TYPE : std::ostream &
264 std::ostream & RpmHeader::dumpOn( std::ostream & str ) const
266 BinHeader::dumpOn( str ) << '{' << tag_name() << "-";
267 if ( tag_epoch() != 0 )
268 str << tag_epoch() << ":";
270 << (tag_release().empty()?"":(std::string("-")+tag_release()))
271 << ( isSrc() ? ".src}" : "}");
276 ///////////////////////////////////////////////////////////////////
279 // METHOD NAME : RpmHeader::isSrc
280 // METHOD TYPE : bool
282 bool RpmHeader::isSrc() const
284 return has_tag( RPMTAG_SOURCEPACKAGE );
287 bool RpmHeader::isNosrc() const
289 return has_tag( RPMTAG_SOURCEPACKAGE ) && ( has_tag( RPMTAG_NOSOURCE ) || has_tag( RPMTAG_NOPATCH ) );
292 ///////////////////////////////////////////////////////////////////
295 // METHOD NAME : RpmHeader::tag_name
296 // METHOD TYPE : std::string
300 std::string RpmHeader::tag_name() const
302 return string_val( RPMTAG_NAME );
305 ///////////////////////////////////////////////////////////////////
308 // METHOD NAME : RpmHeader::tag_epoch
309 // METHOD TYPE : Edition::epoch_t
313 Edition::epoch_t RpmHeader::tag_epoch() const
315 return int_val ( RPMTAG_EPOCH );
318 ///////////////////////////////////////////////////////////////////
321 // METHOD NAME : RpmHeader::tag_version
322 // METHOD TYPE : std::string
326 std::string RpmHeader::tag_version() const
328 return string_val ( RPMTAG_VERSION );
331 ///////////////////////////////////////////////////////////////////
334 // METHOD NAME : RpmHeader::tag_release
335 // METHOD TYPE : std::string
339 std::string RpmHeader::tag_release() const
341 return string_val( RPMTAG_RELEASE );
344 ///////////////////////////////////////////////////////////////////
347 // METHOD NAME : RpmHeader::tag_edition
348 // METHOD TYPE : Edition
352 Edition RpmHeader::tag_edition () const
354 return Edition( tag_version(), tag_release(), tag_epoch() );
357 ///////////////////////////////////////////////////////////////////
360 // METHOD NAME : RpmHeader::tag_arch
361 // METHOD TYPE : Arch
365 Arch RpmHeader::tag_arch() const
367 return Arch( string_val( RPMTAG_ARCH ) );
370 ///////////////////////////////////////////////////////////////////
373 // METHOD NAME : RpmHeader::tag_installtime
374 // METHOD TYPE : Date
378 Date RpmHeader::tag_installtime() const
380 return int_val( RPMTAG_INSTALLTIME );
383 ///////////////////////////////////////////////////////////////////
386 // METHOD NAME : RpmHeader::tag_buildtime
387 // METHOD TYPE : Date
391 Date RpmHeader::tag_buildtime() const
393 return int_val( RPMTAG_BUILDTIME );
395 #warning CHECK IF FILE REQUIRES HANDLING IS OBSOLETE
396 ///////////////////////////////////////////////////////////////////
399 // METHOD NAME : RpmHeader::PkgRelList_val
400 // METHOD TYPE : CapabilitySet
404 CapabilitySet RpmHeader::PkgRelList_val( tag tag_r, bool pre, std::set<std::string> * freq_r ) const
408 rpmTag kindFlags = rpmTag(0);
409 rpmTag kindVersion = rpmTag(0);
413 case RPMTAG_REQUIRENAME:
414 kindFlags = RPMTAG_REQUIREFLAGS;
415 kindVersion = RPMTAG_REQUIREVERSION;
417 case RPMTAG_PROVIDENAME:
418 kindFlags = RPMTAG_PROVIDEFLAGS;
419 kindVersion = RPMTAG_PROVIDEVERSION;
421 case RPMTAG_OBSOLETENAME:
422 kindFlags = RPMTAG_OBSOLETEFLAGS;
423 kindVersion = RPMTAG_OBSOLETEVERSION;
425 case RPMTAG_CONFLICTNAME:
426 kindFlags = RPMTAG_CONFLICTFLAGS;
427 kindVersion = RPMTAG_CONFLICTVERSION;
429 #ifdef RPMTAG_OLDSUGGESTS
430 case RPMTAG_OLDENHANCESNAME:
431 kindFlags = RPMTAG_OLDENHANCESFLAGS;
432 kindVersion = RPMTAG_OLDENHANCESVERSION;
434 case RPMTAG_OLDSUGGESTSNAME:
435 kindFlags = RPMTAG_OLDSUGGESTSFLAGS;
436 kindVersion = RPMTAG_OLDSUGGESTSVERSION;
438 case RPMTAG_RECOMMENDNAME:
439 kindFlags = RPMTAG_RECOMMENDFLAGS;
440 kindVersion = RPMTAG_RECOMMENDVERSION;
442 case RPMTAG_SUPPLEMENTNAME:
443 kindFlags = RPMTAG_SUPPLEMENTFLAGS;
444 kindVersion = RPMTAG_SUPPLEMENTVERSION;
446 case RPMTAG_SUGGESTNAME:
447 kindFlags = RPMTAG_SUGGESTFLAGS;
448 kindVersion = RPMTAG_SUGGESTVERSION;
450 case RPMTAG_ENHANCENAME:
451 kindFlags = RPMTAG_ENHANCEFLAGS;
452 kindVersion = RPMTAG_ENHANCEVERSION;
455 case RPMTAG_ENHANCESNAME:
456 kindFlags = RPMTAG_ENHANCESFLAGS;
457 kindVersion = RPMTAG_ENHANCESVERSION;
459 case RPMTAG_SUGGESTSNAME:
460 kindFlags = RPMTAG_SUGGESTSFLAGS;
461 kindVersion = RPMTAG_SUGGESTSVERSION;
465 INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
471 unsigned count = string_list( tag_r, names );
476 int_list( kindFlags, flags );
479 string_list( kindVersion, versions );
481 for ( unsigned i = 0; i < count; ++i )
484 std::string n( names[i] );
487 int32_t f = flags[i];
488 std::string v = versions[i];
501 switch ( f & RPMSENSE_SENSEMASK )
506 case RPMSENSE_LESS|RPMSENSE_EQUAL:
509 case RPMSENSE_GREATER:
512 case RPMSENSE_GREATER|RPMSENSE_EQUAL:
521 if ((pre && (f & RPMSENSE_PREREQ))
522 || ((! pre) && !(f & RPMSENSE_PREREQ)))
526 ret.insert( Capability( n, op, Edition(v) ) );
528 catch (Exception & excpt_r)
530 ZYPP_CAUGHT(excpt_r);
531 WAR << "Invalid capability: " << n << " " << op << " "
540 ///////////////////////////////////////////////////////////////////
543 // METHOD NAME : RpmHeader::tag_provides
544 // METHOD TYPE : CapabilitySet
548 CapabilitySet RpmHeader::tag_provides( std::set<std::string> * freq_r ) const
550 return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
553 ///////////////////////////////////////////////////////////////////
556 // METHOD NAME : RpmHeader::tag_requires
557 // METHOD TYPE : CapabilitySet
561 CapabilitySet RpmHeader::tag_requires( std::set<std::string> * freq_r ) const
563 return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
566 ///////////////////////////////////////////////////////////////////
569 // METHOD NAME : RpmHeader::tag_requires
570 // METHOD TYPE : CapabilitySet
574 CapabilitySet RpmHeader::tag_prerequires( std::set<std::string> * freq_r ) const
576 return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
579 ///////////////////////////////////////////////////////////////////
582 // METHOD NAME : RpmHeader::tag_conflicts
583 // METHOD TYPE : CapabilitySet
587 CapabilitySet RpmHeader::tag_conflicts( std::set<std::string> * freq_r ) const
589 return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
592 ///////////////////////////////////////////////////////////////////
595 // METHOD NAME : RpmHeader::tag_obsoletes
596 // METHOD TYPE : CapabilitySet
600 CapabilitySet RpmHeader::tag_obsoletes( std::set<std::string> * freq_r ) const
602 return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
605 ///////////////////////////////////////////////////////////////////
608 // METHOD NAME : RpmHeader::tag_enhances
609 // METHOD TYPE : CapabilitySet
613 CapabilitySet RpmHeader::tag_enhances( std::set<std::string> * freq_r ) const
615 #ifdef RPMTAG_OLDSUGGESTS
616 return PkgRelList_val( RPMTAG_ENHANCENAME, false, freq_r );
618 return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
622 ///////////////////////////////////////////////////////////////////
625 // METHOD NAME : RpmHeader::tag_suggests
626 // METHOD TYPE : CapabilitySet
630 CapabilitySet RpmHeader::tag_suggests( std::set<std::string> * freq_r ) const
632 #ifdef RPMTAG_OLDSUGGESTS
633 return PkgRelList_val( RPMTAG_SUGGESTNAME, false, freq_r );
635 return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r );
639 ///////////////////////////////////////////////////////////////////
642 // METHOD NAME : RpmHeader::tag_supplements
643 // METHOD TYPE : CapabilitySet
647 CapabilitySet RpmHeader::tag_supplements( std::set<std::string> * freq_r ) const
649 #ifdef RPMTAG_OLDSUGGESTS
650 return PkgRelList_val( RPMTAG_SUPPLEMENTNAME, false, freq_r );
652 return CapabilitySet();
656 ///////////////////////////////////////////////////////////////////
659 // METHOD NAME : RpmHeader::tag_recommends
660 // METHOD TYPE : CapabilitySet
664 CapabilitySet RpmHeader::tag_recommends( std::set<std::string> * freq_r ) const
666 #ifdef RPMTAG_OLDSUGGESTS
667 return PkgRelList_val( RPMTAG_RECOMMENDNAME, false, freq_r );
669 return CapabilitySet();
673 ///////////////////////////////////////////////////////////////////
676 // METHOD NAME : RpmHeader::tag_size
677 // METHOD TYPE : ByteCount
681 ByteCount RpmHeader::tag_size() const
683 return int_val( RPMTAG_SIZE );
686 ///////////////////////////////////////////////////////////////////
689 // METHOD NAME : RpmHeader::tag_archivesize
690 // METHOD TYPE : ByteCount
694 ByteCount RpmHeader::tag_archivesize() const
696 return int_val( RPMTAG_ARCHIVESIZE );
699 ///////////////////////////////////////////////////////////////////
702 // METHOD NAME : RpmHeader::tag_summary
703 // METHOD TYPE : std::string
707 std::string RpmHeader::tag_summary() const
709 return string_val( RPMTAG_SUMMARY );
712 ///////////////////////////////////////////////////////////////////
715 // METHOD NAME : RpmHeader::tag_description
716 // METHOD TYPE : std::string
720 std::string RpmHeader::tag_description() const
722 return string_val( RPMTAG_DESCRIPTION );
725 ///////////////////////////////////////////////////////////////////
728 // METHOD NAME : RpmHeader::tag_group
729 // METHOD TYPE : std::string
733 std::string RpmHeader::tag_group() const
735 return string_val( RPMTAG_GROUP );
738 ///////////////////////////////////////////////////////////////////
741 // METHOD NAME : RpmHeader::tag_vendor
742 // METHOD TYPE : std::string
746 std::string RpmHeader::tag_vendor() const
748 return string_val( RPMTAG_VENDOR );
751 ///////////////////////////////////////////////////////////////////
754 // METHOD NAME : RpmHeader::tag_distribution
755 // METHOD TYPE : std::string
759 std::string RpmHeader::tag_distribution() const
761 return string_val( RPMTAG_DISTRIBUTION );
764 ///////////////////////////////////////////////////////////////////
767 // METHOD NAME : RpmHeader::tag_license
768 // METHOD TYPE : std::string
772 std::string RpmHeader::tag_license() const
774 return string_val( RPMTAG_LICENSE );
777 ///////////////////////////////////////////////////////////////////
780 // METHOD NAME : RpmHeader::tag_buildhost
781 // METHOD TYPE : std::string
785 std::string RpmHeader::tag_buildhost() const
787 return string_val( RPMTAG_BUILDHOST );
790 ///////////////////////////////////////////////////////////////////
793 // METHOD NAME : RpmHeader::tag_packager
794 // METHOD TYPE : std::string
798 std::string RpmHeader::tag_packager() const
800 return string_val( RPMTAG_PACKAGER );
803 ///////////////////////////////////////////////////////////////////
806 // METHOD NAME : RpmHeader::tag_url
807 // METHOD TYPE : std::string
811 std::string RpmHeader::tag_url() const
813 return string_val( RPMTAG_URL );
816 ///////////////////////////////////////////////////////////////////
819 // METHOD NAME : RpmHeader::tag_os
820 // METHOD TYPE : std::string
824 std::string RpmHeader::tag_os() const
826 return string_val( RPMTAG_OS );
830 std::string RpmHeader::tag_prein() const
831 { return string_val( RPMTAG_PREIN ); }
833 std::string RpmHeader::tag_preinprog() const
834 { return string_val( RPMTAG_PREINPROG ); }
836 std::string RpmHeader::tag_postin() const
837 { return string_val( RPMTAG_POSTIN ); }
839 std::string RpmHeader::tag_postinprog() const
840 { return string_val( RPMTAG_POSTINPROG ); }
842 std::string RpmHeader::tag_preun() const
843 { return string_val( RPMTAG_PREUN ); }
845 std::string RpmHeader::tag_preunprog() const
846 { return string_val( RPMTAG_PREUNPROG ); }
848 std::string RpmHeader::tag_postun() const
849 { return string_val( RPMTAG_POSTUN ); }
851 std::string RpmHeader::tag_postunprog() const
852 { return string_val( RPMTAG_POSTUNPROG ); }
854 std::string RpmHeader::tag_pretrans() const
855 { return string_val( RPMTAG_PRETRANS ); }
857 std::string RpmHeader::tag_pretransprog() const
858 { return string_val( RPMTAG_PRETRANSPROG ); }
860 std::string RpmHeader::tag_posttrans() const
861 { return string_val( RPMTAG_POSTTRANS ); }
863 std::string RpmHeader::tag_posttransprog() const
864 { return string_val( RPMTAG_POSTTRANSPROG ); }
866 ///////////////////////////////////////////////////////////////////
869 // METHOD NAME : RpmHeader::tag_sourcerpm
870 // METHOD TYPE : std::string
874 std::string RpmHeader::tag_sourcerpm() const
876 return string_val( RPMTAG_SOURCERPM );
879 std::string RpmHeader::signatureKeyID() const
881 std::string sigInfo = format("%|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|");
883 //no signature, return empty string
884 if ( sigInfo == "(none)" )
885 return std::string();
887 std::vector<std::string> words;
888 str::split( sigInfo, std::back_inserter(words), ",");
889 if ( words.size() < 3)
890 return std::string();
892 const std::string &keyId = words[2];
893 if ( !str::startsWith(keyId, " Key ID "))
894 return std::string();
896 return str::toUpper( words[2].substr(8) );
899 ///////////////////////////////////////////////////////////////////
902 // METHOD NAME : RpmHeader::tag_filenames
903 // METHOD TYPE : std::list<std::string>
907 std::list<std::string> RpmHeader::tag_filenames() const
909 std::list<std::string> ret;
911 stringList basenames;
912 if ( string_list( RPMTAG_BASENAMES, basenames ) )
915 string_list( RPMTAG_DIRNAMES, dirnames );
917 int_list( RPMTAG_DIRINDEXES, dirindexes );
918 for ( unsigned i = 0; i < basenames.size(); ++ i )
920 ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
927 ///////////////////////////////////////////////////////////////////
930 // METHOD NAME : RpmHeader::tag_fileinfos
931 // METHOD TYPE : std::list<FileInfo>
935 std::list<FileInfo> RpmHeader::tag_fileinfos() const
937 std::list<FileInfo> ret;
939 stringList basenames;
940 if ( string_list( RPMTAG_BASENAMES, basenames ) )
943 string_list( RPMTAG_DIRNAMES, dirnames );
945 int_list( RPMTAG_DIRINDEXES, dirindexes );
947 int_list( RPMTAG_FILESIZES, filesizes );
949 string_list( RPMTAG_FILEMD5S, md5sums );
950 stringList usernames;
951 string_list( RPMTAG_FILEUSERNAME, usernames );
952 stringList groupnames;
953 string_list( RPMTAG_FILEGROUPNAME, groupnames );
955 int_list( RPMTAG_FILEUIDS, uids );
957 int_list( RPMTAG_FILEGIDS, gids );
959 int_list( RPMTAG_FILEMODES, filemodes );
961 int_list( RPMTAG_FILEMTIMES, filemtimes );
963 int_list( RPMTAG_FILEFLAGS, fileflags );
964 stringList filelinks;
965 string_list( RPMTAG_FILELINKTOS, filelinks );
967 for ( unsigned i = 0; i < basenames.size(); ++ i )
972 uid = unameToUid( usernames[i].c_str(), &uid );
982 gid = gnameToGid( groupnames[i].c_str(), &gid );
990 dirnames[dirindexes[i]] + basenames[i],
995 mode_t(filemodes[i]),
997 bool(fileflags[i] & RPMFILE_GHOST),
1001 ret.push_back( info );
1008 ///////////////////////////////////////////////////////////////////
1011 // METHOD NAME : RpmHeader::tag_changelog
1012 // METHOD TYPE : Changelog
1016 Changelog RpmHeader::tag_changelog() const
1021 if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
1024 string_list( RPMTAG_CHANGELOGNAME, names );
1026 string_list( RPMTAG_CHANGELOGTEXT, texts );
1027 for ( unsigned i = 0; i < times.size(); ++ i )
1029 ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
1037 } // namespace target