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

« back to all changes in this revision

Viewing changes to ftparchive/writer.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:
14
14
#include "writer.h"
15
15
    
16
16
#include <apti18n.h>
17
 
#include <apt-pkg/contrib/strutl.h>
18
 
#include <apt-pkg/contrib/error.h>
19
 
#include <apt-pkg/contrib/configuration.h>
20
 
#include <apt-pkg/contrib/md5.h>
21
 
#include <apt-pkg/contrib/sha1.h>
22
 
#include <apt-pkg/contrib/sha256.h>
23
 
#include <apt-pkg/deb/deblistparser.h>
 
17
#include <apt-pkg/strutl.h>
 
18
#include <apt-pkg/error.h>
 
19
#include <apt-pkg/configuration.h>
 
20
#include <apt-pkg/md5.h>
 
21
#include <apt-pkg/sha1.h>
 
22
#include <apt-pkg/sha256.h>
 
23
#include <apt-pkg/deblistparser.h>
24
24
 
25
25
#include <sys/types.h>
26
26
#include <unistd.h>
54
54
// FTWScanner::FTWScanner - Constructor                                 /*{{{*/
55
55
// ---------------------------------------------------------------------
56
56
/* */
57
 
FTWScanner::FTWScanner()
 
57
FTWScanner::FTWScanner(string const &Arch): Arch(Arch)
58
58
{
59
59
   ErrorPrinted = false;
60
60
   NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
61
 
   RealPath = 0;
62
 
   long PMax = pathconf(".",_PC_PATH_MAX);
63
 
   if (PMax > 0)
64
 
      RealPath = new char[PMax];
65
61
}
66
62
                                                                        /*}}}*/
67
63
// FTWScanner::Scanner - FTW Scanner                                    /*{{{*/
89
85
// FTWScanner::ScannerFile - File Scanner                               /*{{{*/
90
86
// ---------------------------------------------------------------------
91
87
/* */
92
 
int FTWScanner::ScannerFile(const char *File, bool ReadLink)
 
88
int FTWScanner::ScannerFile(const char *File, bool const &ReadLink)
93
89
{
94
90
   const char *LastComponent = strrchr(File, '/');
 
91
   char *RealPath = NULL;
 
92
 
95
93
   if (LastComponent == NULL)
96
94
      LastComponent = File;
97
95
   else
98
96
      LastComponent++;
99
97
 
100
 
   vector<string>::iterator I;
 
98
   vector<string>::const_iterator I;
101
99
   for(I = Owner->Patterns.begin(); I != Owner->Patterns.end(); ++I)
102
100
   {
103
101
      if (fnmatch((*I).c_str(), LastComponent, 0) == 0)
111
109
      given are not links themselves. */
112
110
   char Jnk[2];
113
111
   Owner->OriginalPath = File;
114
 
   if (ReadLink && Owner->RealPath != 0 &&
 
112
   if (ReadLink &&
115
113
       readlink(File,Jnk,sizeof(Jnk)) != -1 &&
116
 
       realpath(File,Owner->RealPath) != 0)
117
 
      Owner->DoPackage(Owner->RealPath);
 
114
       (RealPath = realpath(File,NULL)) != 0)
 
115
   {
 
116
      Owner->DoPackage(RealPath);
 
117
      free(RealPath);
 
118
   }
118
119
   else
119
120
      Owner->DoPackage(File);
120
121
   
127
128
      {
128
129
         Owner->NewLine(1);
129
130
         
130
 
         bool Type = _error->PopMessage(Err);
 
131
         bool const Type = _error->PopMessage(Err);
131
132
         if (Type == true)
132
133
            cerr << _("E: ") << Err << endl;
133
134
         else
148
149
// FTWScanner::RecursiveScan - Just scan a directory tree               /*{{{*/
149
150
// ---------------------------------------------------------------------
150
151
/* */
151
 
bool FTWScanner::RecursiveScan(string Dir)
 
152
bool FTWScanner::RecursiveScan(string const &Dir)
152
153
{
 
154
   char *RealPath = NULL;
153
155
   /* If noprefix is set then jam the scan root in, so we don't generate
154
156
      link followed paths out of control */
155
157
   if (InternalPrefix.empty() == true)
156
158
   {
157
 
      if (realpath(Dir.c_str(),RealPath) == 0)
 
159
      if ((RealPath = realpath(Dir.c_str(),NULL)) == 0)
158
160
         return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
159
 
      InternalPrefix = RealPath;      
 
161
      InternalPrefix = RealPath;
 
162
      free(RealPath);
160
163
   }
161
164
   
162
165
   // Do recursive directory searching
163
166
   Owner = this;
164
 
   int Res = ftw(Dir.c_str(),ScannerFTW,30);
 
167
   int const Res = ftw(Dir.c_str(),ScannerFTW,30);
165
168
   
166
169
   // Error treewalking?
167
170
   if (Res != 0)
178
181
// ---------------------------------------------------------------------
179
182
/* This is an alternative to using FTW to locate files, it reads the list
180
183
   of files from another file. */
181
 
bool FTWScanner::LoadFileList(string Dir,string File)
 
184
bool FTWScanner::LoadFileList(string const &Dir, string const &File)
182
185
{
 
186
   char *RealPath = NULL;
183
187
   /* If noprefix is set then jam the scan root in, so we don't generate
184
188
      link followed paths out of control */
185
189
   if (InternalPrefix.empty() == true)
186
190
   {
187
 
      if (realpath(Dir.c_str(),RealPath) == 0)
 
191
      if ((RealPath = realpath(Dir.c_str(),NULL)) == 0)
188
192
         return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
189
193
      InternalPrefix = RealPath;      
 
194
      free(RealPath);
190
195
   }
191
196
   
192
197
   Owner = this;
236
241
/* */
237
242
bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
238
243
                        unsigned long &DeLinkBytes,
239
 
                        off_t FileSize)
 
244
                        off_t const &FileSize)
240
245
{
241
246
   // See if this isn't an internaly prefix'd file name.
242
247
   if (InternalPrefix.empty() == false &&
293
298
// PackagesWriter::PackagesWriter - Constructor                         /*{{{*/
294
299
// ---------------------------------------------------------------------
295
300
/* */
296
 
PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides,
297
 
                               string aArch) :
298
 
   Db(DB),Stats(Db.Stats), Arch(aArch)
 
301
PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string const &ExtOverrides,
 
302
                               string const &Arch) :
 
303
   FTWScanner(Arch), Db(DB), Stats(Db.Stats)
299
304
{
300
305
   Output = stdout;
301
 
   SetExts(".deb .udeb .foo .bar .baz");
302
 
   AddPattern("*.deb");
 
306
   SetExts(".deb .udeb");
303
307
   DeLinkLimit = 0;
304
308
   
305
309
   // Process the command line options
306
310
   DoMD5 = _config->FindB("APT::FTPArchive::MD5",true);
307
311
   DoSHA1 = _config->FindB("APT::FTPArchive::SHA1",true);
308
312
   DoSHA256 = _config->FindB("APT::FTPArchive::SHA256",true);
 
313
   DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false);
309
314
   DoContents = _config->FindB("APT::FTPArchive::Contents",true);
310
315
   NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false);
 
316
   LongDescription = _config->FindB("APT::FTPArchive::LongDescription",true);
311
317
 
312
318
   if (Db.Loaded() == false)
313
319
      DoContents = false;
327
333
// FTWScanner::SetExts - Set extensions to support                      /*{{{*/
328
334
// ---------------------------------------------------------------------
329
335
/* */
330
 
bool FTWScanner::SetExts(string Vals)
 
336
bool FTWScanner::SetExts(string const &Vals)
331
337
{
332
338
   ClearPatterns();
333
339
   string::size_type Start = 0;
334
340
   while (Start <= Vals.length()-1)
335
341
   {
336
 
      string::size_type Space = Vals.find(' ',Start);
337
 
      string::size_type Length;
338
 
      if (Space == string::npos)
 
342
      string::size_type const Space = Vals.find(' ',Start);
 
343
      string::size_type const Length = ((Space == string::npos) ? Vals.length() : Space) - Start;
 
344
      if ( Arch.empty() == false )
339
345
      {
340
 
         Length = Vals.length()-Start;
 
346
         AddPattern(string("*_") + Arch + Vals.substr(Start, Length));
 
347
         AddPattern(string("*_all") + Vals.substr(Start, Length));
341
348
      }
342
349
      else
343
 
      {
344
 
         Length = Space-Start;
345
 
      }
346
 
      AddPattern(string("*") + Vals.substr(Start, Length));
 
350
         AddPattern(string("*") + Vals.substr(Start, Length));
 
351
 
347
352
      Start += Length + 1;
348
353
   }
349
354
 
359
364
bool PackagesWriter::DoPackage(string FileName)
360
365
{      
361
366
   // Pull all the data we need form the DB
362
 
   if (Db.GetFileInfo(FileName, true, DoContents, true, DoMD5, DoSHA1, DoSHA256) 
 
367
   if (Db.GetFileInfo(FileName, true, DoContents, true, DoMD5, DoSHA1, DoSHA256, DoAlwaysStat)
363
368
                  == false)
364
369
   {
365
370
      return false;
414
419
      NewFileName = FileName;
415
420
   if (PathPrefix.empty() == false)
416
421
      NewFileName = flCombine(PathPrefix,NewFileName);
417
 
          
 
422
 
 
423
   /* Configuration says we don't want to include the long Description
 
424
      in the package file - instead we want to ship a separated file */
 
425
   string desc;
 
426
   if (LongDescription == false) {
 
427
      desc = Tags.FindS("Description").append("\n");
 
428
      OverItem->FieldOverride["Description"] = desc.substr(0, desc.find('\n')).c_str();
 
429
   }
 
430
 
418
431
   // This lists all the changes to the fields we are going to make.
419
432
   // (7 hardcoded + maintainer + suggests + end marker)
420
 
   TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1];
 
433
   TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1+1];
421
434
 
422
435
   unsigned int End = 0;
423
436
   SetTFRewriteData(Changes[End++], "Size", Size);
429
442
   SetTFRewriteData(Changes[End++], "Status", 0);
430
443
   SetTFRewriteData(Changes[End++], "Optional", 0);
431
444
 
 
445
   string DescriptionMd5;
 
446
   if (LongDescription == false) {
 
447
      MD5Summation descmd5;
 
448
      descmd5.Add(desc.c_str());
 
449
      DescriptionMd5 = descmd5.Result().Value();
 
450
      SetTFRewriteData(Changes[End++], "Description-md5", DescriptionMd5.c_str());
 
451
   }
 
452
 
432
453
   // Rewrite the maintainer field if necessary
433
454
   bool MaintFailed;
434
455
   string NewMaint = OverItem->SwapMaint(Tags.FindS("Maintainer"),MaintFailed);
446
467
      SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
447
468
   
448
469
   /* Get rid of the Optional tag. This is an ugly, ugly, ugly hack that
449
 
      dpkg-scanpackages does.. Well sort of. dpkg-scanpackages just does renaming
 
470
      dpkg-scanpackages does. Well sort of. dpkg-scanpackages just does renaming
450
471
      but dpkg does this append bit. So we do the append bit, at least that way the
451
472
      status file and package file will remain similar. There are other transforms
452
473
      but optional is the only legacy one still in use for some lazy reason. */
458
479
      SetTFRewriteData(Changes[End++], "Suggests", OptionalStr.c_str());
459
480
   }
460
481
 
461
 
   for (map<string,string>::iterator I = OverItem->FieldOverride.begin(); 
 
482
   for (map<string,string>::const_iterator I = OverItem->FieldOverride.begin(); 
462
483
        I != OverItem->FieldOverride.end(); I++) 
463
484
      SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
464
485
 
476
497
// SourcesWriter::SourcesWriter - Constructor                           /*{{{*/
477
498
// ---------------------------------------------------------------------
478
499
/* */
479
 
SourcesWriter::SourcesWriter(string BOverrides,string SOverrides,
480
 
                             string ExtOverrides)
 
500
SourcesWriter::SourcesWriter(string const &BOverrides,string const &SOverrides,
 
501
                             string const &ExtOverrides)
481
502
{
482
503
   Output = stdout;
483
504
   AddPattern("*.dsc");
537
558
   char *BlkEnd = Buffer + St.st_size;
538
559
   MD5Summation MD5;
539
560
   MD5.Add((unsigned char *)Start,BlkEnd - Start);
540
 
      
 
561
 
 
562
   SHA1Summation SHA1;
 
563
   SHA256Summation SHA256;
 
564
   SHA1.Add((unsigned char *)Start,BlkEnd - Start);
 
565
   SHA256.Add((unsigned char *)Start,BlkEnd - Start);
 
566
 
541
567
   // Add an extra \n to the end, just in case
542
568
   *BlkEnd++ = '\n';
543
569
   
628
654
   }
629
655
   
630
656
   // Add the dsc to the files hash list
 
657
   string const strippedName = flNotDir(FileName);
631
658
   char Files[1000];
632
659
   snprintf(Files,sizeof(Files),"\n %s %lu %s\n %s",
633
660
            string(MD5.Result()).c_str(),St.st_size,
634
 
            flNotDir(FileName).c_str(),
 
661
            strippedName.c_str(),
635
662
            Tags.FindS("Files").c_str());
636
 
   
 
663
 
 
664
   char ChecksumsSha1[1000];
 
665
   snprintf(ChecksumsSha1,sizeof(ChecksumsSha1),"\n %s %lu %s\n %s",
 
666
            string(SHA1.Result()).c_str(),St.st_size,
 
667
            strippedName.c_str(),
 
668
            Tags.FindS("Checksums-Sha1").c_str());
 
669
 
 
670
   char ChecksumsSha256[1000];
 
671
   snprintf(ChecksumsSha256,sizeof(ChecksumsSha256),"\n %s %lu %s\n %s",
 
672
            string(SHA256.Result()).c_str(),St.st_size,
 
673
            strippedName.c_str(),
 
674
            Tags.FindS("Checksums-Sha256").c_str());
 
675
 
637
676
   // Strip the DirStrip prefix from the FileName and add the PathPrefix
638
677
   string NewFileName;
639
678
   if (DirStrip.empty() == false &&
651
690
   // Perform the delinking operation over all of the files
652
691
   string ParseJnk;
653
692
   const char *C = Files;
 
693
   char *RealPath = NULL;
654
694
   for (;isspace(*C); C++);
655
695
   while (*C != 0)
656
696
   {   
662
702
      
663
703
      char Jnk[2];
664
704
      string OriginalPath = Directory + ParseJnk;
665
 
      if (RealPath != 0 && readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 &&
666
 
          realpath(OriginalPath.c_str(),RealPath) != 0)
 
705
      if (readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 &&
 
706
          (RealPath = realpath(OriginalPath.c_str(),NULL)) != 0)
667
707
      {
668
708
         string RP = RealPath;
 
709
         free(RealPath);
669
710
         if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St.st_size) == false)
670
711
            return false;
671
712
      }
676
717
      Directory.erase(Directory.end()-1);
677
718
 
678
719
   // This lists all the changes to the fields we are going to make.
679
 
   // (5 hardcoded + maintainer + end marker)
680
 
   TFRewriteData Changes[5+1+SOverItem->FieldOverride.size()+1];
 
720
   // (5 hardcoded + checksums + maintainer + end marker)
 
721
   TFRewriteData Changes[5+2+1+SOverItem->FieldOverride.size()+1];
681
722
 
682
723
   unsigned int End = 0;
683
724
   SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
684
725
   SetTFRewriteData(Changes[End++],"Files",Files);
 
726
   SetTFRewriteData(Changes[End++],"Checksums-Sha1",ChecksumsSha1);
 
727
   SetTFRewriteData(Changes[End++],"Checksums-Sha256",ChecksumsSha256);
685
728
   if (Directory != "./")
686
729
      SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
687
730
   SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
702
745
   if (NewMaint.empty() == false)
703
746
      SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
704
747
   
705
 
   for (map<string,string>::iterator I = SOverItem->FieldOverride.begin(); 
 
748
   for (map<string,string>::const_iterator I = SOverItem->FieldOverride.begin(); 
706
749
        I != SOverItem->FieldOverride.end(); I++) 
707
750
      SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
708
751
 
722
765
// ContentsWriter::ContentsWriter - Constructor                         /*{{{*/
723
766
// ---------------------------------------------------------------------
724
767
/* */
725
 
ContentsWriter::ContentsWriter(string DB) : 
726
 
                    Db(DB), Stats(Db.Stats)
 
768
ContentsWriter::ContentsWriter(string const &DB, string const &Arch) :
 
769
                    FTWScanner(Arch), Db(DB), Stats(Db.Stats)
727
770
 
728
771
{
729
 
   AddPattern("*.deb");
 
772
   SetExts(".deb");
730
773
   Output = stdout;
731
774
}
732
775
                                                                        /*}}}*/
734
777
// ---------------------------------------------------------------------
735
778
/* If Package is the empty string the control record will be parsed to
736
779
   determine what the package name is. */
737
 
bool ContentsWriter::DoPackage(string FileName,string Package)
 
780
bool ContentsWriter::DoPackage(string FileName, string Package)
738
781
{
739
 
   if (!Db.GetFileInfo(FileName, Package.empty(), true, false, false, false, false))
 
782
   if (!Db.GetFileInfo(FileName, Package.empty(), true, false, false, false, false, false))
740
783
   {
741
784
      return false;
742
785
   }
755
798
// ContentsWriter::ReadFromPkgs - Read from a packages file             /*{{{*/
756
799
// ---------------------------------------------------------------------
757
800
/* */
758
 
bool ContentsWriter::ReadFromPkgs(string PkgFile,string PkgCompress)
 
801
bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompress)
759
802
{
760
803
   MultiCompress Pkgs(PkgFile,PkgCompress,0,false);
761
804
   if (_error->PendingError() == true)
810
853
// ReleaseWriter::ReleaseWriter - Constructor                           /*{{{*/
811
854
// ---------------------------------------------------------------------
812
855
/* */
813
 
ReleaseWriter::ReleaseWriter(string DB)
 
856
ReleaseWriter::ReleaseWriter(string const &DB)
814
857
{
815
858
   AddPattern("Packages");
816
859
   AddPattern("Packages.gz");
817
860
   AddPattern("Packages.bz2");
 
861
   AddPattern("Packages.lzma");
818
862
   AddPattern("Sources");
819
863
   AddPattern("Sources.gz");
820
864
   AddPattern("Sources.bz2");
 
865
   AddPattern("Sources.lzma");
821
866
   AddPattern("Release");
822
867
   AddPattern("md5sum.txt");
823
868
 
824
869
   Output = stdout;
825
 
   time_t now = time(NULL);
 
870
   time_t const now = time(NULL);
826
871
   char datestr[128];
827
872
   if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S UTC",
828
873
                gmtime(&now)) == 0)
909
954
void ReleaseWriter::Finish()
910
955
{
911
956
   fprintf(Output, "MD5Sum:\n");
912
 
   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
 
957
   for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
913
958
       I != CheckSums.end();
914
959
       ++I)
915
960
   {
920
965
   }
921
966
 
922
967
   fprintf(Output, "SHA1:\n");
923
 
   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
 
968
   for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
924
969
       I != CheckSums.end();
925
970
       ++I)
926
971
   {
931
976
   }
932
977
 
933
978
   fprintf(Output, "SHA256:\n");
934
 
   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
 
979
   for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
935
980
       I != CheckSums.end();
936
981
       ++I)
937
982
   {