added disk usage data to PackageImplIf interface, provide this info from
[platform/upstream/libzypp.git] / zypp / target / rpm / RpmHeader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/rpm/RpmHeader.cc
10  *
11 */
12 #include "librpm.h"
13
14 #include <iostream>
15 #include <map>
16 #include <set>
17 #include <vector>
18
19 #include "zypp/base/Logger.h"
20 #include "zypp/PathInfo.h"
21
22 #include "zypp/target/rpm/RpmHeader.h"
23 #include "zypp/CapFactory.h"
24 #include "zypp/Rel.h"
25 #include "zypp/Package.h"
26
27 using namespace std;
28
29 namespace zypp {
30   namespace target {
31     namespace rpm {
32
33       ///////////////////////////////////////////////////////////////////
34       
35       ///////////////////////////////////////////////////////////////////
36       //
37       //
38       //        METHOD NAME : RpmHeader::RpmHeader
39       //        METHOD TYPE : Constructor
40       //
41       //        DESCRIPTION :
42       //
43       RpmHeader::RpmHeader( Header h_r )
44           : BinHeader( h_r )
45       {
46       }
47       
48       ///////////////////////////////////////////////////////////////////
49       //
50       //
51       //        METHOD NAME : RpmHeader::RpmHeader
52       //        METHOD TYPE : Constructor
53       //
54       RpmHeader::RpmHeader( BinHeader::Ptr & rhs )
55           : BinHeader( rhs )
56       {
57       }
58       
59       ///////////////////////////////////////////////////////////////////
60       //
61       //
62       //        METHOD NAME : RpmHeader::~RpmHeader
63       //        METHOD TYPE : Destructor
64       //
65       //        DESCRIPTION :
66       //
67       RpmHeader::~RpmHeader()
68       {
69       }
70       
71       ///////////////////////////////////////////////////////////////////
72       //
73       //
74       //        METHOD NAME : RpmHeader::readPackage
75       //        METHOD TYPE : constRpmHeaderPtr
76       //
77       RpmHeader::constPtr RpmHeader::readPackage( const Pathname & path_r,
78                                           VERIFICATION verification_r )
79       {
80         PathInfo file( path_r );
81         if ( ! file.isFile() ) {
82           ERR << "Not a file: " << file << endl;
83           return (RpmHeader*)0;
84         }
85       
86         FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" );
87         if ( fd == 0 || ::Ferror(fd) ) {
88           ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl;
89           if ( fd )
90             ::Fclose( fd );
91           return (RpmHeader*)0;
92         }
93       
94         rpmts ts = ::rpmtsCreate();
95         unsigned vsflag = RPMVSF_DEFAULT;
96         if ( verification_r & NODIGEST )
97           vsflag |= _RPMVSF_NODIGESTS;
98         if ( verification_r & NOSIGNATURE )
99           vsflag |= _RPMVSF_NOSIGNATURES;
100         ::rpmtsSetVSFlags( ts, rpmVSFlags(vsflag) );
101       
102         Header nh = 0;
103         int res = ::rpmReadPackageFile( ts, fd, path_r.asString().c_str(), &nh );
104       
105         ts = ::rpmtsFree(ts);
106       
107         ::Fclose( fd );
108       
109         if ( ! nh ) {
110           WAR << "Error reading header from " << path_r << " error(" << res << ")" << endl;
111           return (RpmHeader*)0;
112         }
113       
114         RpmHeader::constPtr h( new RpmHeader( nh ) );
115         headerFree( nh ); // clear the reference set in ReadPackageFile
116       
117         MIL << h << " from " << path_r << endl;
118         return h;
119       }
120       
121       ///////////////////////////////////////////////////////////////////
122       //
123       //
124       //        METHOD NAME : RpmHeader::dumpOn
125       //        METHOD TYPE : ostream &
126       //
127       //        DESCRIPTION :
128       //
129       ostream & RpmHeader::dumpOn( ostream & str ) const
130       {
131         return BinHeader::dumpOn( str ) << '{' << tag_name() << "-" << tag_edition() << ( isSrc() ? ".src}" : "}");
132       }
133       
134       
135       ///////////////////////////////////////////////////////////////////
136       //
137       //
138       //        METHOD NAME : RpmHeader::isSrc
139       //        METHOD TYPE : bool
140       //
141       bool RpmHeader::isSrc() const
142       {
143         return has_tag( RPMTAG_SOURCEPACKAGE );
144       }
145       
146       ///////////////////////////////////////////////////////////////////
147       //
148       //
149       //        METHOD NAME : RpmHeader::tag_name
150       //        METHOD TYPE : string
151       //
152       //        DESCRIPTION :
153       //
154       string RpmHeader::tag_name() const
155       {
156         return string( string_val( RPMTAG_NAME ) );
157       }
158       
159       ///////////////////////////////////////////////////////////////////
160       //
161       //
162       //        METHOD NAME : RpmHeader::tag_edition
163       //        METHOD TYPE : Edition
164       //
165       //        DESCRIPTION :
166       //
167       Edition RpmHeader::tag_edition() const
168       {
169         return Edition( string_val( RPMTAG_VERSION ),
170                      string_val( RPMTAG_RELEASE ),
171                      string_val   ( RPMTAG_EPOCH ));
172       }
173       
174       ///////////////////////////////////////////////////////////////////
175       //
176       //
177       //        METHOD NAME : RpmHeader::tag_arch
178       //        METHOD TYPE : Arch
179       //
180       //        DESCRIPTION :
181       //
182       Arch RpmHeader::tag_arch() const
183       {
184         return Arch( string_val( RPMTAG_ARCH ) );
185       }
186       
187       ///////////////////////////////////////////////////////////////////
188       //
189       //
190       //        METHOD NAME : RpmHeader::tag_installtime
191       //        METHOD TYPE : Date
192       //
193       //        DESCRIPTION :
194       //
195       Date RpmHeader::tag_installtime() const
196       {
197         return int_val( RPMTAG_INSTALLTIME );
198       }
199       
200       ///////////////////////////////////////////////////////////////////
201       //
202       //
203       //        METHOD NAME : RpmHeader::tag_buildtime
204       //        METHOD TYPE : Date
205       //
206       //        DESCRIPTION :
207       //
208       Date RpmHeader::tag_buildtime() const
209       {
210         return int_val( RPMTAG_BUILDTIME );
211       }
212       
213       ///////////////////////////////////////////////////////////////////
214       //
215       //
216       //        METHOD NAME : RpmHeader::PkgRelList_val
217       //        METHOD TYPE : unsigned
218       //
219       //        DESCRIPTION :
220       //
221       CapSet RpmHeader::PkgRelList_val( tag tag_r, bool pre, set<string> * freq_r ) const
222       {
223         CapSet ret;
224       
225         int_32  kindFlags   = 0;
226         int_32  kindVersion = 0;
227       
228         switch ( tag_r ) {
229         case RPMTAG_REQUIRENAME:
230           kindFlags   = RPMTAG_REQUIREFLAGS;
231           kindVersion = RPMTAG_REQUIREVERSION;
232           break;
233         case RPMTAG_PROVIDENAME:
234           kindFlags   = RPMTAG_PROVIDEFLAGS;
235           kindVersion = RPMTAG_PROVIDEVERSION;
236           break;
237         case RPMTAG_OBSOLETENAME:
238           kindFlags   = RPMTAG_OBSOLETEFLAGS;
239           kindVersion = RPMTAG_OBSOLETEVERSION;
240           break;
241         case RPMTAG_CONFLICTNAME:
242           kindFlags   = RPMTAG_CONFLICTFLAGS;
243           kindVersion = RPMTAG_CONFLICTVERSION;
244           break;
245         default:
246           INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
247           return ret;
248           break;
249         }
250       
251         stringList names;
252         unsigned count = string_list( tag_r, names );
253         if ( !count )
254           return ret;
255       
256         intList  flags;
257         int_list( kindFlags, flags );
258       
259         stringList versions;
260         string_list( kindVersion, versions );
261       
262         for ( unsigned i = 0; i < count; ++i ) {
263       
264           string n( names[i] );
265       
266           Rel op = Rel::ANY;
267           int_32 f  = flags[i];
268           string v  = versions[i];
269       
270           if ( n[0] == '/' ) {
271             if ( freq_r ) {
272               freq_r->insert( n );
273             }
274           } else {
275             if ( v.size() ) {
276               switch ( f & RPMSENSE_SENSEMASK ) {
277               case RPMSENSE_LESS:
278                 op = Rel::LT;
279                 break;
280               case RPMSENSE_LESS|RPMSENSE_EQUAL:
281                 op = Rel::LE;
282                 break;
283               case RPMSENSE_GREATER:
284                 op = Rel::GT;
285                 break;
286               case RPMSENSE_GREATER|RPMSENSE_EQUAL:
287                 op = Rel::GE;
288                 break;
289               case RPMSENSE_EQUAL:
290                 op = Rel::EQ;
291                 break;
292               }
293             }
294           }
295           if ((pre && (f & RPMSENSE_PREREQ))
296             || ((! pre) && !(f & RPMSENSE_PREREQ)))
297           {
298             CapFactory _f;
299             Capability cap = _f.parse(
300               ResTraits<Package>::kind,
301               n,
302               op,
303               Edition(v)
304             );
305             ret.insert(cap);
306           }
307         }
308       
309         return ret;
310       }
311       
312       ///////////////////////////////////////////////////////////////////
313       //
314       //
315       //        METHOD NAME : RpmHeader::tag_provides
316       //        METHOD TYPE : CapSet
317       //
318       //        DESCRIPTION :
319       //
320       CapSet RpmHeader::tag_provides( set<string> * freq_r ) const
321       {
322         return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
323       }
324       
325       ///////////////////////////////////////////////////////////////////
326       //
327       //
328       //        METHOD NAME : RpmHeader::tag_requires
329       //        METHOD TYPE : CapSet
330       //
331       //        DESCRIPTION :
332       //
333       CapSet RpmHeader::tag_requires( set<string> * freq_r ) const
334       {
335         return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
336       }
337       
338       ///////////////////////////////////////////////////////////////////
339       //
340       //
341       //        METHOD NAME : RpmHeader::tag_requires
342       //        METHOD TYPE : CapSet
343       //
344       //        DESCRIPTION :
345       //
346       CapSet RpmHeader::tag_prerequires( set<string> * freq_r ) const
347       {
348         return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
349       }
350       
351       ///////////////////////////////////////////////////////////////////
352       //
353       //
354       //        METHOD NAME : RpmHeader::tag_conflicts
355       //        METHOD TYPE : CapSet
356       //
357       //        DESCRIPTION :
358       //
359       CapSet RpmHeader::tag_conflicts( set<string> * freq_r ) const
360       {
361         return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
362       }
363       
364       ///////////////////////////////////////////////////////////////////
365       //
366       //
367       //        METHOD NAME : RpmHeader::tag_obsoletes
368       //        METHOD TYPE : CapSet
369       //
370       //        DESCRIPTION :
371       //
372       CapSet RpmHeader::tag_obsoletes( set<string> * freq_r ) const
373       {
374         return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
375       }
376       
377       ///////////////////////////////////////////////////////////////////
378       //
379       //
380       //        METHOD NAME : RpmHeader::tag_size
381       //        METHOD TYPE : ByteCount
382       //
383       //        DESCRIPTION :
384       //
385       ByteCount RpmHeader::tag_size() const
386       {
387         return int_val( RPMTAG_SIZE );
388       }
389       
390       ///////////////////////////////////////////////////////////////////
391       //
392       //
393       //        METHOD NAME : RpmHeader::tag_archivesize
394       //        METHOD TYPE : ByteCount
395       //
396       //        DESCRIPTION :
397       //
398       ByteCount RpmHeader::tag_archivesize() const
399       {
400         return int_val( RPMTAG_ARCHIVESIZE );
401       }
402       
403       ///////////////////////////////////////////////////////////////////
404       //
405       //
406       //        METHOD NAME : RpmHeader::tag_summary
407       //        METHOD TYPE : std::string
408       //
409       //        DESCRIPTION :
410       //
411       std::string RpmHeader::tag_summary() const
412       {
413         return string_val( RPMTAG_SUMMARY );
414       }
415       
416       ///////////////////////////////////////////////////////////////////
417       //
418       //
419       //        METHOD NAME : RpmHeader::tag_description
420       //        METHOD TYPE : std::string
421       //
422       //        DESCRIPTION :
423       //
424       std::string RpmHeader::tag_description() const
425       {
426         return string_val( RPMTAG_DESCRIPTION );
427       }
428       
429       ///////////////////////////////////////////////////////////////////
430       //
431       //
432       //        METHOD NAME : RpmHeader::tag_group
433       //        METHOD TYPE : std::string
434       //
435       //        DESCRIPTION :
436       //
437       std::string RpmHeader::tag_group() const
438       {
439         return string_val( RPMTAG_GROUP );
440       }
441       
442       ///////////////////////////////////////////////////////////////////
443       //
444       //
445       //        METHOD NAME : RpmHeader::tag_vendor
446       //        METHOD TYPE : std::string
447       //
448       //        DESCRIPTION :
449       //
450       std::string RpmHeader::tag_vendor() const
451       {
452         return string_val( RPMTAG_VENDOR );
453       }
454       
455       ///////////////////////////////////////////////////////////////////
456       //
457       //
458       //        METHOD NAME : RpmHeader::tag_distribution
459       //        METHOD TYPE : std::string
460       //
461       //        DESCRIPTION :
462       //
463       std::string RpmHeader::tag_distribution() const
464       {
465         return string_val( RPMTAG_DISTRIBUTION );
466       }
467       
468       ///////////////////////////////////////////////////////////////////
469       //
470       //
471       //        METHOD NAME : RpmHeader::tag_license
472       //        METHOD TYPE : std::string
473       //
474       //        DESCRIPTION :
475       //
476       std::string RpmHeader::tag_license() const
477       {
478         return string_val( RPMTAG_LICENSE );
479       }
480       
481       ///////////////////////////////////////////////////////////////////
482       //
483       //
484       //        METHOD NAME : RpmHeader::tag_buildhost
485       //        METHOD TYPE : std::string
486       //
487       //        DESCRIPTION :
488       //
489       std::string RpmHeader::tag_buildhost() const
490       {
491         return string_val( RPMTAG_BUILDHOST );
492       }
493       
494       ///////////////////////////////////////////////////////////////////
495       //
496       //
497       //        METHOD NAME : RpmHeader::tag_packager
498       //        METHOD TYPE : std::string
499       //
500       //        DESCRIPTION :
501       //
502       std::string RpmHeader::tag_packager() const
503       {
504         return string_val( RPMTAG_PACKAGER );
505       }
506       
507       ///////////////////////////////////////////////////////////////////
508       //
509       //
510       //        METHOD NAME : RpmHeader::tag_url
511       //        METHOD TYPE : std::string
512       //
513       //        DESCRIPTION :
514       //
515       std::string RpmHeader::tag_url() const
516       {
517         return string_val( RPMTAG_URL );
518       }
519       
520       ///////////////////////////////////////////////////////////////////
521       //
522       //
523       //        METHOD NAME : RpmHeader::tag_os
524       //        METHOD TYPE : std::string
525       //
526       //        DESCRIPTION :
527       //
528       std::string RpmHeader::tag_os() const
529       {
530         return string_val( RPMTAG_OS );
531       }
532       
533       ///////////////////////////////////////////////////////////////////
534       //
535       //
536       //        METHOD NAME : RpmHeader::tag_prein
537       //        METHOD TYPE : std::string
538       //
539       //        DESCRIPTION :
540       //
541       std::string RpmHeader::tag_prein() const
542       {
543         return string_val( RPMTAG_PREIN );
544       }
545       
546       ///////////////////////////////////////////////////////////////////
547       //
548       //
549       //        METHOD NAME : RpmHeader::tag_postin
550       //        METHOD TYPE : std::string
551       //
552       //        DESCRIPTION :
553       //
554       std::string RpmHeader::tag_postin() const
555       {
556         return string_val( RPMTAG_POSTIN );
557       }
558       
559       ///////////////////////////////////////////////////////////////////
560       //
561       //
562       //        METHOD NAME : RpmHeader::tag_preun
563       //        METHOD TYPE : std::string
564       //
565       //        DESCRIPTION :
566       //
567       std::string RpmHeader::tag_preun() const
568       {
569         return string_val( RPMTAG_PREUN );
570       }
571       
572       ///////////////////////////////////////////////////////////////////
573       //
574       //
575       //        METHOD NAME : RpmHeader::tag_postun
576       //        METHOD TYPE : std::string
577       //
578       //        DESCRIPTION :
579       //
580       std::string RpmHeader::tag_postun() const
581       {
582         return string_val( RPMTAG_POSTUN );
583       }
584       
585       ///////////////////////////////////////////////////////////////////
586       //
587       //
588       //        METHOD NAME : RpmHeader::tag_sourcerpm
589       //        METHOD TYPE : std::string
590       //
591       //        DESCRIPTION :
592       //
593       std::string RpmHeader::tag_sourcerpm() const
594       {
595         return string_val( RPMTAG_SOURCERPM );
596       }
597       
598       ///////////////////////////////////////////////////////////////////
599       //
600       //
601       //        METHOD NAME : RpmHeader::tag_filenames
602       //        METHOD TYPE : std::list<std::string>
603       //
604       //        DESCRIPTION :
605       //
606       std::list<std::string> RpmHeader::tag_filenames() const
607       {
608         std::list<std::string> ret;
609       
610         stringList basenames;
611         if ( string_list( RPMTAG_BASENAMES, basenames ) ) {
612           stringList dirnames;
613           string_list( RPMTAG_DIRNAMES, dirnames );
614           intList  dirindexes;
615           int_list( RPMTAG_DIRINDEXES, dirindexes );
616           for ( unsigned i = 0; i < basenames.size(); ++ i ) {
617             ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
618           }
619         }
620       
621         return ret;
622       }
623       
624       ///////////////////////////////////////////////////////////////////
625       //
626       //
627       //        METHOD NAME : RpmHeader::tag_changelog
628       //        METHOD TYPE : Changelog
629       //
630       //        DESCRIPTION :
631       //
632       Changelog RpmHeader::tag_changelog() const
633       {
634         Changelog ret;
635       
636         intList times;
637         if ( int_list( RPMTAG_CHANGELOGTIME, times ) ) {
638           stringList names;
639           string_list( RPMTAG_CHANGELOGNAME, names );
640           stringList texts;
641           string_list( RPMTAG_CHANGELOGTEXT, texts );
642           for ( unsigned i = 0; i < times.size(); ++ i ) {
643             ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
644           }
645         }
646       
647         return ret;
648       }
649      
650       ///////////////////////////////////////////////////////////////////
651       //
652       //
653       //        METHOD NAME : RpmHeader::tag_du
654       //        METHOD TYPE : PkgDu &
655       //
656       //        DESCRIPTION :
657       //
658       Package::DiskUsage & RpmHeader::tag_du( Package::DiskUsage & dudata_r ) const
659       {
660         dudata_r.clear();
661         stringList basenames;
662         if ( string_list( RPMTAG_BASENAMES, basenames ) ) {
663           stringList dirnames;
664           string_list( RPMTAG_DIRNAMES, dirnames );
665           intList dirindexes;
666           int_list( RPMTAG_DIRINDEXES, dirindexes );
667       
668           intList filedevices;
669           int_list( RPMTAG_FILEDEVICES, filedevices );
670           intList fileinodes;
671           int_list( RPMTAG_FILEINODES, fileinodes );
672           intList filesizes;
673           int_list( RPMTAG_FILESIZES, filesizes );
674           intList filemodes;
675           int_list( RPMTAG_FILEMODES, filemodes );
676       
677           ///////////////////////////////////////////////////////////////////
678           // Create and collect Entries by index. devino_cache is used to
679           // filter out hardliks ( different name but same device and inode ).
680           ///////////////////////////////////////////////////////////////////
681           filesystem::DevInoCache trace;
682           vector<Package::DiskUsage::Entry> entries;
683           entries.resize( dirnames.size() );
684           for ( unsigned i = 0; i < dirnames.size(); ++i ) {
685             entries[i] = Package::DiskUsage::Entry(dirnames[i]);
686           }
687       
688           for ( unsigned i = 0; i < basenames.size(); ++ i ) {
689             filesystem::StatMode mode( filemodes[i] );
690             if ( mode.isFile() ) {
691               if ( trace.insert( filedevices[i], fileinodes[i] ) ) {
692                 // Count full 1K blocks
693                 entries[dirindexes[i]]._size += ByteCount( filesizes[i] ).fillBlock();
694                 ++(entries[dirindexes[i]]._files);
695               }
696               // else: hardlink; already counted this device/inode
697             }
698           }
699       
700           ///////////////////////////////////////////////////////////////////
701           // Crreate and collect by index Entries. DevInoTrace is used to
702           // filter out hardliks ( different name but same device and inode ).
703           ///////////////////////////////////////////////////////////////////
704           for ( unsigned i = 0; i < entries.size(); ++i ) {
705             if ( entries[i]._size ) {
706               dudata_r.add( entries[i] );
707             }
708           }
709         }
710         return dudata_r;
711       }
712
713     } // namespace rpm
714   } // namespace target
715 } // namespace zypp