~ubuntu-branches/debian/experimental/apt/experimental

« back to all changes in this revision

Viewing changes to apt-pkg/pkgcachegen.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2010-02-18 22:07:23 UTC
  • mfrom: (9.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100218220723-zb7zdh6fmsmp30tr
Tags: 0.7.26~exp2
fix crash when LANGUAGE is not set

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
#define APT_COMPATIBILITY 986
14
14
 
15
15
#include <apt-pkg/pkgcachegen.h>
16
 
#include <apt-pkg/contrib/error.h>
 
16
#include <apt-pkg/error.h>
17
17
#include <apt-pkg/version.h>
18
 
#include <apt-pkg/contrib/progress.h>
 
18
#include <apt-pkg/progress.h>
19
19
#include <apt-pkg/sourcelist.h>
20
 
#include <apt-pkg/contrib/configuration.h>
21
 
#include <apt-pkg/contrib/strutl.h>
22
 
#include <apt-pkg/contrib/sptr.h>
 
20
#include <apt-pkg/configuration.h>
 
21
#include <apt-pkg/strutl.h>
 
22
#include <apt-pkg/sptr.h>
23
23
#include <apt-pkg/pkgsystem.h>
 
24
#include <apt-pkg/macros.h>
24
25
 
25
26
#include <apt-pkg/tagfile.h>
26
27
 
32
33
#include <unistd.h>
33
34
#include <errno.h>
34
35
#include <stdio.h>
35
 
#include <apt-pkg/contrib/system.h>
36
36
                                                                        /*}}}*/
37
37
typedef vector<pkgIndexFile *>::iterator FileIterator;
38
38
 
53
53
   {
54
54
      // Setup the map interface..
55
55
      Cache.HeaderP = (pkgCache::Header *)Map.Data();
56
 
      Map.RawAllocate(sizeof(pkgCache::Header));
 
56
      if (Map.RawAllocate(sizeof(pkgCache::Header)) == 0 && _error->PendingError() == true)
 
57
         return;
 
58
 
57
59
      Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0]));
58
 
      
 
60
 
59
61
      // Starting header
60
62
      *Cache.HeaderP = pkgCache::Header();
61
63
      Cache.HeaderP->VerSysName = Map.WriteString(_system->VS->Label);
62
64
      Cache.HeaderP->Architecture = Map.WriteString(_config->Find("APT::Architecture"));
63
 
      Cache.ReMap(); 
 
65
      Cache.ReMap();
64
66
   }
65
67
   else
66
68
   {
135
137
         pkgCache::VerIterator Ver = Pkg.VersionList();
136
138
         map_ptrloc *LastVer = &Pkg->VersionList;
137
139
 
138
 
         for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) 
 
140
         for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
139
141
         {
140
142
            pkgCache::DescIterator Desc = Ver.DescriptionList();
141
143
            map_ptrloc *LastDesc = &Ver->DescriptionList;
 
144
            bool duplicate=false;
142
145
 
143
146
            // don't add a new description if we have one for the given
144
147
            // md5 && language
145
 
            if(IsDuplicatedTranslation(List, Desc, CurMd5))
 
148
            for ( ; Desc.end() == false; Desc++)
 
149
               if (MD5SumValue(Desc.md5()) == CurMd5 && 
 
150
                   Desc.LanguageCode() == List.DescriptionLanguage())
 
151
                  duplicate=true;
 
152
            if(duplicate)
146
153
               continue;
147
154
            
148
155
            for (Desc = Ver.DescriptionList();
149
 
                 Desc.end() == false; 
 
156
                 Desc.end() == false;
150
157
                 LastDesc = &Desc->NextDesc, Desc++)
151
158
            {
152
159
               if (MD5SumValue(Desc.md5()) == CurMd5) 
155
162
                  *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
156
163
                  Desc->ParentPkg = Pkg.Index();
157
164
                  
158
 
                  if (NewFileDesc(Desc,List) == false)
 
165
                  if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
159
166
                     return _error->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName.c_str());
160
167
                  break;
161
168
               }
215
222
      Ver->ParentPkg = Pkg.Index();
216
223
      Ver->Hash = Hash;
217
224
 
218
 
      if (List.NewVersion(Ver) == false)
 
225
      if ((*LastVer == 0 && _error->PendingError()) || List.NewVersion(Ver) == false)
219
226
         return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
220
227
                              PackageName.c_str());
221
228
 
247
254
      *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
248
255
      Desc->ParentPkg = Pkg.Index();
249
256
 
250
 
      if (NewFileDesc(Desc,List) == false)
 
257
      if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
251
258
         return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str());
252
259
   }
253
260
 
254
261
   FoundFileDeps |= List.HasFileDeps();
255
262
 
 
263
   if (Cache.HeaderP->PackageCount >= (1ULL<<sizeof(Cache.PkgP->ID)*8)-1)
 
264
      return _error->Error(_("Wow, you exceeded the number of package "
 
265
                             "names this APT is capable of."));
 
266
   if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
 
267
      return _error->Error(_("Wow, you exceeded the number of versions "
 
268
                             "this APT is capable of."));
 
269
   if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1)
 
270
      return _error->Error(_("Wow, you exceeded the number of descriptions "
 
271
                             "this APT is capable of."));
 
272
   if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
 
273
      return _error->Error(_("Wow, you exceeded the number of dependencies "
 
274
                             "this APT is capable of."));
256
275
   return true;
257
276
}
258
277
                                                                        /*}}}*/
402
421
   // Get a structure
403
422
   unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
404
423
   if (DescFile == 0)
405
 
      return 0;
 
424
      return false;
406
425
 
407
426
   pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile);
408
427
   DF->File = CurrentFile - Cache.PkgFileP;
443
462
   Desc->ID = Cache.HeaderP->DescriptionCount++;
444
463
   Desc->language_code = Map.WriteString(Lang);
445
464
   Desc->md5sum = Map.WriteString(md5sum.Value());
 
465
   if (Desc->language_code == 0 || Desc->md5sum == 0)
 
466
      return 0;
446
467
 
447
468
   return Description;
448
469
}
635
656
   return ItemP->String;
636
657
}
637
658
                                                                        /*}}}*/
638
 
// CacheGenerator::IsDuplicatedDescription - check for duplicated translations
639
 
// ---------------------------------------------------------------------
640
 
/* check for duplicated translations  */
641
 
bool pkgCacheGenerator::IsDuplicatedTranslation(ListParser &List,
642
 
                                                pkgCache::DescIterator Desc,
643
 
                                                MD5SumValue CurMd5)
644
 
{
645
 
   for ( ; Desc.end() == false; Desc++)
646
 
      if (MD5SumValue(Desc.md5()) == CurMd5 && 
647
 
      Desc.LanguageCode() == List.DescriptionLanguage())
648
 
         return true;
649
 
   return false;
650
 
}
651
 
 
652
 
 
653
659
// CheckValidity - Check that a cache is up-to-date                     /*{{{*/
654
660
// ---------------------------------------------------------------------
655
661
/* This just verifies that each file in the list of index files exists,
658
664
static bool CheckValidity(const string &CacheFile, FileIterator Start, 
659
665
                          FileIterator End,MMap **OutMap = 0)
660
666
{
 
667
   bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
661
668
   // No file, certainly invalid
662
669
   if (CacheFile.empty() == true || FileExists(CacheFile) == false)
 
670
   {
 
671
      if (Debug == true)
 
672
         std::clog << "CacheFile doesn't exist" << std::endl;
663
673
      return false;
664
 
   
 
674
   }
 
675
 
665
676
   // Map it
666
677
   FileFd CacheF(CacheFile,FileFd::ReadOnly);
667
 
   SPtr<MMap> Map = new MMap(CacheF,MMap::Public | MMap::ReadOnly);
 
678
   SPtr<MMap> Map = new MMap(CacheF,0);
668
679
   pkgCache Cache(Map);
669
680
   if (_error->PendingError() == true || Map->Size() == 0)
670
681
   {
 
682
      if (Debug == true)
 
683
         std::clog << "Errors are pending or Map is empty()" << std::endl;
671
684
      _error->Discard();
672
685
      return false;
673
686
   }
677
690
   SPtrArray<bool> Visited = new bool[Cache.HeaderP->PackageFileCount];
678
691
   memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount);
679
692
   for (; Start != End; Start++)
680
 
   {      
 
693
   {
 
694
      if (Debug == true)
 
695
         std::clog << "Checking PkgFile " << (*Start)->Describe() << ": ";
681
696
      if ((*Start)->HasPackages() == false)
 
697
      {
 
698
         if (Debug == true)
 
699
            std::clog << "Has NO packages" << std::endl;
682
700
         continue;
 
701
      }
683
702
    
684
703
      if ((*Start)->Exists() == false)
685
704
      {
687
706
         _error->WarningE("stat",_("Couldn't stat source package list %s"),
688
707
                          (*Start)->Describe().c_str());
689
708
#endif
 
709
         if (Debug == true)
 
710
            std::clog << "file doesn't exist" << std::endl;
690
711
         continue;
691
712
      }
692
713
 
693
714
      // FindInCache is also expected to do an IMS check.
694
715
      pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
695
716
      if (File.end() == true)
 
717
      {
 
718
         if (Debug == true)
 
719
            std::clog << "FindInCache returned end-Pointer" << std::endl;
696
720
         return false;
 
721
      }
697
722
 
698
723
      Visited[File->ID] = true;
 
724
      if (Debug == true)
 
725
         std::clog << "with ID " << File->ID << " is valid" << std::endl;
699
726
   }
700
727
   
701
728
   for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
702
729
      if (Visited[I] == false)
 
730
      {
 
731
         if (Debug == true)
 
732
            std::clog << "File with ID" << I << " wasn't visited" << std::endl;
703
733
         return false;
 
734
      }
704
735
   
705
736
   if (_error->PendingError() == true)
706
737
   {
 
738
      if (Debug == true)
 
739
      {
 
740
         std::clog << "Validity failed because of pending errors:" << std::endl;
 
741
         _error->DumpErrors();
 
742
      }
707
743
      _error->Discard();
708
744
      return false;
709
745
   }
790
826
bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
791
827
                        MMap **OutMap,bool AllowMem)
792
828
{
793
 
   unsigned long MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024);
 
829
   bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
 
830
   unsigned long const MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024);
794
831
   
795
832
   vector<pkgIndexFile *> Files;
796
833
   for (vector<metaIndex *>::const_iterator i = List.begin();
804
841
         Files.push_back (*j);
805
842
   }
806
843
   
807
 
   unsigned long EndOfSource = Files.size();
 
844
   unsigned long const EndOfSource = Files.size();
808
845
   if (_system->AddStatusFiles(Files) == false)
809
846
      return false;
810
 
   
 
847
 
811
848
   // Decide if we can write to the files..
812
 
   string CacheFile = _config->FindFile("Dir::Cache::pkgcache");
813
 
   string SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache");
 
849
   string const CacheFile = _config->FindFile("Dir::Cache::pkgcache");
 
850
   string const SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache");
814
851
   
815
852
   // Decide if we can write to the cache
816
853
   bool Writeable = false;
819
856
   else
820
857
      if (SrcCacheFile.empty() == false)
821
858
         Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0;
822
 
   
 
859
   if (Debug == true)
 
860
      std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl;
 
861
 
823
862
   if (Writeable == false && AllowMem == false && CacheFile.empty() == false)
824
863
      return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str());
825
864
   
829
868
   if (CheckValidity(CacheFile,Files.begin(),Files.end(),OutMap) == true)
830
869
   {
831
870
      Progress.OverallProgress(1,1,1,_("Reading package lists"));
 
871
      if (Debug == true)
 
872
         std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
832
873
      return true;
833
874
   }
 
875
   else if (Debug == true)
 
876
         std::clog << "pkgcache.bin is NOT valid" << std::endl;
834
877
   
835
878
   /* At this point we know we need to reconstruct the package cache,
836
879
      begin. */
844
887
      Map = new DynamicMMap(*CacheF,MMap::Public,MapSize);
845
888
      if (_error->PendingError() == true)
846
889
         return false;
 
890
      if (Debug == true)
 
891
         std::clog << "Open filebased MMap" << std::endl;
847
892
   }
848
893
   else
849
894
   {
850
895
      // Just build it in memory..
851
 
      Map = new DynamicMMap(MMap::Public,MapSize);
 
896
      Map = new DynamicMMap(0,MapSize);
 
897
      if (Debug == true)
 
898
         std::clog << "Open memory Map (not filebased)" << std::endl;
852
899
   }
853
900
   
854
901
   // Lets try the source cache.
857
904
   if (CheckValidity(SrcCacheFile,Files.begin(),
858
905
                     Files.begin()+EndOfSource) == true)
859
906
   {
 
907
      if (Debug == true)
 
908
         std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
860
909
      // Preload the map with the source cache
861
910
      FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly);
862
 
      if (SCacheF.Read((unsigned char *)Map->Data() + Map->RawAllocate(SCacheF.Size()),
863
 
                       SCacheF.Size()) == false)
 
911
      unsigned long const alloc = Map->RawAllocate(SCacheF.Size());
 
912
      if ((alloc == 0 && _error->PendingError())
 
913
                || SCacheF.Read((unsigned char *)Map->Data() + alloc,
 
914
                                SCacheF.Size()) == false)
864
915
         return false;
865
916
 
866
917
      TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
867
 
      
 
918
 
868
919
      // Build the status cache
869
920
      pkgCacheGenerator Gen(Map.Get(),&Progress);
870
921
      if (_error->PendingError() == true)
875
926
   }
876
927
   else
877
928
   {
 
929
      if (Debug == true)
 
930
         std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl;
878
931
      TotalSize = ComputeSize(Files.begin(),Files.end());
879
932
      
880
933
      // Build the source cache
913
966
                     Files.begin()+EndOfSource,Files.end()) == false)
914
967
         return false;
915
968
   }
 
969
   if (Debug == true)
 
970
      std::clog << "Caches are ready for shipping" << std::endl;
916
971
 
917
972
   if (_error->PendingError() == true)
918
973
      return false;
921
976
      if (CacheF != 0)
922
977
      {
923
978
         delete Map.UnGuard();
924
 
         *OutMap = new MMap(*CacheF,MMap::Public | MMap::ReadOnly);
 
979
         *OutMap = new MMap(*CacheF,0);
925
980
      }
926
981
      else
927
982
      {
943
998
   if (_system->AddStatusFiles(Files) == false)
944
999
      return false;
945
1000
   
946
 
   SPtr<DynamicMMap> Map;   
947
 
   Map = new DynamicMMap(MMap::Public,MapSize);
 
1001
   SPtr<DynamicMMap> Map = new DynamicMMap(0,MapSize);
948
1002
   unsigned long CurrentSize = 0;
949
1003
   unsigned long TotalSize = 0;
950
1004