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