1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/rpm/RpmHeader.cc
13 #ifndef _RPM_4_4_COMPAT
15 inline uid_t getUidS(const char * uname) { uid_t tmp; return ::unameToUid( uname, &tmp ); }
16 inline gid_t getGidS(const char * gname) { gid_t tmp; return ::gnameToGid( gname, &tmp ); }
18 #include <rpm/rpmbuild.h>
26 #include "zypp/base/Easy.h"
27 #include "zypp/base/Logger.h"
28 #include "zypp/base/Exception.h"
30 #include "zypp/target/rpm/RpmHeader.h"
31 #include "zypp/Package.h"
32 #include "zypp/PathInfo.h"
43 ///////////////////////////////////////////////////////////////////
45 ///////////////////////////////////////////////////////////////////
48 // METHOD NAME : RpmHeader::RpmHeader
49 // METHOD TYPE : Constructor
53 RpmHeader::RpmHeader( Header h_r )
57 ///////////////////////////////////////////////////////////////////
60 // METHOD NAME : RpmHeader::RpmHeader
61 // METHOD TYPE : Constructor
63 RpmHeader::RpmHeader( BinHeader::Ptr & rhs )
67 ///////////////////////////////////////////////////////////////////
70 // METHOD NAME : RpmHeader::~RpmHeader
71 // METHOD TYPE : Destructor
75 RpmHeader::~RpmHeader()
78 ///////////////////////////////////////////////////////////////////
81 // METHOD NAME : RpmHeader::readPackage
82 // METHOD TYPE : constRpmHeaderPtr
84 RpmHeader::constPtr RpmHeader::readPackage( const Pathname & path_r,
85 VERIFICATION verification_r )
87 PathInfo file( path_r );
88 if ( ! file.isFile() )
90 ERR << "Not a file: " << file << endl;
94 FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" );
95 if ( fd == 0 || ::Ferror(fd) )
97 ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl;
100 return (RpmHeader*)0;
103 rpmts ts = ::rpmtsCreate();
104 unsigned vsflag = RPMVSF_DEFAULT;
105 if ( verification_r & NODIGEST )
106 vsflag |= _RPMVSF_NODIGESTS;
107 if ( verification_r & NOSIGNATURE )
108 vsflag |= _RPMVSF_NOSIGNATURES;
109 ::rpmtsSetVSFlags( ts, rpmVSFlags(vsflag) );
112 int res = ::rpmReadPackageFile( ts, fd, path_r.asString().c_str(), &nh );
114 ts = ::rpmtsFree(ts);
120 WAR << "Error reading header from " << path_r << " error(" << res << ")" << endl;
121 return (RpmHeader*)0;
124 RpmHeader::constPtr h( new RpmHeader( nh ) );
125 headerFree( nh ); // clear the reference set in ReadPackageFile
127 MIL << h << " from " << path_r << endl;
131 ///////////////////////////////////////////////////////////////////
134 // METHOD NAME : RpmHeader::dumpOn
135 // METHOD TYPE : std::ostream &
139 std::ostream & RpmHeader::dumpOn( std::ostream & str ) const
141 return BinHeader::dumpOn( str ) << '{' << tag_name() << "-"
142 << (tag_epoch()==0?"":(tag_epoch()+":"))
144 << (tag_release().empty()?"":(std::string("-")+tag_release()))
145 << ( isSrc() ? ".src}" : "}");
149 ///////////////////////////////////////////////////////////////////
152 // METHOD NAME : RpmHeader::isSrc
153 // METHOD TYPE : bool
155 bool RpmHeader::isSrc() const
157 return has_tag( RPMTAG_SOURCEPACKAGE );
160 ///////////////////////////////////////////////////////////////////
163 // METHOD NAME : RpmHeader::tag_name
164 // METHOD TYPE : std::string
168 std::string RpmHeader::tag_name() const
170 return string_val( RPMTAG_NAME );
173 ///////////////////////////////////////////////////////////////////
176 // METHOD NAME : RpmHeader::tag_epoch
177 // METHOD TYPE : Edition::epoch_t
181 Edition::epoch_t RpmHeader::tag_epoch() const
183 return int_val ( RPMTAG_EPOCH );
186 ///////////////////////////////////////////////////////////////////
189 // METHOD NAME : RpmHeader::tag_version
190 // METHOD TYPE : std::string
194 std::string RpmHeader::tag_version() const
196 return string_val ( RPMTAG_VERSION );
199 ///////////////////////////////////////////////////////////////////
202 // METHOD NAME : RpmHeader::tag_release
203 // METHOD TYPE : std::string
207 std::string RpmHeader::tag_release() const
209 return string_val( RPMTAG_RELEASE );
212 ///////////////////////////////////////////////////////////////////
215 // METHOD NAME : RpmHeader::tag_edition
216 // METHOD TYPE : Edition
220 Edition RpmHeader::tag_edition () const
222 return Edition( tag_version(), tag_release(), tag_epoch() );
225 ///////////////////////////////////////////////////////////////////
228 // METHOD NAME : RpmHeader::tag_arch
229 // METHOD TYPE : Arch
233 Arch RpmHeader::tag_arch() const
235 return Arch( string_val( RPMTAG_ARCH ) );
238 ///////////////////////////////////////////////////////////////////
241 // METHOD NAME : RpmHeader::tag_installtime
242 // METHOD TYPE : Date
246 Date RpmHeader::tag_installtime() const
248 return int_val( RPMTAG_INSTALLTIME );
251 ///////////////////////////////////////////////////////////////////
254 // METHOD NAME : RpmHeader::tag_buildtime
255 // METHOD TYPE : Date
259 Date RpmHeader::tag_buildtime() const
261 return int_val( RPMTAG_BUILDTIME );
263 #warning CHECK IF FILE REQUIRES HANDLING IS OBSOLETE
264 ///////////////////////////////////////////////////////////////////
267 // METHOD NAME : RpmHeader::PkgRelList_val
268 // METHOD TYPE : CapabilitySet
272 CapabilitySet RpmHeader::PkgRelList_val( tag tag_r, bool pre, std::set<std::string> * freq_r ) const
276 rpmTag kindFlags = rpmTag(0);
277 rpmTag kindVersion = rpmTag(0);
281 case RPMTAG_REQUIRENAME:
282 kindFlags = RPMTAG_REQUIREFLAGS;
283 kindVersion = RPMTAG_REQUIREVERSION;
285 case RPMTAG_PROVIDENAME:
286 kindFlags = RPMTAG_PROVIDEFLAGS;
287 kindVersion = RPMTAG_PROVIDEVERSION;
289 case RPMTAG_OBSOLETENAME:
290 kindFlags = RPMTAG_OBSOLETEFLAGS;
291 kindVersion = RPMTAG_OBSOLETEVERSION;
293 case RPMTAG_CONFLICTNAME:
294 kindFlags = RPMTAG_CONFLICTFLAGS;
295 kindVersion = RPMTAG_CONFLICTVERSION;
297 case RPMTAG_ENHANCESNAME:
298 kindFlags = RPMTAG_ENHANCESFLAGS;
299 kindVersion = RPMTAG_ENHANCESVERSION;
301 case RPMTAG_SUGGESTSNAME:
302 kindFlags = RPMTAG_SUGGESTSFLAGS;
303 kindVersion = RPMTAG_SUGGESTSVERSION;
306 INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
312 unsigned count = string_list( tag_r, names );
317 int_list( kindFlags, flags );
320 string_list( kindVersion, versions );
322 for ( unsigned i = 0; i < count; ++i )
325 std::string n( names[i] );
328 int32_t f = flags[i];
329 std::string v = versions[i];
342 switch ( f & RPMSENSE_SENSEMASK )
347 case RPMSENSE_LESS|RPMSENSE_EQUAL:
350 case RPMSENSE_GREATER:
353 case RPMSENSE_GREATER|RPMSENSE_EQUAL:
362 if ((pre && (f & RPMSENSE_PREREQ))
363 || ((! pre) && !(f & RPMSENSE_PREREQ)))
367 ret.insert( Capability( n, op, Edition(v) ) );
369 catch (Exception & excpt_r)
371 ZYPP_CAUGHT(excpt_r);
372 WAR << "Invalid capability: " << n << " " << op << " "
381 ///////////////////////////////////////////////////////////////////
384 // METHOD NAME : RpmHeader::tag_provides
385 // METHOD TYPE : CapabilitySet
389 CapabilitySet RpmHeader::tag_provides( std::set<std::string> * freq_r ) const
391 return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
394 ///////////////////////////////////////////////////////////////////
397 // METHOD NAME : RpmHeader::tag_requires
398 // METHOD TYPE : CapabilitySet
402 CapabilitySet RpmHeader::tag_requires( std::set<std::string> * freq_r ) const
404 return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
407 ///////////////////////////////////////////////////////////////////
410 // METHOD NAME : RpmHeader::tag_requires
411 // METHOD TYPE : CapabilitySet
415 CapabilitySet RpmHeader::tag_prerequires( std::set<std::string> * freq_r ) const
417 return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
420 ///////////////////////////////////////////////////////////////////
423 // METHOD NAME : RpmHeader::tag_conflicts
424 // METHOD TYPE : CapabilitySet
428 CapabilitySet RpmHeader::tag_conflicts( std::set<std::string> * freq_r ) const
430 return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
433 ///////////////////////////////////////////////////////////////////
436 // METHOD NAME : RpmHeader::tag_obsoletes
437 // METHOD TYPE : CapabilitySet
441 CapabilitySet RpmHeader::tag_obsoletes( std::set<std::string> * freq_r ) const
443 return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
446 ///////////////////////////////////////////////////////////////////
449 // METHOD NAME : RpmHeader::tag_enhances
450 // METHOD TYPE : CapabilitySet
454 CapabilitySet RpmHeader::tag_enhances( std::set<std::string> * freq_r ) const
456 return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
459 ///////////////////////////////////////////////////////////////////
462 // METHOD NAME : RpmHeader::tag_suggests
463 // METHOD TYPE : CapabilitySet
467 CapabilitySet RpmHeader::tag_suggests( std::set<std::string> * freq_r ) const
469 return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r );
472 ///////////////////////////////////////////////////////////////////
475 // METHOD NAME : RpmHeader::tag_size
476 // METHOD TYPE : ByteCount
480 ByteCount RpmHeader::tag_size() const
482 return int_val( RPMTAG_SIZE );
485 ///////////////////////////////////////////////////////////////////
488 // METHOD NAME : RpmHeader::tag_archivesize
489 // METHOD TYPE : ByteCount
493 ByteCount RpmHeader::tag_archivesize() const
495 return int_val( RPMTAG_ARCHIVESIZE );
498 ///////////////////////////////////////////////////////////////////
501 // METHOD NAME : RpmHeader::tag_summary
502 // METHOD TYPE : std::string
506 std::string RpmHeader::tag_summary() const
508 return string_val( RPMTAG_SUMMARY );
511 ///////////////////////////////////////////////////////////////////
514 // METHOD NAME : RpmHeader::tag_description
515 // METHOD TYPE : std::string
519 std::string RpmHeader::tag_description() const
521 return string_val( RPMTAG_DESCRIPTION );
524 ///////////////////////////////////////////////////////////////////
527 // METHOD NAME : RpmHeader::tag_group
528 // METHOD TYPE : std::string
532 std::string RpmHeader::tag_group() const
534 return string_val( RPMTAG_GROUP );
537 ///////////////////////////////////////////////////////////////////
540 // METHOD NAME : RpmHeader::tag_vendor
541 // METHOD TYPE : std::string
545 std::string RpmHeader::tag_vendor() const
547 return string_val( RPMTAG_VENDOR );
550 ///////////////////////////////////////////////////////////////////
553 // METHOD NAME : RpmHeader::tag_distribution
554 // METHOD TYPE : std::string
558 std::string RpmHeader::tag_distribution() const
560 return string_val( RPMTAG_DISTRIBUTION );
563 ///////////////////////////////////////////////////////////////////
566 // METHOD NAME : RpmHeader::tag_license
567 // METHOD TYPE : std::string
571 std::string RpmHeader::tag_license() const
573 return string_val( RPMTAG_LICENSE );
576 ///////////////////////////////////////////////////////////////////
579 // METHOD NAME : RpmHeader::tag_buildhost
580 // METHOD TYPE : std::string
584 std::string RpmHeader::tag_buildhost() const
586 return string_val( RPMTAG_BUILDHOST );
589 ///////////////////////////////////////////////////////////////////
592 // METHOD NAME : RpmHeader::tag_packager
593 // METHOD TYPE : std::string
597 std::string RpmHeader::tag_packager() const
599 return string_val( RPMTAG_PACKAGER );
602 ///////////////////////////////////////////////////////////////////
605 // METHOD NAME : RpmHeader::tag_url
606 // METHOD TYPE : std::string
610 std::string RpmHeader::tag_url() const
612 return string_val( RPMTAG_URL );
615 ///////////////////////////////////////////////////////////////////
618 // METHOD NAME : RpmHeader::tag_os
619 // METHOD TYPE : std::string
623 std::string RpmHeader::tag_os() const
625 return string_val( RPMTAG_OS );
628 ///////////////////////////////////////////////////////////////////
631 // METHOD NAME : RpmHeader::tag_prein
632 // METHOD TYPE : std::string
636 std::string RpmHeader::tag_prein() const
638 return string_val( RPMTAG_PREIN );
641 ///////////////////////////////////////////////////////////////////
644 // METHOD NAME : RpmHeader::tag_postin
645 // METHOD TYPE : std::string
649 std::string RpmHeader::tag_postin() const
651 return string_val( RPMTAG_POSTIN );
654 ///////////////////////////////////////////////////////////////////
657 // METHOD NAME : RpmHeader::tag_preun
658 // METHOD TYPE : std::string
662 std::string RpmHeader::tag_preun() const
664 return string_val( RPMTAG_PREUN );
667 ///////////////////////////////////////////////////////////////////
670 // METHOD NAME : RpmHeader::tag_postun
671 // METHOD TYPE : std::string
675 std::string RpmHeader::tag_postun() const
677 return string_val( RPMTAG_POSTUN );
680 ///////////////////////////////////////////////////////////////////
683 // METHOD NAME : RpmHeader::tag_sourcerpm
684 // METHOD TYPE : std::string
688 std::string RpmHeader::tag_sourcerpm() const
690 return string_val( RPMTAG_SOURCERPM );
693 ///////////////////////////////////////////////////////////////////
696 // METHOD NAME : RpmHeader::tag_filenames
697 // METHOD TYPE : std::list<std::string>
701 std::list<std::string> RpmHeader::tag_filenames() const
703 std::list<std::string> ret;
705 stringList basenames;
706 if ( string_list( RPMTAG_BASENAMES, basenames ) )
709 string_list( RPMTAG_DIRNAMES, dirnames );
711 int_list( RPMTAG_DIRINDEXES, dirindexes );
712 for ( unsigned i = 0; i < basenames.size(); ++ i )
714 ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
721 ///////////////////////////////////////////////////////////////////
724 // METHOD NAME : RpmHeader::tag_fileinfos
725 // METHOD TYPE : std::list<FileInfo>
729 std::list<FileInfo> RpmHeader::tag_fileinfos() const
731 std::list<FileInfo> ret;
733 stringList basenames;
734 if ( string_list( RPMTAG_BASENAMES, basenames ) )
737 string_list( RPMTAG_DIRNAMES, dirnames );
739 int_list( RPMTAG_DIRINDEXES, dirindexes );
741 int_list( RPMTAG_FILESIZES, filesizes );
743 string_list( RPMTAG_FILEMD5S, md5sums );
744 stringList usernames;
745 string_list( RPMTAG_FILEUSERNAME, usernames );
746 stringList groupnames;
747 string_list( RPMTAG_FILEGROUPNAME, groupnames );
749 int_list( RPMTAG_FILEUIDS, uids );
751 int_list( RPMTAG_FILEGIDS, gids );
753 int_list( RPMTAG_FILEMODES, filemodes );
755 int_list( RPMTAG_FILEMTIMES, filemtimes );
757 int_list( RPMTAG_FILEFLAGS, fileflags );
758 stringList filelinks;
759 string_list( RPMTAG_FILELINKTOS, filelinks );
761 for ( unsigned i = 0; i < basenames.size(); ++ i )
766 uid = getUidS( usernames[i].c_str() );
776 gid = getGidS( groupnames[i].c_str() );
784 dirnames[dirindexes[i]] + basenames[i],
791 fileflags[i] & RPMFILE_GHOST,
795 ret.push_back( info );
802 ///////////////////////////////////////////////////////////////////
805 // METHOD NAME : RpmHeader::tag_changelog
806 // METHOD TYPE : Changelog
810 Changelog RpmHeader::tag_changelog() const
815 if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
818 string_list( RPMTAG_CHANGELOGNAME, names );
820 string_list( RPMTAG_CHANGELOGTEXT, texts );
821 for ( unsigned i = 0; i < times.size(); ++ i )
823 ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
830 ///////////////////////////////////////////////////////////////////
833 // METHOD NAME : RpmHeader::tag_du
834 // METHOD TYPE : PkgDu &
838 DiskUsage & RpmHeader::tag_du( DiskUsage & dudata_r ) const
841 stringList basenames;
842 if ( string_list( RPMTAG_BASENAMES, basenames ) )
845 string_list( RPMTAG_DIRNAMES, dirnames );
847 int_list( RPMTAG_DIRINDEXES, dirindexes );
850 int_list( RPMTAG_FILEDEVICES, filedevices );
852 int_list( RPMTAG_FILEINODES, fileinodes );
854 int_list( RPMTAG_FILESIZES, filesizes );
856 int_list( RPMTAG_FILEMODES, filemodes );
858 ///////////////////////////////////////////////////////////////////
859 // Create and collect Entries by index. devino_cache is used to
860 // filter out hardliks ( different name but same device and inode ).
861 ///////////////////////////////////////////////////////////////////
862 filesystem::DevInoCache trace;
863 std::vector<DiskUsage::Entry> entries;
864 entries.resize( dirnames.size() );
865 for ( unsigned i = 0; i < dirnames.size(); ++i )
867 entries[i] = DiskUsage::Entry( dirnames[i] );
869 // cut off deeper directory levels in DiskUsage::Entry
870 unsigned level = 3; // number of '/' incl. a trailing one
871 std::string::size_type pos = 0; // we know rpm stores absolute pathnames
872 while ( --level && pos != std::string::npos )
874 pos = entries[i].path.find( "/", pos+1 );
876 if ( pos != std::string::npos )
878 entries[i].path.erase( pos+1 );
882 for ( unsigned i = 0; i < basenames.size(); ++ i )
884 filesystem::StatMode mode( filemodes[i] );
887 if ( trace.insert( filedevices[i], fileinodes[i] ) )
889 // Count full 1K blocks
890 entries[dirindexes[i]]._size += ByteCount( filesizes[i] ).blocks( ByteCount::K );
891 ++(entries[dirindexes[i]]._files);
893 // else: hardlink; already counted this device/inode
897 ///////////////////////////////////////////////////////////////////
898 // Collect all enties. We first unify the duplicate entries that
899 // were created by cutting off deeper levels. Then the size of each
900 // directory must also be added to each of it's parent directories.
901 ///////////////////////////////////////////////////////////////////
903 for ( unsigned i = 0; i < entries.size(); ++i )
905 if ( entries[i]._size )
906 tmpdata.add( entries[i] );
909 for_( it, tmpdata.begin(), tmpdata.end() )
911 DiskUsage::Entry ent( *it );
915 if ( ent.path.size() <= 1 ) // "" or "/"
918 // set path to parent dir. Note that DiskUsage::Entry
919 // has leading and trailing '/' on pathnmes.
920 std::string::size_type rstart = ent.path.size() - 2; // trailing '/' !
921 std::string::size_type lpos = ent.path.rfind( '/', rstart ); // one but last '/'
922 if ( lpos == std::string::npos )
925 ent.path.erase( lpos + 1 );
933 } // namespace target