Use gcc-c++ >= 4.5
[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 #ifdef _RPM_4_4
14 #include <rpm/ugid.h>
15 #else
16 ////////////////////////////////////////////////////////////////////
17 // unameToUid and gnameToGid are shamelessly stolen from rpm-4.4.
18 // (rpmio/ugid.c) Those functions were dropped in RPM_4_7
19 extern "C"
20 {
21 #include <pwd.h>
22 #include <grp.h>
23 }
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 :-( */
30
31 int unameToUid(const char * thisUname, uid_t * uid)
32 {
33 /*@only@*/ static char * lastUname = NULL;
34     static size_t lastUnameLen = 0;
35     static size_t lastUnameAlloced;
36     static uid_t lastUid;
37     struct passwd * pwent;
38     size_t thisUnameLen;
39
40     if (!thisUname) {
41         lastUnameLen = 0;
42         return -1;
43     } else if (strcmp(thisUname, "root") == 0) {
44 /*@-boundswrite@*/
45         *uid = 0;
46 /*@=boundswrite@*/
47         return 0;
48     }
49
50     thisUnameLen = strlen(thisUname);
51     if (lastUname == NULL || thisUnameLen != lastUnameLen ||
52         strcmp(thisUname, lastUname) != 0)
53     {
54         if (lastUnameAlloced < thisUnameLen + 1) {
55             lastUnameAlloced = thisUnameLen + 10;
56             lastUname = (char *)realloc(lastUname, lastUnameAlloced);   /* XXX memory leak */
57         }
58 /*@-boundswrite@*/
59         strcpy(lastUname, thisUname);
60 /*@=boundswrite@*/
61
62         pwent = getpwnam(thisUname);
63         if (pwent == NULL) {
64             /*@-internalglobs@*/ /* FIX: shrug */
65             endpwent();
66             /*@=internalglobs@*/
67             pwent = getpwnam(thisUname);
68             if (pwent == NULL) return -1;
69         }
70
71         lastUid = pwent->pw_uid;
72     }
73
74 /*@-boundswrite@*/
75     *uid = lastUid;
76 /*@=boundswrite@*/
77
78     return 0;
79 }
80
81 int gnameToGid(const char * thisGname, gid_t * gid)
82 {
83 /*@only@*/ static char * lastGname = NULL;
84     static size_t lastGnameLen = 0;
85     static size_t lastGnameAlloced;
86     static gid_t lastGid;
87     size_t thisGnameLen;
88     struct group * grent;
89
90     if (thisGname == NULL) {
91         lastGnameLen = 0;
92         return -1;
93     } else if (strcmp(thisGname, "root") == 0) {
94 /*@-boundswrite@*/
95         *gid = 0;
96 /*@=boundswrite@*/
97         return 0;
98     }
99
100     thisGnameLen = strlen(thisGname);
101     if (lastGname == NULL || thisGnameLen != lastGnameLen ||
102         strcmp(thisGname, lastGname) != 0)
103     {
104         if (lastGnameAlloced < thisGnameLen + 1) {
105             lastGnameAlloced = thisGnameLen + 10;
106             lastGname = (char *)realloc(lastGname, lastGnameAlloced);   /* XXX memory leak */
107         }
108 /*@-boundswrite@*/
109         strcpy(lastGname, thisGname);
110 /*@=boundswrite@*/
111
112         grent = getgrnam(thisGname);
113         if (grent == NULL) {
114             /*@-internalglobs@*/ /* FIX: shrug */
115             endgrent();
116             /*@=internalglobs@*/
117             grent = getgrnam(thisGname);
118             if (grent == NULL) {
119                 /* XXX The filesystem package needs group/lock w/o getgrnam. */
120                 if (strcmp(thisGname, "lock") == 0) {
121 /*@-boundswrite@*/
122                     *gid = lastGid = 54;
123 /*@=boundswrite@*/
124                     return 0;
125                 } else
126                 if (strcmp(thisGname, "mail") == 0) {
127 /*@-boundswrite@*/
128                     *gid = lastGid = 12;
129 /*@=boundswrite@*/
130                     return 0;
131                 } else
132                 return -1;
133             }
134         }
135         lastGid = grent->gr_gid;
136     }
137
138 /*@-boundswrite@*/
139     *gid = lastGid;
140 /*@=boundswrite@*/
141
142     return 0;
143 }
144 ////////////////////////////////////////////////////////////////////
145 #endif
146
147 #include <iostream>
148 #include <map>
149 #include <set>
150 #include <vector>
151
152 #include "zypp/base/Easy.h"
153 #include "zypp/base/Logger.h"
154 #include "zypp/base/Exception.h"
155
156 #include "zypp/target/rpm/librpmDb.h"
157 #include "zypp/target/rpm/RpmHeader.h"
158 #include "zypp/Package.h"
159 #include "zypp/PathInfo.h"
160
161 using std::endl;
162
163 namespace zypp
164 {
165 namespace target
166 {
167 namespace rpm
168 {
169
170 ///////////////////////////////////////////////////////////////////
171
172 ///////////////////////////////////////////////////////////////////
173 //
174 //
175 //        METHOD NAME : RpmHeader::RpmHeader
176 //        METHOD TYPE : Constructor
177 //
178 //        DESCRIPTION :
179 //
180 RpmHeader::RpmHeader( Header h_r )
181     : BinHeader( h_r )
182 {}
183
184 ///////////////////////////////////////////////////////////////////
185 //
186 //
187 //        METHOD NAME : RpmHeader::RpmHeader
188 //        METHOD TYPE : Constructor
189 //
190 RpmHeader::RpmHeader( BinHeader::Ptr & rhs )
191     : BinHeader( rhs )
192 {}
193
194 ///////////////////////////////////////////////////////////////////
195 //
196 //
197 //        METHOD NAME : RpmHeader::~RpmHeader
198 //        METHOD TYPE : Destructor
199 //
200 //        DESCRIPTION :
201 //
202 RpmHeader::~RpmHeader()
203 {}
204
205 ///////////////////////////////////////////////////////////////////
206 //
207 //
208 //        METHOD NAME : RpmHeader::readPackage
209 //        METHOD TYPE : constRpmHeaderPtr
210 //
211 RpmHeader::constPtr RpmHeader::readPackage( const Pathname & path_r,
212                                             VERIFICATION verification_r )
213 {
214   PathInfo file( path_r );
215   if ( ! file.isFile() )
216   {
217     ERR << "Not a file: " << file << endl;
218     return (RpmHeader*)0;
219   }
220
221   FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" );
222   if ( fd == 0 || ::Ferror(fd) )
223   {
224     ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl;
225     if ( fd )
226       ::Fclose( fd );
227     return (RpmHeader*)0;
228   }
229
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) );
238
239   Header nh = 0;
240   int res = ::rpmReadPackageFile( ts, fd, path_r.asString().c_str(), &nh );
241
242   ts = rpmtsFree(ts);
243
244   ::Fclose( fd );
245
246   if ( ! nh )
247   {
248     WAR << "Error reading header from " << path_r << " error(" << res << ")" << endl;
249     return (RpmHeader*)0;
250   }
251
252   RpmHeader::constPtr h( new RpmHeader( nh ) );
253   headerFree( nh ); // clear the reference set in ReadPackageFile
254
255   MIL << h << " from " << path_r << endl;
256   return h;
257 }
258
259 ///////////////////////////////////////////////////////////////////
260 //
261 //
262 //        METHOD NAME : RpmHeader::dumpOn
263 //        METHOD TYPE : std::ostream &
264 //
265 //        DESCRIPTION :
266 //
267 std::ostream & RpmHeader::dumpOn( std::ostream & str ) const
268 {
269   return BinHeader::dumpOn( str ) << '{' << tag_name() << "-"
270          << (tag_epoch()==0?"":(tag_epoch()+":"))
271          << tag_version()
272          << (tag_release().empty()?"":(std::string("-")+tag_release()))
273          << ( isSrc() ? ".src}" : "}");
274 }
275
276
277 ///////////////////////////////////////////////////////////////////
278 //
279 //
280 //        METHOD NAME : RpmHeader::isSrc
281 //        METHOD TYPE : bool
282 //
283 bool RpmHeader::isSrc() const
284 {
285   return has_tag( RPMTAG_SOURCEPACKAGE );
286 }
287
288 ///////////////////////////////////////////////////////////////////
289 //
290 //
291 //        METHOD NAME : RpmHeader::tag_name
292 //        METHOD TYPE : std::string
293 //
294 //        DESCRIPTION :
295 //
296 std::string RpmHeader::tag_name() const
297 {
298   return string_val( RPMTAG_NAME );
299 }
300
301 ///////////////////////////////////////////////////////////////////
302 //
303 //
304 //        METHOD NAME : RpmHeader::tag_epoch
305 //        METHOD TYPE : Edition::epoch_t
306 //
307 //        DESCRIPTION :
308 //
309 Edition::epoch_t RpmHeader::tag_epoch() const
310 {
311   return int_val ( RPMTAG_EPOCH );
312 }
313
314 ///////////////////////////////////////////////////////////////////
315 //
316 //
317 //        METHOD NAME : RpmHeader::tag_version
318 //        METHOD TYPE : std::string
319 //
320 //        DESCRIPTION :
321 //
322 std::string RpmHeader::tag_version() const
323 {
324   return string_val ( RPMTAG_VERSION );
325 }
326
327 ///////////////////////////////////////////////////////////////////
328 //
329 //
330 //        METHOD NAME : RpmHeader::tag_release
331 //        METHOD TYPE : std::string
332 //
333 //        DESCRIPTION :
334 //
335 std::string RpmHeader::tag_release() const
336 {
337   return string_val( RPMTAG_RELEASE );
338 }
339
340 ///////////////////////////////////////////////////////////////////
341 //
342 //
343 //        METHOD NAME : RpmHeader::tag_edition
344 //        METHOD TYPE : Edition
345 //
346 //        DESCRIPTION :
347 //
348 Edition RpmHeader::tag_edition () const
349 {
350   return Edition( tag_version(), tag_release(), tag_epoch() );
351 }
352
353 ///////////////////////////////////////////////////////////////////
354 //
355 //
356 //        METHOD NAME : RpmHeader::tag_arch
357 //        METHOD TYPE : Arch
358 //
359 //        DESCRIPTION :
360 //
361 Arch RpmHeader::tag_arch() const
362 {
363   return Arch( string_val( RPMTAG_ARCH ) );
364 }
365
366 ///////////////////////////////////////////////////////////////////
367 //
368 //
369 //        METHOD NAME : RpmHeader::tag_installtime
370 //        METHOD TYPE : Date
371 //
372 //        DESCRIPTION :
373 //
374 Date RpmHeader::tag_installtime() const
375 {
376   return int_val( RPMTAG_INSTALLTIME );
377 }
378
379 ///////////////////////////////////////////////////////////////////
380 //
381 //
382 //        METHOD NAME : RpmHeader::tag_buildtime
383 //        METHOD TYPE : Date
384 //
385 //        DESCRIPTION :
386 //
387 Date RpmHeader::tag_buildtime() const
388 {
389   return int_val( RPMTAG_BUILDTIME );
390 }
391 #warning CHECK IF FILE REQUIRES HANDLING IS OBSOLETE
392 ///////////////////////////////////////////////////////////////////
393 //
394 //
395 //        METHOD NAME : RpmHeader::PkgRelList_val
396 //        METHOD TYPE : CapabilitySet
397 //
398 //        DESCRIPTION :
399 //
400 CapabilitySet RpmHeader::PkgRelList_val( tag tag_r, bool pre, std::set<std::string> * freq_r ) const
401   {
402     CapabilitySet ret;
403
404     rpmTag  kindFlags   = rpmTag(0);
405     rpmTag  kindVersion = rpmTag(0);
406
407     switch ( tag_r )
408     {
409     case RPMTAG_REQUIRENAME:
410       kindFlags   = RPMTAG_REQUIREFLAGS;
411       kindVersion = RPMTAG_REQUIREVERSION;
412       break;
413     case RPMTAG_PROVIDENAME:
414       kindFlags   = RPMTAG_PROVIDEFLAGS;
415       kindVersion = RPMTAG_PROVIDEVERSION;
416       break;
417     case RPMTAG_OBSOLETENAME:
418       kindFlags   = RPMTAG_OBSOLETEFLAGS;
419       kindVersion = RPMTAG_OBSOLETEVERSION;
420       break;
421     case RPMTAG_CONFLICTNAME:
422       kindFlags   = RPMTAG_CONFLICTFLAGS;
423       kindVersion = RPMTAG_CONFLICTVERSION;
424       break;
425     case RPMTAG_ENHANCESNAME:
426       kindFlags   = RPMTAG_ENHANCESFLAGS;
427       kindVersion = RPMTAG_ENHANCESVERSION;
428       break;
429     case RPMTAG_SUGGESTSNAME:
430       kindFlags   = RPMTAG_SUGGESTSFLAGS;
431       kindVersion = RPMTAG_SUGGESTSVERSION;
432       break;
433     default:
434       INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl;
435       return ret;
436       break;
437     }
438
439     stringList names;
440     unsigned count = string_list( tag_r, names );
441     if ( !count )
442       return ret;
443
444     intList  flags;
445     int_list( kindFlags, flags );
446
447     stringList versions;
448     string_list( kindVersion, versions );
449
450     for ( unsigned i = 0; i < count; ++i )
451     {
452
453       std::string n( names[i] );
454
455       Rel op = Rel::ANY;
456       int32_t f = flags[i];
457       std::string v = versions[i];
458
459       if ( n[0] == '/' )
460       {
461         if ( freq_r )
462         {
463           freq_r->insert( n );
464         }
465       }
466       else
467       {
468         if ( v.size() )
469         {
470           switch ( f & RPMSENSE_SENSEMASK )
471           {
472           case RPMSENSE_LESS:
473             op = Rel::LT;
474             break;
475           case RPMSENSE_LESS|RPMSENSE_EQUAL:
476             op = Rel::LE;
477             break;
478           case RPMSENSE_GREATER:
479             op = Rel::GT;
480             break;
481           case RPMSENSE_GREATER|RPMSENSE_EQUAL:
482             op = Rel::GE;
483             break;
484           case RPMSENSE_EQUAL:
485             op = Rel::EQ;
486             break;
487           }
488         }
489       }
490       if ((pre && (f & RPMSENSE_PREREQ))
491           || ((! pre) && !(f & RPMSENSE_PREREQ)))
492       {
493         try
494         {
495           ret.insert( Capability( n, op, Edition(v) ) );
496         }
497         catch (Exception & excpt_r)
498         {
499           ZYPP_CAUGHT(excpt_r);
500           WAR << "Invalid capability: " << n << " " << op << " "
501           << v << endl;
502         }
503       }
504     }
505
506     return ret;
507   }
508
509 ///////////////////////////////////////////////////////////////////
510 //
511 //
512 //        METHOD NAME : RpmHeader::tag_provides
513 //        METHOD TYPE : CapabilitySet
514 //
515 //        DESCRIPTION :
516 //
517 CapabilitySet RpmHeader::tag_provides( std::set<std::string> * freq_r ) const
518   {
519     return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r );
520   }
521
522 ///////////////////////////////////////////////////////////////////
523 //
524 //
525 //        METHOD NAME : RpmHeader::tag_requires
526 //        METHOD TYPE : CapabilitySet
527 //
528 //        DESCRIPTION :
529 //
530 CapabilitySet RpmHeader::tag_requires( std::set<std::string> * freq_r ) const
531   {
532     return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r );
533   }
534
535 ///////////////////////////////////////////////////////////////////
536 //
537 //
538 //        METHOD NAME : RpmHeader::tag_requires
539 //        METHOD TYPE : CapabilitySet
540 //
541 //        DESCRIPTION :
542 //
543 CapabilitySet RpmHeader::tag_prerequires( std::set<std::string> * freq_r ) const
544   {
545     return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r );
546   }
547
548 ///////////////////////////////////////////////////////////////////
549 //
550 //
551 //        METHOD NAME : RpmHeader::tag_conflicts
552 //        METHOD TYPE : CapabilitySet
553 //
554 //        DESCRIPTION :
555 //
556 CapabilitySet RpmHeader::tag_conflicts( std::set<std::string> * freq_r ) const
557   {
558     return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r );
559   }
560
561 ///////////////////////////////////////////////////////////////////
562 //
563 //
564 //        METHOD NAME : RpmHeader::tag_obsoletes
565 //        METHOD TYPE : CapabilitySet
566 //
567 //        DESCRIPTION :
568 //
569 CapabilitySet RpmHeader::tag_obsoletes( std::set<std::string> * freq_r ) const
570   {
571     return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r );
572   }
573
574 ///////////////////////////////////////////////////////////////////
575 //
576 //
577 //        METHOD NAME : RpmHeader::tag_enhances
578 //        METHOD TYPE : CapabilitySet
579 //
580 //        DESCRIPTION :
581 //
582 CapabilitySet RpmHeader::tag_enhances( std::set<std::string> * freq_r ) const
583   {
584     return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r );
585   }
586
587 ///////////////////////////////////////////////////////////////////
588 //
589 //
590 //        METHOD NAME : RpmHeader::tag_suggests
591 //        METHOD TYPE : CapabilitySet
592 //
593 //        DESCRIPTION :
594 //
595 CapabilitySet RpmHeader::tag_suggests( std::set<std::string> * freq_r ) const
596   {
597     return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r );
598   }
599
600 ///////////////////////////////////////////////////////////////////
601 //
602 //
603 //        METHOD NAME : RpmHeader::tag_size
604 //        METHOD TYPE : ByteCount
605 //
606 //        DESCRIPTION :
607 //
608 ByteCount RpmHeader::tag_size() const
609 {
610   return int_val( RPMTAG_SIZE );
611 }
612
613 ///////////////////////////////////////////////////////////////////
614 //
615 //
616 //        METHOD NAME : RpmHeader::tag_archivesize
617 //        METHOD TYPE : ByteCount
618 //
619 //        DESCRIPTION :
620 //
621 ByteCount RpmHeader::tag_archivesize() const
622 {
623   return int_val( RPMTAG_ARCHIVESIZE );
624 }
625
626 ///////////////////////////////////////////////////////////////////
627 //
628 //
629 //        METHOD NAME : RpmHeader::tag_summary
630 //        METHOD TYPE : std::string
631 //
632 //        DESCRIPTION :
633 //
634 std::string RpmHeader::tag_summary() const
635 {
636   return string_val( RPMTAG_SUMMARY );
637 }
638
639 ///////////////////////////////////////////////////////////////////
640 //
641 //
642 //        METHOD NAME : RpmHeader::tag_description
643 //        METHOD TYPE : std::string
644 //
645 //        DESCRIPTION :
646 //
647 std::string RpmHeader::tag_description() const
648 {
649   return string_val( RPMTAG_DESCRIPTION );
650 }
651
652 ///////////////////////////////////////////////////////////////////
653 //
654 //
655 //        METHOD NAME : RpmHeader::tag_group
656 //        METHOD TYPE : std::string
657 //
658 //        DESCRIPTION :
659 //
660 std::string RpmHeader::tag_group() const
661 {
662   return string_val( RPMTAG_GROUP );
663 }
664
665 ///////////////////////////////////////////////////////////////////
666 //
667 //
668 //        METHOD NAME : RpmHeader::tag_vendor
669 //        METHOD TYPE : std::string
670 //
671 //        DESCRIPTION :
672 //
673 std::string RpmHeader::tag_vendor() const
674 {
675   return string_val( RPMTAG_VENDOR );
676 }
677
678 ///////////////////////////////////////////////////////////////////
679 //
680 //
681 //        METHOD NAME : RpmHeader::tag_distribution
682 //        METHOD TYPE : std::string
683 //
684 //        DESCRIPTION :
685 //
686 std::string RpmHeader::tag_distribution() const
687 {
688   return string_val( RPMTAG_DISTRIBUTION );
689 }
690
691 ///////////////////////////////////////////////////////////////////
692 //
693 //
694 //        METHOD NAME : RpmHeader::tag_license
695 //        METHOD TYPE : std::string
696 //
697 //        DESCRIPTION :
698 //
699 std::string RpmHeader::tag_license() const
700 {
701   return string_val( RPMTAG_LICENSE );
702 }
703
704 ///////////////////////////////////////////////////////////////////
705 //
706 //
707 //        METHOD NAME : RpmHeader::tag_buildhost
708 //        METHOD TYPE : std::string
709 //
710 //        DESCRIPTION :
711 //
712 std::string RpmHeader::tag_buildhost() const
713 {
714   return string_val( RPMTAG_BUILDHOST );
715 }
716
717 ///////////////////////////////////////////////////////////////////
718 //
719 //
720 //        METHOD NAME : RpmHeader::tag_packager
721 //        METHOD TYPE : std::string
722 //
723 //        DESCRIPTION :
724 //
725 std::string RpmHeader::tag_packager() const
726 {
727   return string_val( RPMTAG_PACKAGER );
728 }
729
730 ///////////////////////////////////////////////////////////////////
731 //
732 //
733 //        METHOD NAME : RpmHeader::tag_url
734 //        METHOD TYPE : std::string
735 //
736 //        DESCRIPTION :
737 //
738 std::string RpmHeader::tag_url() const
739 {
740   return string_val( RPMTAG_URL );
741 }
742
743 ///////////////////////////////////////////////////////////////////
744 //
745 //
746 //        METHOD NAME : RpmHeader::tag_os
747 //        METHOD TYPE : std::string
748 //
749 //        DESCRIPTION :
750 //
751 std::string RpmHeader::tag_os() const
752 {
753   return string_val( RPMTAG_OS );
754 }
755
756 ///////////////////////////////////////////////////////////////////
757 //
758 //
759 //        METHOD NAME : RpmHeader::tag_prein
760 //        METHOD TYPE : std::string
761 //
762 //        DESCRIPTION :
763 //
764 std::string RpmHeader::tag_prein() const
765 {
766   return string_val( RPMTAG_PREIN );
767 }
768
769 ///////////////////////////////////////////////////////////////////
770 //
771 //
772 //        METHOD NAME : RpmHeader::tag_postin
773 //        METHOD TYPE : std::string
774 //
775 //        DESCRIPTION :
776 //
777 std::string RpmHeader::tag_postin() const
778 {
779   return string_val( RPMTAG_POSTIN );
780 }
781
782 ///////////////////////////////////////////////////////////////////
783 //
784 //
785 //        METHOD NAME : RpmHeader::tag_preun
786 //        METHOD TYPE : std::string
787 //
788 //        DESCRIPTION :
789 //
790 std::string RpmHeader::tag_preun() const
791 {
792   return string_val( RPMTAG_PREUN );
793 }
794
795 ///////////////////////////////////////////////////////////////////
796 //
797 //
798 //        METHOD NAME : RpmHeader::tag_postun
799 //        METHOD TYPE : std::string
800 //
801 //        DESCRIPTION :
802 //
803 std::string RpmHeader::tag_postun() const
804 {
805   return string_val( RPMTAG_POSTUN );
806 }
807
808 ///////////////////////////////////////////////////////////////////
809 //
810 //
811 //        METHOD NAME : RpmHeader::tag_sourcerpm
812 //        METHOD TYPE : std::string
813 //
814 //        DESCRIPTION :
815 //
816 std::string RpmHeader::tag_sourcerpm() const
817 {
818   return string_val( RPMTAG_SOURCERPM );
819 }
820
821 ///////////////////////////////////////////////////////////////////
822 //
823 //
824 //        METHOD NAME : RpmHeader::tag_filenames
825 //        METHOD TYPE : std::list<std::string>
826 //
827 //        DESCRIPTION :
828 //
829 std::list<std::string> RpmHeader::tag_filenames() const
830 {
831   std::list<std::string> ret;
832
833   stringList basenames;
834   if ( string_list( RPMTAG_BASENAMES, basenames ) )
835   {
836     stringList dirnames;
837     string_list( RPMTAG_DIRNAMES, dirnames );
838     intList  dirindexes;
839     int_list( RPMTAG_DIRINDEXES, dirindexes );
840     for ( unsigned i = 0; i < basenames.size(); ++ i )
841     {
842       ret.push_back( dirnames[dirindexes[i]] + basenames[i] );
843     }
844   }
845
846   return ret;
847 }
848
849 ///////////////////////////////////////////////////////////////////
850 //
851 //
852 //        METHOD NAME : RpmHeader::tag_fileinfos
853 //        METHOD TYPE : std::list<FileInfo>
854 //
855 //        DESCRIPTION :
856 //
857 std::list<FileInfo> RpmHeader::tag_fileinfos() const
858 {
859   std::list<FileInfo> ret;
860
861   stringList basenames;
862   if ( string_list( RPMTAG_BASENAMES, basenames ) )
863   {
864     stringList dirnames;
865     string_list( RPMTAG_DIRNAMES, dirnames );
866     intList  dirindexes;
867     int_list( RPMTAG_DIRINDEXES, dirindexes );
868     intList filesizes;
869     int_list( RPMTAG_FILESIZES, filesizes );
870     stringList md5sums;
871     string_list( RPMTAG_FILEMD5S, md5sums );
872     stringList usernames;
873     string_list( RPMTAG_FILEUSERNAME, usernames );
874     stringList groupnames;
875     string_list( RPMTAG_FILEGROUPNAME, groupnames );
876     intList uids;
877     int_list( RPMTAG_FILEUIDS, uids );
878     intList gids;
879     int_list( RPMTAG_FILEGIDS, gids );
880     intList filemodes;
881     int_list( RPMTAG_FILEMODES, filemodes );
882     intList filemtimes;
883     int_list( RPMTAG_FILEMTIMES, filemtimes );
884     intList fileflags;
885     int_list( RPMTAG_FILEFLAGS, fileflags );
886     stringList filelinks;
887     string_list( RPMTAG_FILELINKTOS, filelinks );
888
889     for ( unsigned i = 0; i < basenames.size(); ++ i )
890     {
891       uid_t uid;
892       if (uids.empty())
893       {
894         uid = unameToUid( usernames[i].c_str(), &uid );
895       }
896       else
897       {
898         uid =uids[i];
899       }
900
901       gid_t gid;
902       if (gids.empty())
903       {
904         gid = gnameToGid( groupnames[i].c_str(), &gid );
905       }
906       else
907       {
908         gid = gids[i];
909       }
910
911       FileInfo info = {
912                         dirnames[dirindexes[i]] + basenames[i],
913                         filesizes[i],
914                         md5sums[i],
915                         uid,
916                         gid,
917                         mode_t(filemodes[i]),
918                         filemtimes[i],
919                         bool(fileflags[i] & RPMFILE_GHOST),
920                         filelinks[i]
921                       };
922
923       ret.push_back( info );
924     }
925   }
926
927   return ret;
928 }
929
930 ///////////////////////////////////////////////////////////////////
931 //
932 //
933 //        METHOD NAME : RpmHeader::tag_changelog
934 //        METHOD TYPE : Changelog
935 //
936 //        DESCRIPTION :
937 //
938 Changelog RpmHeader::tag_changelog() const
939 {
940   Changelog ret;
941
942   intList times;
943   if ( int_list( RPMTAG_CHANGELOGTIME, times ) )
944   {
945     stringList names;
946     string_list( RPMTAG_CHANGELOGNAME, names );
947     stringList texts;
948     string_list( RPMTAG_CHANGELOGTEXT, texts );
949     for ( unsigned i = 0; i < times.size(); ++ i )
950     {
951       ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) );
952     }
953   }
954
955   return ret;
956 }
957
958 ///////////////////////////////////////////////////////////////////
959 //
960 //
961 //        METHOD NAME : RpmHeader::tag_du
962 //        METHOD TYPE : PkgDu &
963 //
964 //        DESCRIPTION :
965 //
966 DiskUsage & RpmHeader::tag_du( DiskUsage & dudata_r ) const
967 {
968   dudata_r.clear();
969   stringList basenames;
970   if ( string_list( RPMTAG_BASENAMES, basenames ) )
971   {
972     stringList dirnames;
973     string_list( RPMTAG_DIRNAMES, dirnames );
974     intList dirindexes;
975     int_list( RPMTAG_DIRINDEXES, dirindexes );
976
977     intList filedevices;
978     int_list( RPMTAG_FILEDEVICES, filedevices );
979     intList fileinodes;
980     int_list( RPMTAG_FILEINODES, fileinodes );
981     intList filesizes;
982     int_list( RPMTAG_FILESIZES, filesizes );
983     intList filemodes;
984     int_list( RPMTAG_FILEMODES, filemodes );
985
986     ///////////////////////////////////////////////////////////////////
987     // Create and collect Entries by index. devino_cache is used to
988     // filter out hardliks ( different name but same device and inode ).
989     ///////////////////////////////////////////////////////////////////
990     filesystem::DevInoCache trace;
991     std::vector<DiskUsage::Entry> entries;
992     entries.resize( dirnames.size() );
993     for ( unsigned i = 0; i < dirnames.size(); ++i )
994     {
995       entries[i] = DiskUsage::Entry( dirnames[i] );
996
997       // cut off deeper directory levels in DiskUsage::Entry
998       unsigned level             = 3; // number of '/' incl. a trailing one
999       std::string::size_type pos = 0; // we know rpm stores absolute pathnames
1000       while ( --level && pos != std::string::npos )
1001       {
1002         pos = entries[i].path.find( "/", pos+1 );
1003       }
1004       if ( pos != std::string::npos )
1005       {
1006         entries[i].path.erase( pos+1 );
1007       }
1008     }
1009
1010     for ( unsigned i = 0; i < basenames.size(); ++ i )
1011     {
1012       filesystem::StatMode mode( filemodes[i] );
1013       if ( mode.isFile() )
1014       {
1015         if ( trace.insert( filedevices[i], fileinodes[i] ) )
1016         {
1017           // Count full 1K blocks
1018           entries[dirindexes[i]]._size += ByteCount( filesizes[i] ).blocks( ByteCount::K );
1019           ++(entries[dirindexes[i]]._files);
1020         }
1021         // else: hardlink; already counted this device/inode
1022       }
1023     }
1024
1025     ///////////////////////////////////////////////////////////////////
1026     // Collect all enties. We first unify the duplicate entries that
1027     // were created by cutting off deeper levels. Then the size of each
1028     // directory must also be added to each of it's parent directories.
1029     ///////////////////////////////////////////////////////////////////
1030     DiskUsage tmpdata;
1031     for ( unsigned i = 0; i < entries.size(); ++i )
1032     {
1033       if ( entries[i]._size )
1034         tmpdata.add( entries[i] );
1035     }
1036
1037     for_( it, tmpdata.begin(), tmpdata.end() )
1038     {
1039       DiskUsage::Entry ent( *it );
1040
1041       do {
1042         dudata_r.add( ent );
1043         if ( ent.path.size() <= 1 ) // "" or "/"
1044           break;
1045
1046         // set path to parent dir. Note that DiskUsage::Entry
1047         // has leading and trailing '/' on pathnmes.
1048         std::string::size_type rstart = ent.path.size() - 2;           // trailing '/' !
1049         std::string::size_type lpos   = ent.path.rfind( '/', rstart ); // one but last '/'
1050         if ( lpos == std::string::npos )
1051           break;
1052
1053         ent.path.erase( lpos + 1 );
1054       } while( true );
1055     }
1056   }
1057   return dudata_r;
1058 }
1059
1060 } // namespace rpm
1061 } // namespace target
1062 } // namespace zypp