~l3on/ubuntu/lucid/apt/fix-917845

« back to all changes in this revision

Viewing changes to ftparchive/writer.cc

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2005-03-07 20:08:33 UTC
  • Revision ID: james.westby@ubuntu.com-20050307200833-0lxdgg2cb4oculdv
Tags: 0.6.35
* Merge apt--mvo--0 (incorporates 0.6.34ubuntu1):
  - Implement MaxSize and MaxAge in apt.cron.daily, to prevent the cache
    from growing too large (Ubuntu #6761)
  - some comments about the pkgAcqMetaSig::Custom600Headers() added
  - use gpg --with-colons
  - commented the ftp no_proxy unseting in methods/ftp.cc
  - added support for "Acquire::gpgv::options" in methods/gpgv.cc
* Merge bubulle@debian.org--2005/apt--main--0
  - Make capitalization more consistent
  - Un-fuzzy translations resulting from capitalization changes
  - Italian translation update

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// -*- mode: cpp; mode: fold -*-
2
2
// Description                                                          /*{{{*/
3
 
// $Id: writer.cc,v 1.4 2001/06/26 02:50:27 jgg Exp $
 
3
// $Id: writer.cc,v 1.14 2004/03/24 01:40:43 mdz Exp $
4
4
/* ######################################################################
5
5
 
6
6
   Writer 
17
17
 
18
18
#include "writer.h"
19
19
    
 
20
#include <apti18n.h>
20
21
#include <apt-pkg/strutl.h>
21
22
#include <apt-pkg/error.h>
22
23
#include <apt-pkg/configuration.h>
23
24
#include <apt-pkg/md5.h>
 
25
#include <apt-pkg/sha1.h>
24
26
#include <apt-pkg/deblistparser.h>
25
27
 
26
28
#include <sys/types.h>
27
29
#include <unistd.h>
 
30
#include <ctime>
28
31
#include <ftw.h>
 
32
#include <fnmatch.h>
29
33
#include <iostream>
30
34
    
31
35
#include "cachedb.h"
57
61
{
58
62
   ErrorPrinted = false;
59
63
   NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
60
 
   TmpExt = 0;
61
 
   Ext[0] = 0;
62
64
   RealPath = 0;
63
65
   long PMax = pathconf(".",_PC_PATH_MAX);
64
66
   if (PMax > 0)
74
76
   if (Flag == FTW_DNR)
75
77
   {
76
78
      Owner->NewLine(1);
77
 
      c1out << "W: Unable to read directory " << File << endl;
 
79
      ioprintf(c1out, _("W: Unable to read directory %s\n"), File);
78
80
   }   
79
81
   if (Flag == FTW_NS)
80
82
   {
81
83
      Owner->NewLine(1);
82
 
      c1out << "W: Unable to stat " << File << endl;
 
84
      ioprintf(c1out, _("W: Unable to stat %s\n"), File);
83
85
   }   
84
86
   if (Flag != FTW_F)
85
87
      return 0;
86
88
 
87
 
   // See if it is a .deb
88
 
   if (strlen(File) < 4)
89
 
      return 0;
90
 
   
91
 
   unsigned CurExt = 0;
92
 
   for (; Owner->Ext[CurExt] != 0; CurExt++)
93
 
      if (strcmp(File+strlen(File)-strlen(Owner->Ext[CurExt]),
94
 
                 Owner->Ext[CurExt]) == 0)
95
 
         break;
96
 
   if (Owner->Ext[CurExt] == 0)
 
89
   const char *LastComponent = strrchr(File, '/');
 
90
   if (LastComponent == NULL)
 
91
      LastComponent = File;
 
92
   else
 
93
      LastComponent++;
 
94
 
 
95
   vector<string>::iterator I;
 
96
   for(I = Owner->Patterns.begin(); I != Owner->Patterns.end(); ++I)
 
97
   {
 
98
      if (fnmatch((*I).c_str(), LastComponent, 0) == 0)
 
99
         break;
 
100
   }
 
101
   if (I == Owner->Patterns.end())
97
102
      return 0;
98
103
 
99
104
   /* Process it. If the file is a link then resolve it into an absolute
118
123
         
119
124
         bool Type = _error->PopMessage(Err);
120
125
         if (Type == true)
121
 
            c1out << "E: " << Err << endl;
 
126
            cerr << _("E: ") << Err << endl;
122
127
         else
123
 
            c1out << "W: " << Err << endl;
 
128
            cerr << _("W: ") << Err << endl;
124
129
         
125
130
         if (Err.find(File) != string::npos)
126
131
            SeenPath = true;
127
132
      }      
128
133
      
129
134
      if (SeenPath == false)
130
 
         cerr << "E: Errors apply to file '" << File << "'" << endl;
 
135
         cerr << _("E: Errors apply to file ") << "'" << File << "'" << endl;
131
136
      return 0;
132
137
   }
133
138
   
144
149
   if (InternalPrefix.empty() == true)
145
150
   {
146
151
      if (realpath(Dir.c_str(),RealPath) == 0)
147
 
         return _error->Errno("realpath","Failed to resolve %s",Dir.c_str());
 
152
         return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
148
153
      InternalPrefix = RealPath;      
149
154
   }
150
155
   
156
161
   if (Res != 0)
157
162
   {
158
163
      if (_error->PendingError() == false)
159
 
         _error->Errno("ftw","Tree walking failed");
 
164
         _error->Errno("ftw",_("Tree walking failed"));
160
165
      return false;
161
166
   }
162
167
   
174
179
   if (InternalPrefix.empty() == true)
175
180
   {
176
181
      if (realpath(Dir.c_str(),RealPath) == 0)
177
 
         return _error->Errno("realpath","Failed to resolve %s",Dir.c_str());
 
182
         return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
178
183
      InternalPrefix = RealPath;      
179
184
   }
180
185
   
181
186
   Owner = this;
182
187
   FILE *List = fopen(File.c_str(),"r");
183
188
   if (List == 0)
184
 
      return _error->Errno("fopen","Failed to open %s",File.c_str());
 
189
      return _error->Errno("fopen",_("Failed to open %s"),File.c_str());
185
190
   
186
191
   /* We are a tad tricky here.. We prefix the buffer with the directory
187
192
      name, that way if we need a full path with just use line.. Sneaky and
238
243
            cout << endl;
239
244
         
240
245
         NewLine(1);
241
 
         c1out << " DeLink " << (OriginalPath + InternalPrefix.length())
242
 
            << " [" << SizeToStr(St.st_size) << "B]" << endl << flush;
 
246
         ioprintf(c1out, _(" DeLink %s [%s]\n"), (OriginalPath + InternalPrefix.length()),
 
247
                    SizeToStr(St.st_size).c_str());
 
248
         c1out << flush;
243
249
         
244
250
         if (NoLinkAct == false)
245
251
         {
246
252
            char OldLink[400];
247
253
            if (readlink(OriginalPath,OldLink,sizeof(OldLink)) == -1)
248
 
               _error->Errno("readlink","Failed to readlink %s",OriginalPath);
 
254
               _error->Errno("readlink",_("Failed to readlink %s"),OriginalPath);
249
255
            else
250
256
            {
251
257
               if (unlink(OriginalPath) != 0)
252
 
                  _error->Errno("unlink","Failed to unlink %s",OriginalPath);
 
258
                  _error->Errno("unlink",_("Failed to unlink %s"),OriginalPath);
253
259
               else
254
260
               {
255
261
                  if (link(FileName.c_str(),OriginalPath) != 0)
256
262
                  {
257
263
                     // Panic! Restore the symlink
258
264
                     symlink(OldLink,OriginalPath);
259
 
                     return _error->Errno("link","*** Failed to link %s to %s",
 
265
                     return _error->Errno("link",_("*** Failed to link %s to %s"),
260
266
                                          FileName.c_str(),
261
267
                                          OriginalPath);
262
268
                  }            
266
272
         
267
273
         DeLinkBytes += St.st_size;
268
274
         if (DeLinkBytes/1024 >= DeLinkLimit)
269
 
            c1out << " DeLink limit of " << SizeToStr(DeLinkBytes) << "B hit." << endl;      
 
275
            ioprintf(c1out, _(" DeLink limit of %sB hit.\n"), SizeToStr(DeLinkBytes).c_str());      
270
276
      }
271
277
      
272
278
      FileName = OriginalPath;
275
281
   return true;
276
282
}
277
283
                                                                        /*}}}*/
278
 
// FTWScanner::SetExts - Set extensions to support                      /*{{{*/
279
 
// ---------------------------------------------------------------------
280
 
/* */
281
 
bool FTWScanner::SetExts(string Vals)
282
 
{
283
 
   delete [] TmpExt;
284
 
   TmpExt = new char[Vals.length()+1];
285
 
   strcpy(TmpExt,Vals.c_str());
286
 
   return TokSplitString(' ',TmpExt,(char **)Ext,sizeof(Ext)/sizeof(Ext[0]));
287
 
}
288
 
                                                                        /*}}}*/
289
284
 
290
285
// PackagesWriter::PackagesWriter - Constructor                         /*{{{*/
291
286
// ---------------------------------------------------------------------
294
289
                    Db(DB),Stats(Db.Stats)
295
290
{
296
291
   Output = stdout;
297
 
   Ext[0] = ".deb";
298
 
   Ext[1] = 0;
 
292
   SetExts(".deb .udeb .foo .bar .baz");
 
293
   AddPattern("*.deb");
299
294
   DeLinkLimit = 0;
300
295
   
301
296
   // Process the command line options
317
312
 
318
313
   _error->DumpErrors();
319
314
}
 
315
                                                                        /*}}}*/
 
316
// FTWScanner::SetExts - Set extensions to support                      /*{{{*/
 
317
// ---------------------------------------------------------------------
 
318
/* */
 
319
bool FTWScanner::SetExts(string Vals)
 
320
{
 
321
   ClearPatterns();
 
322
   string::size_type Start = 0;
 
323
   while (Start <= Vals.length()-1)
 
324
   {
 
325
      string::size_type Space = Vals.find(' ',Start);
 
326
      string::size_type Length;
 
327
      if (Space == string::npos)
 
328
      {
 
329
         Length = Vals.length()-Start;
 
330
      }
 
331
      else
 
332
      {
 
333
         Length = Space-Start;
 
334
      }
 
335
      AddPattern(string("*") + Vals.substr(Start, Length));
 
336
      Start += Length + 1;
 
337
   }
 
338
 
 
339
   return true;
 
340
}
 
341
 
320
342
                                                                        /*}}}*/
321
343
// PackagesWriter::DoPackage - Process a single package                 /*{{{*/
322
344
// ---------------------------------------------------------------------
333
355
   // Stat the file for later
334
356
   struct stat St;
335
357
   if (fstat(F.Fd(),&St) != 0)
336
 
      return _error->Errno("fstat","Failed to stat %s",FileName.c_str());
 
358
      return _error->Errno("fstat",_("Failed to stat %s"),FileName.c_str());
337
359
 
338
360
   // Pull all the data we need form the DB
339
361
   string MD5Res;
353
375
   Override::Item *OverItem = Over.GetItem(Package);
354
376
   
355
377
   if (Package.empty() == true)
356
 
      return _error->Error("Archive had no package field");
 
378
      return _error->Error(_("Archive had no package field"));
357
379
   
358
380
   // If we need to do any rewriting of the header do it now..
359
381
   if (OverItem == 0)
361
383
      if (NoOverride == false)
362
384
      {
363
385
         NewLine(1);
364
 
         c1out << "  " << Package << " has no override entry" << endl;
 
386
         ioprintf(c1out, _("  %s has no override entry\n"), Package.c_str());
365
387
      }
366
388
      
367
389
      OverItem = &Tmp;
404
426
      if (NoOverride == false)
405
427
      {
406
428
         NewLine(1);
407
 
         c1out << "  " << Package << " maintainer is " <<
408
 
               Tags.FindS("Maintainer") << " not " <<
409
 
               OverItem->OldMaint << endl;
 
429
         ioprintf(c1out, _("  %s maintainer is %s not %s\n"),
 
430
               Package.c_str(), Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str());
410
431
      }      
411
432
   }
412
433
   
448
469
                             string ExtOverrides)
449
470
{
450
471
   Output = stdout;
451
 
   Ext[0] = ".dsc";
452
 
   Ext[1] = 0;
 
472
   AddPattern("*.dsc");
453
473
   DeLinkLimit = 0;
454
474
   Buffer = 0;
455
475
   BufSize = 0;
535
555
      
536
556
   // Lookup the overide information, finding first the best priority.
537
557
   string BestPrio;
538
 
   char Buffer[1000];
539
558
   string Bins = Tags.FindS("Binary");
 
559
   char Buffer[Bins.length() + 1];
540
560
   Override::Item *OverItem = 0;
541
 
   if (Bins.empty() == false && Bins.length() < sizeof(Buffer))
 
561
   if (Bins.empty() == false)
542
562
   {
543
563
      strcpy(Buffer,Bins.c_str());
544
564
      
572
592
      if (NoOverride == false)
573
593
      {
574
594
         NewLine(1);     
575
 
         c1out << "  " << Tags.FindS("Source") << " has no override entry" << endl;
 
595
         ioprintf(c1out, _("  %s has no override entry\n"), Tags.FindS("Source").c_str());
576
596
      }
577
597
      
578
598
      OverItem = &Tmp;
603
623
      NewFileName = OriginalPath;
604
624
   if (PathPrefix.empty() == false)
605
625
      NewFileName = flCombine(PathPrefix,NewFileName);
606
 
    
 
626
 
607
627
   string Directory = flNotFile(OriginalPath);
608
628
   string Package = Tags.FindS("Source");
609
 
   
 
629
 
610
630
   // Perform the delinking operation over all of the files
611
631
   string ParseJnk;
612
632
   const char *C = Files;
633
653
   Directory = flNotFile(NewFileName);
634
654
   if (Directory.length() > 2)
635
655
      Directory.erase(Directory.end()-1);
636
 
      
 
656
 
637
657
   // This lists all the changes to the fields we are going to make.
638
658
   // (5 hardcoded + maintainer + end marker)
639
659
   TFRewriteData Changes[5+1+SOverItem->FieldOverride.size()+1];
641
661
   unsigned int End = 0;
642
662
   SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
643
663
   SetTFRewriteData(Changes[End++],"Files",Files);
644
 
   SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
 
664
   if (Directory != "./")
 
665
      SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
645
666
   SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
646
667
   SetTFRewriteData(Changes[End++],"Status",0);
647
668
 
653
674
      if (NoOverride == false)
654
675
      {
655
676
         NewLine(1);     
656
 
         c1out << "  " << Package << " maintainer is " <<
657
 
               Tags.FindS("Maintainer") << " not " <<
658
 
               OverItem->OldMaint << endl;
 
677
         ioprintf(c1out, _("  %s maintainer is %s not %s\n"), Package.c_str(),
 
678
               Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str());
659
679
      }      
660
680
   }
661
681
   if (NewMaint.empty() == false)
685
705
                    Db(DB), Stats(Db.Stats)
686
706
 
687
707
{
688
 
   Ext[0] = ".deb";
689
 
   Ext[1] = 0;
 
708
   AddPattern("*.deb");
690
709
   Output = stdout;
691
710
}
692
711
                                                                        /*}}}*/
735
754
   
736
755
   // Open the package file
737
756
   int CompFd = -1;
738
 
   int Proc = -1;
 
757
   pid_t Proc = -1;
739
758
   if (Pkgs.OpenOld(CompFd,Proc) == false)
740
759
      return false;
741
760
   
776
795
   
777
796
   return true;
778
797
}
779
 
                                                                        /*}}}*/
 
798
 
 
799
                                                                        /*}}}*/
 
800
 
 
801
// ReleaseWriter::ReleaseWriter - Constructor                           /*{{{*/
 
802
// ---------------------------------------------------------------------
 
803
/* */
 
804
ReleaseWriter::ReleaseWriter(string DB)
 
805
{
 
806
   AddPattern("Packages");
 
807
   AddPattern("Packages.gz");
 
808
   AddPattern("Packages.bz2");
 
809
   AddPattern("Sources");
 
810
   AddPattern("Sources.gz");
 
811
   AddPattern("Sources.bz2");
 
812
   AddPattern("Release");
 
813
   AddPattern("md5sum.txt");
 
814
 
 
815
   Output = stdout;
 
816
   time_t now = time(NULL);
 
817
   char datestr[128];
 
818
   if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S UTC",
 
819
                gmtime(&now)) == 0)
 
820
   {
 
821
      datestr[0] = '\0';
 
822
   }
 
823
 
 
824
   map<string,string> Fields;
 
825
   Fields["Origin"] = "";
 
826
   Fields["Label"] = "";
 
827
   Fields["Suite"] = "";
 
828
   Fields["Version"] = "";
 
829
   Fields["Codename"] = "";
 
830
   Fields["Date"] = datestr;
 
831
   Fields["Architectures"] = "";
 
832
   Fields["Components"] = "";
 
833
   Fields["Description"] = "";
 
834
 
 
835
   for(map<string,string>::const_iterator I = Fields.begin();
 
836
       I != Fields.end();
 
837
       ++I)
 
838
   {
 
839
      string Config = string("APT::FTPArchive::Release::") + (*I).first;
 
840
      string Value = _config->Find(Config, (*I).second.c_str());
 
841
      if (Value == "")
 
842
         continue;
 
843
 
 
844
      fprintf(Output, "%s: %s\n", (*I).first.c_str(), Value.c_str());
 
845
   }
 
846
}
 
847
                                                                        /*}}}*/
 
848
// ReleaseWriter::DoPackage - Process a single package                  /*{{{*/
 
849
// ---------------------------------------------------------------------
 
850
bool ReleaseWriter::DoPackage(string FileName)
 
851
{
 
852
   // Strip the DirStrip prefix from the FileName and add the PathPrefix
 
853
   string NewFileName;
 
854
   if (DirStrip.empty() == false &&
 
855
       FileName.length() > DirStrip.length() &&
 
856
       stringcmp(FileName.begin(),FileName.begin() + DirStrip.length(),
 
857
                 DirStrip.begin(),DirStrip.end()) == 0)
 
858
   {
 
859
      NewFileName = string(FileName.begin() + DirStrip.length(),FileName.end());
 
860
      while (NewFileName[0] == '/')
 
861
         NewFileName = string(NewFileName.begin() + 1,NewFileName.end());
 
862
   }
 
863
   else 
 
864
      NewFileName = FileName;
 
865
 
 
866
   if (PathPrefix.empty() == false)
 
867
      NewFileName = flCombine(PathPrefix,NewFileName);
 
868
 
 
869
   FileFd fd(FileName, FileFd::ReadOnly);
 
870
 
 
871
   if (!fd.IsOpen())
 
872
   {
 
873
      return false;
 
874
   }
 
875
 
 
876
   CheckSums[NewFileName].size = fd.Size();
 
877
 
 
878
   MD5Summation MD5;
 
879
   MD5.AddFD(fd.Fd(), fd.Size());
 
880
   CheckSums[NewFileName].MD5 = MD5.Result();
 
881
 
 
882
   fd.Seek(0);
 
883
   SHA1Summation SHA1;
 
884
   SHA1.AddFD(fd.Fd(), fd.Size());
 
885
   CheckSums[NewFileName].SHA1 = SHA1.Result();
 
886
 
 
887
   fd.Close();
 
888
   
 
889
   return true;
 
890
}
 
891
 
 
892
                                                                        /*}}}*/
 
893
// ReleaseWriter::Finish - Output the checksums                         /*{{{*/
 
894
// ---------------------------------------------------------------------
 
895
void ReleaseWriter::Finish()
 
896
{
 
897
   fprintf(Output, "MD5Sum:\n");
 
898
   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
 
899
       I != CheckSums.end();
 
900
       ++I)
 
901
   {
 
902
      fprintf(Output, " %s %16ld %s\n",
 
903
              (*I).second.MD5.c_str(),
 
904
              (*I).second.size,
 
905
              (*I).first.c_str());
 
906
   }
 
907
 
 
908
   fprintf(Output, "SHA1:\n");
 
909
   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
 
910
       I != CheckSums.end();
 
911
       ++I)
 
912
   {
 
913
      fprintf(Output, " %s %16ld %s\n",
 
914
              (*I).second.SHA1.c_str(),
 
915
              (*I).second.size,
 
916
              (*I).first.c_str());
 
917
   }
 
918
}
 
919