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 str << BinHeader::dumpOn( str ) << '{' << tag_name() << "-";
270 if ( tag_epoch() != 0 )
271 str << tag_epoch() << ":";
273 << (tag_release().empty()?"":(std::string("-")+tag_release()))
274 << ( isSrc() ? ".src}" : "}");
279 ///////////////////////////////////////////////////////////////////
282 // METHOD NAME : RpmHeader::isSrc
283 // METHOD TYPE : bool
285 bool RpmHeader::isSrc() const
287 return has_tag( RPMTAG_SOURCEPACKAGE );
290 bool RpmHeader::isNosrc() const
292 return has_tag( RPMTAG_SOURCEPACKAGE ) && ( has_tag( RPMTAG_NOSOURCE ) || has_tag( RPMTAG_NOPATCH ) );
295 ///////////////////////////////////////////////////////////////////
298 // METHOD NAME : RpmHeader::tag_name
299 // METHOD TYPE : std::string
303 std::string RpmHeader::tag_name() const
305 return string_val( RPMTAG_NAME );
308 ///////////////////////////////////////////////////////////////////
311 // METHOD NAME : RpmHeader::tag_epoch
312 // METHOD TYPE : Edition::epoch_t
316 Edition::epoch_t RpmHeader::tag_epoch() const
318 return int_val ( RPMTAG_EPOCH );
321 ///////////////////////////////////////////////////////////////////
324 // METHOD NAME : RpmHeader::tag_version
325 // METHOD TYPE : std::string
329 std::string RpmHeader::tag_version() const
331 return string_val ( RPMTAG_VERSION );
334 ///////////////////////////////////////////////////////////////////
337 // METHOD NAME : RpmHeader::tag_release
338 // METHOD TYPE : std::string
342 std::string RpmHeader::tag_release() const
344 return string_val( RPMTAG_RELEASE );
347 ///////////////////////////////////////////////////////////////////
350 // METHOD NAME : RpmHeader::tag_edition
351 // METHOD TYPE : Edition
355 Edition RpmHeader::tag_edition () const
357 return Edition( tag_version(), tag_release(), tag_epoch() );
360 ///////////////////////////////////////////////////////////////////
363 // METHOD NAME : RpmHeader::tag_arch
364 // METHOD TYPE : Arch
368 Arch RpmHeader::tag_arch() const
370 return Arch( string_val( RPMTAG_ARCH ) );
373 ///////////////////////////////////////////////////////////////////
376 // METHOD NAME : RpmHeader::tag_installtime
377 // METHOD TYPE : Date
381 Date RpmHeader::tag_installtime() const
383 return int_val( RPMTAG_INSTALLTIME );
386 ///////////////////////////////////////////////////////////////////
389 // METHOD NAME : RpmHeader::tag_buildtime
390 // METHOD TYPE : Date
394 Date RpmHeader::tag_buildtime() const
396 return int_val( RPMTAG_BUILDTIME );
398 #warning CHECK IF FILE REQUIRES HANDLING IS OBSOLETE
399 ///////////////////////////////////////////////////////////////////
402 // METHOD NAME : RpmHeader::PkgRelList_val
403 // METHOD TYPE : CapabilitySet
407 CapabilitySet RpmHeader::PkgRelList_val( tag tag_r, bool pre, std::set<std::string> * freq_r ) const
411 rpmTag kindFlags = rpmTag(0);
412 rpmTag kindVersion = rpmTag(0);
416 case RPMTAG_REQUIRENAME:
417 kindFlags = RPMTAG_REQUIREFLAGS;
418 kindVersion = RPMTAG_REQUIREVERSION;
420 case RPMTAG_PROVIDENAME:
421 kindFlags = RPMTAG_PROVIDEFLAGS;
422 kindVersion = RPMTAG_PROVIDEVERSION;
424 case RPMTAG_OBSOLETENAME:
425 kindFlags = RPMTAG_OBSOLETEFLAGS;
426 kindVersion = RPMTAG_OBSOLETEVERSION;
428 case RPMTAG_CONFLICTNAME:
429 kindFlags = RPMTAG_CONFLICTFLAGS;
430 kindVersion = RPMTAG_CONFLICTVERSION;
432 #ifdef RPMTAG_OLDSUGGESTS
433 case RPMTAG_OLDENHANCESNAME:
434 kindFlags = RPMTAG_OLDENHANCESFLAGS;
435 kindVersion = RPMTAG_OLDENHANCESVERSION;
437 case RPMTAG_OLDSUGGESTSNAME:
438 kindFlags = RPMTAG_OLDSUGGESTSFLAGS;
439 kindVersion = RPMTAG_OLDSUGGESTSVERSION;
441 case RPMTAG_RECOMMENDNAME:
442 kindFlags = RPMTAG_RECOMMENDFLAGS;
443 kindVersion = RPMTAG_RECOMMENDVERSION;
445 case RPMTAG_SUPPLEMENTNAME:
446 kindFlags = RPMTAG_SUPPLEMENTFLAGS;
447 kindVersion = RPMTAG_SUPPLEMENTVERSION;
449 case RPMTAG_SUGGESTNAME:
450 kindFlags = RPMTAG_SUGGESTFLAGS;
451 kindVersion = RPMTAG_SUGGESTVERSION;
453 case RPMTAG_ENHANCENAME:
454 kindFlags = RPMTAG_ENHANCEFLAGS;
455 kindVersion = RPMTAG_ENHANCEVERSION;
458 case RPMTAG_ENHANCESNAME:
459 kindFlags = RPMTAG_ENHANCESFLAGS;
460 kindVersion = RPMTAG_ENHANCESVERSION;
462 case RPMTAG_SUGGESTSNAME:
463 kindFlags = RPMTAG_SUGGESTSFLAGS;
464 kindVersion = RPMTAG_SUGGESTSVERSION;
468 INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
474 unsigned count = string_list( tag_r, names );
479 int_list( kindFlags, flags );
482 string_list( kindVersion, versions );
484 for ( unsigned i = 0; i < count; ++i )
487 std::string n( names[i] );
490 int32_t f = flags[i];
491 std::string v = versions[i];
504 switch ( f & RPMSENSE_SENSEMASK )
509 case RPMSENSE_LESS|RPMSENSE_EQUAL:
512 case RPMSENSE_GREATER:
515 case RPMSENSE_GREATER|RPMSENSE_EQUAL:
524 if ((pre && (f & RPMSENSE_PREREQ))
525 || ((! pre) && !(f & RPMSENSE_PREREQ)))
529 ret.insert( Capability( n, op, Edition(v) ) );
531 catch (Exception & excpt_r)
533 ZYPP_CAUGHT(excpt_r);
534 WAR << "Invalid capability: " << n << " " << op << " "
543 ///////////////////////////////////////////////////////////////////
546 // METHOD NAME : RpmHeader::tag_provides
547 // METHOD TYPE : CapabilitySet
551 CapabilitySet RpmHeader::tag_provides( std::set<std::string> * freq_r ) const
553 return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
556 ///////////////////////////////////////////////////////////////////
559 // METHOD NAME : RpmHeader::tag_requires
560 // METHOD TYPE : CapabilitySet
564 CapabilitySet RpmHeader::tag_requires( std::set<std::string> * freq_r ) const
566 return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
569 ///////////////////////////////////////////////////////////////////
572 // METHOD NAME : RpmHeader::tag_requires
573 // METHOD TYPE : CapabilitySet
577 CapabilitySet RpmHeader::tag_prerequires( std::set<std::string> * freq_r ) const
579 return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
582 ///////////////////////////////////////////////////////////////////
585 // METHOD NAME : RpmHeader::tag_conflicts
586 // METHOD TYPE : CapabilitySet
590 CapabilitySet RpmHeader::tag_conflicts( std::set<std::string> * freq_r ) const
592 return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
595 ///////////////////////////////////////////////////////////////////
598 // METHOD NAME : RpmHeader::tag_obsoletes
599 // METHOD TYPE : CapabilitySet
603 CapabilitySet RpmHeader::tag_obsoletes( std::set<std::string> * freq_r ) const
605 return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
608 ///////////////////////////////////////////////////////////////////
611 // METHOD NAME : RpmHeader::tag_enhances
612 // METHOD TYPE : CapabilitySet
616 CapabilitySet RpmHeader::tag_enhances( std::set<std::string> * freq_r ) const
618 #ifdef RPMTAG_OLDSUGGESTS
619 return PkgRelList_val( RPMTAG_ENHANCENAME, false, freq_r );
621 return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
625 ///////////////////////////////////////////////////////////////////
628 // METHOD NAME : RpmHeader::tag_suggests
629 // METHOD TYPE : CapabilitySet
633 CapabilitySet RpmHeader::tag_suggests( std::set<std::string> * freq_r ) const
635 #ifdef RPMTAG_OLDSUGGESTS
636 return PkgRelList_val( RPMTAG_SUGGESTNAME, false, freq_r );
638 return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r );
642 ///////////////////////////////////////////////////////////////////
645 // METHOD NAME : RpmHeader::tag_supplements
646 // METHOD TYPE : CapabilitySet
650 CapabilitySet RpmHeader::tag_supplements( std::set<std::string> * freq_r ) const
652 #ifdef RPMTAG_OLDSUGGESTS
653 return PkgRelList_val( RPMTAG_SUPPLEMENTNAME, false, freq_r );
655 return CapabilitySet();
659 ///////////////////////////////////////////////////////////////////
662 // METHOD NAME : RpmHeader::tag_recommends
663 // METHOD TYPE : CapabilitySet
667 CapabilitySet RpmHeader::tag_recommends( std::set<std::string> * freq_r ) const
669 #ifdef RPMTAG_OLDSUGGESTS
670 return PkgRelList_val( RPMTAG_RECOMMENDNAME, false, freq_r );
672 return CapabilitySet();
676 ///////////////////////////////////////////////////////////////////
679 // METHOD NAME : RpmHeader::tag_size
680 // METHOD TYPE : ByteCount
684 ByteCount RpmHeader::tag_size() const
686 return int_val( RPMTAG_SIZE );
689 ///////////////////////////////////////////////////////////////////
692 // METHOD NAME : RpmHeader::tag_archivesize
693 // METHOD TYPE : ByteCount
697 ByteCount RpmHeader::tag_archivesize() const
699 return int_val( RPMTAG_ARCHIVESIZE );
702 ///////////////////////////////////////////////////////////////////
705 // METHOD NAME : RpmHeader::tag_summary
706 // METHOD TYPE : std::string
710 std::string RpmHeader::tag_summary() const
712 return string_val( RPMTAG_SUMMARY );
715 ///////////////////////////////////////////////////////////////////
718 // METHOD NAME : RpmHeader::tag_description
719 // METHOD TYPE : std::string
723 std::string RpmHeader::tag_description() const
725 return string_val( RPMTAG_DESCRIPTION );
728 ///////////////////////////////////////////////////////////////////
731 // METHOD NAME : RpmHeader::tag_group
732 // METHOD TYPE : std::string
736 std::string RpmHeader::tag_group() const
738 return string_val( RPMTAG_GROUP );
741 ///////////////////////////////////////////////////////////////////
744 // METHOD NAME : RpmHeader::tag_vendor
745 // METHOD TYPE : std::string
749 std::string RpmHeader::tag_vendor() const
751 return string_val( RPMTAG_VENDOR );
754 ///////////////////////////////////////////////////////////////////
757 // METHOD NAME : RpmHeader::tag_distribution
758 // METHOD TYPE : std::string
762 std::string RpmHeader::tag_distribution() const
764 return string_val( RPMTAG_DISTRIBUTION );
767 ///////////////////////////////////////////////////////////////////
770 // METHOD NAME : RpmHeader::tag_license
771 // METHOD TYPE : std::string
775 std::string RpmHeader::tag_license() const
777 return string_val( RPMTAG_LICENSE );
780 ///////////////////////////////////////////////////////////////////
783 // METHOD NAME : RpmHeader::tag_buildhost
784 // METHOD TYPE : std::string
788 std::string RpmHeader::tag_buildhost() const
790 return string_val( RPMTAG_BUILDHOST );
793 ///////////////////////////////////////////////////////////////////
796 // METHOD NAME : RpmHeader::tag_packager
797 // METHOD TYPE : std::string
801 std::string RpmHeader::tag_packager() const
803 return string_val( RPMTAG_PACKAGER );
806 ///////////////////////////////////////////////////////////////////
809 // METHOD NAME : RpmHeader::tag_url
810 // METHOD TYPE : std::string
814 std::string RpmHeader::tag_url() const
816 return string_val( RPMTAG_URL );
819 ///////////////////////////////////////////////////////////////////
822 // METHOD NAME : RpmHeader::tag_os
823 // METHOD TYPE : std::string
827 std::string RpmHeader::tag_os() const
829 return string_val( RPMTAG_OS );
833 std::string RpmHeader::tag_prein() const
834 { return string_val( RPMTAG_PREIN ); }
836 std::string RpmHeader::tag_preinprog() const
837 { return string_val( RPMTAG_PREINPROG ); }
839 std::string RpmHeader::tag_postin() const
840 { return string_val( RPMTAG_POSTIN ); }
842 std::string RpmHeader::tag_postinprog() const
843 { return string_val( RPMTAG_POSTINPROG ); }
845 std::string RpmHeader::tag_preun() const
846 { return string_val( RPMTAG_PREUN ); }
848 std::string RpmHeader::tag_preunprog() const
849 { return string_val( RPMTAG_PREUNPROG ); }
851 std::string RpmHeader::tag_postun() const
852 { return string_val( RPMTAG_POSTUN ); }
854 std::string RpmHeader::tag_postunprog() const
855 { return string_val( RPMTAG_POSTUNPROG ); }
857 std::string RpmHeader::tag_pretrans() const
858 { return string_val( RPMTAG_PRETRANS ); }
860 std::string RpmHeader::tag_pretransprog() const
861 { return string_val( RPMTAG_PRETRANSPROG ); }
863 std::string RpmHeader::tag_posttrans() const
864 { return string_val( RPMTAG_POSTTRANS ); }
866 std::string RpmHeader::tag_posttransprog() const
867 { return string_val( RPMTAG_POSTTRANSPROG ); }
869 ///////////////////////////////////////////////////////////////////
872 // METHOD NAME : RpmHeader::tag_sourcerpm
873 // METHOD TYPE : std::string
877 std::string RpmHeader::tag_sourcerpm() const
879 return string_val( RPMTAG_SOURCERPM );
882 ///////////////////////////////////////////////////////////////////
885 // METHOD NAME : RpmHeader::tag_filenames
886 // METHOD TYPE : std::list<std::string>
890 std::list<std::string> RpmHeader::tag_filenames() const
892 std::list<std::string> ret;
894 stringList basenames;
895 if ( string_list( RPMTAG_BASENAMES, basenames ) )
898 string_list( RPMTAG_DIRNAMES, dirnames );
900 int_list( RPMTAG_DIRINDEXES, dirindexes );
901 for ( unsigned i = 0; i < basenames.size(); ++ i )
903 ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
910 ///////////////////////////////////////////////////////////////////
913 // METHOD NAME : RpmHeader::tag_fileinfos
914 // METHOD TYPE : std::list<FileInfo>
918 std::list<FileInfo> RpmHeader::tag_fileinfos() const
920 std::list<FileInfo> ret;
922 stringList basenames;
923 if ( string_list( RPMTAG_BASENAMES, basenames ) )
926 string_list( RPMTAG_DIRNAMES, dirnames );
928 int_list( RPMTAG_DIRINDEXES, dirindexes );
930 int_list( RPMTAG_FILESIZES, filesizes );
932 string_list( RPMTAG_FILEMD5S, md5sums );
933 stringList usernames;
934 string_list( RPMTAG_FILEUSERNAME, usernames );
935 stringList groupnames;
936 string_list( RPMTAG_FILEGROUPNAME, groupnames );
938 int_list( RPMTAG_FILEUIDS, uids );
940 int_list( RPMTAG_FILEGIDS, gids );
942 int_list( RPMTAG_FILEMODES, filemodes );
944 int_list( RPMTAG_FILEMTIMES, filemtimes );
946 int_list( RPMTAG_FILEFLAGS, fileflags );
947 stringList filelinks;
948 string_list( RPMTAG_FILELINKTOS, filelinks );
950 for ( unsigned i = 0; i < basenames.size(); ++ i )
955 uid = unameToUid( usernames[i].c_str(), &uid );
965 gid = gnameToGid( groupnames[i].c_str(), &gid );
973 dirnames[dirindexes[i]] + basenames[i],
978 mode_t(filemodes[i]),
980 bool(fileflags[i] & RPMFILE_GHOST),
984 ret.push_back( info );
991 ///////////////////////////////////////////////////////////////////
994 // METHOD NAME : RpmHeader::tag_changelog
995 // METHOD TYPE : Changelog
999 Changelog RpmHeader::tag_changelog() const
1004 if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
1007 string_list( RPMTAG_CHANGELOGNAME, names );
1009 string_list( RPMTAG_CHANGELOGTEXT, texts );
1010 for ( unsigned i = 0; i < times.size(); ++ i )
1012 ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
1020 } // namespace target