libzypp  11.13.5
RpmHeader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
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 }
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 
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 
171 
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 
185 //
186 //
187 // METHOD NAME : RpmHeader::RpmHeader
188 // METHOD TYPE : Constructor
189 //
191  : BinHeader( rhs )
192 {}
193 
195 //
196 //
197 // METHOD NAME : RpmHeader::~RpmHeader
198 // METHOD TYPE : Destructor
199 //
200 // DESCRIPTION :
201 //
203 {}
204 
206 //
207 //
208 // METHOD NAME : RpmHeader::readPackage
209 // METHOD TYPE : constRpmHeaderPtr
210 //
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 
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 
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 
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 
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 
302 //
303 //
304 // METHOD NAME : RpmHeader::tag_epoch
305 // METHOD TYPE : Edition::epoch_t
306 //
307 // DESCRIPTION :
308 //
310 {
311  return int_val ( RPMTAG_EPOCH );
312 }
313 
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 
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 
341 //
342 //
343 // METHOD NAME : RpmHeader::tag_edition
344 // METHOD TYPE : Edition
345 //
346 // DESCRIPTION :
347 //
349 {
350  return Edition( tag_version(), tag_release(), tag_epoch() );
351 }
352 
354 //
355 //
356 // METHOD NAME : RpmHeader::tag_arch
357 // METHOD TYPE : Arch
358 //
359 // DESCRIPTION :
360 //
362 {
363  return Arch( string_val( RPMTAG_ARCH ) );
364 }
365 
367 //
368 //
369 // METHOD NAME : RpmHeader::tag_installtime
370 // METHOD TYPE : Date
371 //
372 // DESCRIPTION :
373 //
375 {
376  return int_val( RPMTAG_INSTALLTIME );
377 }
378 
380 //
381 //
382 // METHOD NAME : RpmHeader::tag_buildtime
383 // METHOD TYPE : Date
384 //
385 // DESCRIPTION :
386 //
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 
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 
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 
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 
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 
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 
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 
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 
601 //
602 //
603 // METHOD NAME : RpmHeader::tag_size
604 // METHOD TYPE : ByteCount
605 //
606 // DESCRIPTION :
607 //
609 {
610  return int_val( RPMTAG_SIZE );
611 }
612 
614 //
615 //
616 // METHOD NAME : RpmHeader::tag_archivesize
617 // METHOD TYPE : ByteCount
618 //
619 // DESCRIPTION :
620 //
622 {
623  return int_val( RPMTAG_ARCHIVESIZE );
624 }
625 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
931 //
932 //
933 // METHOD NAME : RpmHeader::tag_changelog
934 // METHOD TYPE : Changelog
935 //
936 // DESCRIPTION :
937 //
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 
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 
987  // Create and collect Entries by index. devino_cache is used to
988  // filter out hardliks ( different name but same device and inode ).
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 
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.
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