~ubuntu-core-dev/apt/ubuntu

420 by Arch Librarian
cdrom and source support
1
// -*- mode: cpp; mode: fold -*-
2
// Description								/*{{{*/
792 by Arch Librarian
Use std C++ header names for includes
3
// $Id: indexcopy.cc,v 1.10 2002/03/26 07:38:58 jgg Exp $
420 by Arch Librarian
cdrom and source support
4
/* ######################################################################
5
6
   Index Copying - Aid for copying and verifying the index files
7
   
8
   This class helps apt-cache reconstruct a damaged index files. 
9
   
10
   ##################################################################### */
11
									/*}}}*/
12
// Include Files							/*{{{*/
1327.116.1 by David Kalnischkies
reorder includes: add <config.h> if needed and include it at first
13
#include<config.h>
420 by Arch Librarian
cdrom and source support
14
15
#include <apt-pkg/error.h>
16
#include <apt-pkg/progress.h>
17
#include <apt-pkg/strutl.h>
18
#include <apt-pkg/fileutl.h>
1327.126.3 by David Kalnischkies
use getCompressors() instead of getCompressorTypes() and use it everywhere
19
#include <apt-pkg/aptconfiguration.h>
420 by Arch Librarian
cdrom and source support
20
#include <apt-pkg/configuration.h>
21
#include <apt-pkg/tagfile.h>
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
22
#include <apt-pkg/indexrecords.h>
23
#include <apt-pkg/md5.h>
24
#include <apt-pkg/cdrom.h>
420 by Arch Librarian
cdrom and source support
25
792 by Arch Librarian
Use std C++ header names for includes
26
#include <iostream>
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
27
#include <sstream>
420 by Arch Librarian
cdrom and source support
28
#include <unistd.h>
29
#include <sys/stat.h>
1327.60.7 by David Kalnischkies
enhance the split out of the gpgv commandline mangling by splitting out
30
#include <sys/types.h>
31
#include <fcntl.h>
420 by Arch Librarian
cdrom and source support
32
#include <stdio.h>
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
33
#include <stdlib.h>
1327.116.1 by David Kalnischkies
reorder includes: add <config.h> if needed and include it at first
34
35
#include "indexcopy.h"
36
#include <apti18n.h>
420 by Arch Librarian
cdrom and source support
37
									/*}}}*/
38
725 by Arch Librarian
G++3 fixes from Randolph
39
using namespace std;
40
420 by Arch Librarian
cdrom and source support
41
// IndexCopy::CopyPackages - Copy the package files from the CD		/*{{{*/
42
// ---------------------------------------------------------------------
43
/* */
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
44
bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
45
			     pkgCdromStatus *log)
420 by Arch Librarian
cdrom and source support
46
{
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
47
   OpProgress *Progress = NULL;
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
48
   if (List.empty() == true)
420 by Arch Librarian
cdrom and source support
49
      return true;
50
   
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
51
   if(log) 
52
      Progress = log->GetOpProgress();
420 by Arch Librarian
cdrom and source support
53
   
54
   bool NoStat = _config->FindB("APT::CDROM::Fast",false);
55
   bool Debug = _config->FindB("Debug::aptcdrom",false);
56
   
57
   // Prepare the progress indicator
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
58
   off_t TotalSize = 0;
1327.126.3 by David Kalnischkies
use getCompressors() instead of getCompressorTypes() and use it everywhere
59
   std::vector<APT::Configuration::Compressor> const compressor = APT::Configuration::getCompressors();
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
60
   for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
420 by Arch Librarian
cdrom and source support
61
   {
62
      struct stat Buf;
1327.126.3 by David Kalnischkies
use getCompressors() instead of getCompressorTypes() and use it everywhere
63
      bool found = false;
64
      std::string file = std::string(*I).append(GetFileName());
65
      for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
66
	   c != compressor.end(); ++c)
67
      {
68
	 if (stat(std::string(file + c->Extension).c_str(), &Buf) != 0)
69
	    continue;
70
	 found = true;
71
	 break;
72
      }
73
74
      if (found == false)
75
	 return _error->Errno("stat", "Stat failed for %s", file.c_str());
420 by Arch Librarian
cdrom and source support
76
      TotalSize += Buf.st_size;
1327.126.3 by David Kalnischkies
use getCompressors() instead of getCompressorTypes() and use it everywhere
77
   }
420 by Arch Librarian
cdrom and source support
78
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
79
   off_t CurrentSize = 0;
420 by Arch Librarian
cdrom and source support
80
   unsigned int NotFound = 0;
81
   unsigned int WrongSize = 0;
82
   unsigned int Packages = 0;
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
83
   for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
420 by Arch Librarian
cdrom and source support
84
   {      
85
      string OrigPath = string(*I,CDROM.length());
86
      
87
      // Open the package file
1958 by Colin Watson
Fix IndexCopy::CopyPackages and TranslationsCopy::CopyTranslations to
88
      FileFd Pkg(*I + GetFileName(), FileFd::ReadOnly, FileFd::Auto);
1327.126.15 by David Kalnischkies
Allow the FileFd to use an external Compressor to uncompress a given file
89
      off_t const FileSize = Pkg.Size();
1327.126.1 by Steve McIntyre
factored out the decompressor code in IndexCopy::CopyPackages() and
90
615 by Arch Librarian
Join with aliencode
91
      pkgTagFile Parser(&Pkg);
420 by Arch Librarian
cdrom and source support
92
      if (_error->PendingError() == true)
93
	 return false;
94
      
95
      // Open the output file
96
      char S[400];
674 by Arch Librarian
Core correctness patches
97
      snprintf(S,sizeof(S),"cdrom:[%s]/%s%s",Name.c_str(),
98
	       (*I).c_str() + CDROM.length(),GetFileName());
420 by Arch Librarian
cdrom and source support
99
      string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
100
      TargetF += URItoFileName(S);
1327.47.52 by Michael Vogt
do not replace /dev/null when running in APT::CDROM::NoAct
101
      FileFd Target;
420 by Arch Librarian
cdrom and source support
102
      if (_config->FindB("APT::CDROM::NoAct",false) == true)
1327.47.52 by Michael Vogt
do not replace /dev/null when running in APT::CDROM::NoAct
103
      {
420 by Arch Librarian
cdrom and source support
104
	 TargetF = "/dev/null";
1327.47.52 by Michael Vogt
do not replace /dev/null when running in APT::CDROM::NoAct
105
         Target.Open(TargetF,FileFd::WriteExists);
106
      } else {
107
         Target.Open(TargetF,FileFd::WriteAtomic);
108
      }
615 by Arch Librarian
Join with aliencode
109
      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
420 by Arch Librarian
cdrom and source support
110
      if (_error->PendingError() == true)
111
	 return false;
615 by Arch Librarian
Join with aliencode
112
      if (TargetFl == 0)
113
	 return _error->Errno("fdopen","Failed to reopen fd");
420 by Arch Librarian
cdrom and source support
114
      
115
      // Setup the progress meter
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
116
      if(Progress)
117
	 Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
118
				   string("Reading ") + Type() + " Indexes");
420 by Arch Librarian
cdrom and source support
119
120
      // Parse
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
121
      if(Progress)
122
	 Progress->SubProgress(Pkg.Size());
420 by Arch Librarian
cdrom and source support
123
      pkgTagSection Section;
124
      this->Section = &Section;
125
      string Prefix;
126
      unsigned long Hits = 0;
127
      unsigned long Chop = 0;
128
      while (Parser.Step(Section) == true)
129
      {
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
130
	 if(Progress)
131
	    Progress->Progress(Parser.Offset());
420 by Arch Librarian
cdrom and source support
132
	 string File;
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
133
	 unsigned long long Size;
420 by Arch Librarian
cdrom and source support
134
	 if (GetFile(File,Size) == false)
615 by Arch Librarian
Join with aliencode
135
	 {
136
	    fclose(TargetFl);
420 by Arch Librarian
cdrom and source support
137
	    return false;
615 by Arch Librarian
Join with aliencode
138
	 }
420 by Arch Librarian
cdrom and source support
139
	 
140
	 if (Chop != 0)
141
	    File = OrigPath + ChopDirs(File,Chop);
142
	 
143
	 // See if the file exists
144
	 if (NoStat == false || Hits < 10)
145
	 {
146
	    // Attempt to fix broken structure
147
	    if (Hits == 0)
148
	    {
149
	       if (ReconstructPrefix(Prefix,OrigPath,CDROM,File) == false &&
150
		   ReconstructChop(Chop,*I,File) == false)
151
	       {
152
		  if (Debug == true)
153
		     clog << "Missed: " << File << endl;
154
		  NotFound++;
155
		  continue;
156
	       }
157
	       if (Chop != 0)
158
		  File = OrigPath + ChopDirs(File,Chop);
159
	    }
160
	    
161
	    // Get the size
162
	    struct stat Buf;
163
	    if (stat(string(CDROM + Prefix + File).c_str(),&Buf) != 0 || 
164
		Buf.st_size == 0)
165
	    {
1327.173.1 by David Kalnischkies
various simple changes to fix cppcheck warnings
166
	       bool Mangled = false;
420 by Arch Librarian
cdrom and source support
167
	       // Attempt to fix busted symlink support for one instance
168
	       string OrigFile = File;
169
	       string::size_type Start = File.find("binary-");
170
	       string::size_type End = File.find("/",Start+3);
171
	       if (Start != string::npos && End != string::npos)
172
	       {
173
		  File.replace(Start,End-Start,"binary-all");
174
		  Mangled = true;
175
	       }
176
	       
177
	       if (Mangled == false ||
178
		   stat(string(CDROM + Prefix + File).c_str(),&Buf) != 0)
179
	       {
180
		  if (Debug == true)
181
		     clog << "Missed(2): " << OrigFile << endl;
182
		  NotFound++;
183
		  continue;
184
	       }	       
185
	    }	    
186
	    			    	    
187
	    // Size match
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
188
	    if ((unsigned long long)Buf.st_size != Size)
420 by Arch Librarian
cdrom and source support
189
	    {
190
	       if (Debug == true)
191
		  clog << "Wrong Size: " << File << endl;
192
	       WrongSize++;
193
	       continue;
194
	    }
195
	 }
196
	 
197
	 Packages++;
198
	 Hits++;
199
	 
615 by Arch Librarian
Join with aliencode
200
	 if (RewriteEntry(TargetFl,File) == false)
420 by Arch Librarian
cdrom and source support
201
	 {
615 by Arch Librarian
Join with aliencode
202
	    fclose(TargetFl);
203
	    return false;
420 by Arch Librarian
cdrom and source support
204
	 }
205
      }
615 by Arch Librarian
Join with aliencode
206
      fclose(TargetFl);
420 by Arch Librarian
cdrom and source support
207
208
      if (Debug == true)
209
	 cout << " Processed by using Prefix '" << Prefix << "' and chop " << Chop << endl;
210
	 
211
      if (_config->FindB("APT::CDROM::NoAct",false) == false)
212
      {
213
	 // Move out of the partial directory
214
	 Target.Close();
215
	 string FinalF = _config->FindDir("Dir::State::lists");
216
	 FinalF += URItoFileName(S);
217
	 if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
218
	    return _error->Errno("rename","Failed to rename");
219
      }
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
220
	 
420 by Arch Librarian
cdrom and source support
221
      /* Mangle the source to be in the proper notation with
222
       	 prefix dist [component] */ 
223
      *I = string(*I,Prefix.length());
224
      ConvertToSourceList(CDROM,*I);
225
      *I = Prefix + ' ' + *I;
226
      
227
      CurrentSize += FileSize;
228
   }   
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
229
   if(Progress)
230
      Progress->Done();
420 by Arch Librarian
cdrom and source support
231
   
232
   // Some stats
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
233
   if(log) {
234
      stringstream msg;
235
      if(NotFound == 0 && WrongSize == 0)
236
	 ioprintf(msg, _("Wrote %i records.\n"), Packages);
237
      else if (NotFound != 0 && WrongSize == 0)
238
	 ioprintf(msg, _("Wrote %i records with %i missing files.\n"), 
239
		  Packages, NotFound);
240
      else if (NotFound == 0 && WrongSize != 0)
1388 by Matt Zimmerman
Merge bubulle@debian.org--2005/apt--main--0
241
	 ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), 
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
242
		  Packages, WrongSize);
243
      if (NotFound != 0 && WrongSize != 0)
1388 by Matt Zimmerman
Merge bubulle@debian.org--2005/apt--main--0
244
	 ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize);
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
245
   }
420 by Arch Librarian
cdrom and source support
246
   
247
   if (Packages == 0)
766 by Arch Librarian
Fix bug #97364
248
      _error->Warning("No valid records were found.");
249
420 by Arch Librarian
cdrom and source support
250
   if (NotFound + WrongSize > 10)
1327.48.74 by David Kalnischkies
fix another mistake spotted by lintian:
251
      _error->Warning("A lot of entries were discarded, something may be wrong.\n");
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
252
   
420 by Arch Librarian
cdrom and source support
253
254
   return true;
255
}
256
									/*}}}*/
257
// IndexCopy::ChopDirs - Chop off the leading directory components	/*{{{*/
258
// ---------------------------------------------------------------------
259
/* */
260
string IndexCopy::ChopDirs(string Path,unsigned int Depth)
261
{
262
   string::size_type I = 0;
263
   do
264
   {
265
      I = Path.find('/',I+1);
266
      Depth--;
267
   }
268
   while (I != string::npos && Depth != 0);
269
   
270
   if (I == string::npos)
271
      return string();
272
   
273
   return string(Path,I+1);
274
}
275
									/*}}}*/
276
// IndexCopy::ReconstructPrefix - Fix strange prefixing			/*{{{*/
277
// ---------------------------------------------------------------------
278
/* This prepends dir components from the path to the package files to
279
   the path to the deb until it is found */
280
bool IndexCopy::ReconstructPrefix(string &Prefix,string OrigPath,string CD,
281
				  string File)
282
{
283
   bool Debug = _config->FindB("Debug::aptcdrom",false);
284
   unsigned int Depth = 1;
285
   string MyPrefix = Prefix;
286
   while (1)
287
   {
288
      struct stat Buf;
289
      if (stat(string(CD + MyPrefix + File).c_str(),&Buf) != 0)
290
      {
291
	 if (Debug == true)
292
	    cout << "Failed, " << CD + MyPrefix + File << endl;
293
	 if (GrabFirst(OrigPath,MyPrefix,Depth++) == true)
294
	    continue;
295
	 
296
	 return false;
297
      }
298
      else
299
      {
300
	 Prefix = MyPrefix;
301
	 return true;
302
      }      
303
   }
304
   return false;
305
}
306
									/*}}}*/
307
// IndexCopy::ReconstructChop - Fixes bad source paths			/*{{{*/
308
// ---------------------------------------------------------------------
309
/* This removes path components from the filename and prepends the location
310
   of the package files until a file is found */
311
bool IndexCopy::ReconstructChop(unsigned long &Chop,string Dir,string File)
312
{
313
   // Attempt to reconstruct the filename
314
   unsigned long Depth = 0;
315
   while (1)
316
   {
317
      struct stat Buf;
318
      if (stat(string(Dir + File).c_str(),&Buf) != 0)
319
      {
320
	 File = ChopDirs(File,1);
321
	 Depth++;
322
	 if (File.empty() == false)
323
	    continue;
324
	 return false;
325
      }
326
      else
327
      {
328
	 Chop = Depth;
329
	 return true;
330
      }
331
   }
332
   return false;
333
}
334
									/*}}}*/
335
// IndexCopy::ConvertToSourceList - Convert a Path to a sourcelist 	/*{{{*/
336
// ---------------------------------------------------------------------
337
/* We look for things in dists/ notation and convert them to 
338
   <dist> <component> form otherwise it is left alone. This also strips
580 by Arch Librarian
Updates to apt-cdrom to support integrated non-us nicel...
339
   the CD path. 
340
 
341
   This implements a regex sort of like: 
342
    (.*)/dists/([^/]*)/(.*)/binary-* 
343
     ^          ^      ^- Component
344
     |          |-------- Distribution
345
     |------------------- Path
346
   
347
   It was deciced to use only a single word for dist (rather than say
348
   unstable/non-us) to increase the chance that each CD gets a single
349
   line in sources.list.
350
 */
420 by Arch Librarian
cdrom and source support
351
void IndexCopy::ConvertToSourceList(string CD,string &Path)
352
{
353
   // Strip the cdrom base path
354
   Path = string(Path,CD.length());
355
   if (Path.empty() == true)
356
      Path = "/";
357
   
358
   // Too short to be a dists/ type
359
   if (Path.length() < strlen("dists/"))
360
      return;
361
   
362
   // Not a dists type.
725 by Arch Librarian
G++3 fixes from Randolph
363
   if (stringcmp(Path.c_str(),Path.c_str()+strlen("dists/"),"dists/") != 0)
420 by Arch Librarian
cdrom and source support
364
      return;
560 by Arch Librarian
More fixes
365
      
420 by Arch Librarian
cdrom and source support
366
   // Isolate the dist
367
   string::size_type Slash = strlen("dists/");
368
   string::size_type Slash2 = Path.find('/',Slash + 1);
369
   if (Slash2 == string::npos || Slash2 + 2 >= Path.length())
370
      return;
371
   string Dist = string(Path,Slash,Slash2 - Slash);
372
   
373
   // Isolate the component
580 by Arch Librarian
Updates to apt-cdrom to support integrated non-us nicel...
374
   Slash = Slash2;
375
   for (unsigned I = 0; I != 10; I++)
376
   {
377
      Slash = Path.find('/',Slash+1);
378
      if (Slash == string::npos || Slash + 2 >= Path.length())
379
	 return;
380
      string Comp = string(Path,Slash2+1,Slash - Slash2-1);
381
	 
382
      // Verify the trailing binary- bit
383
      string::size_type BinSlash = Path.find('/',Slash + 1);
384
      if (Slash == string::npos)
385
	 return;
386
      string Binary = string(Path,Slash+1,BinSlash - Slash-1);
387
      
1327.157.5 by David Kalnischkies
* apt-pkg/indexcopy.cc:
388
      if (strncmp(Binary.c_str(), "binary-", strlen("binary-")) == 0)
389
      {
390
	 Binary.erase(0, strlen("binary-"));
391
	 if (APT::Configuration::checkArchitecture(Binary) == false)
392
	    continue;
393
      }
394
      else if (Binary != "source")
580 by Arch Librarian
Updates to apt-cdrom to support integrated non-us nicel...
395
	 continue;
396
397
      Path = Dist + ' ' + Comp;
398
      return;
399
   }   
420 by Arch Librarian
cdrom and source support
400
}
401
									/*}}}*/
402
// IndexCopy::GrabFirst - Return the first Depth path components	/*{{{*/
403
// ---------------------------------------------------------------------
404
/* */
405
bool IndexCopy::GrabFirst(string Path,string &To,unsigned int Depth)
406
{
407
   string::size_type I = 0;
408
   do
409
   {
410
      I = Path.find('/',I+1);
411
      Depth--;
412
   }
413
   while (I != string::npos && Depth != 0);
414
   
415
   if (I == string::npos)
416
      return false;
417
418
   To = string(Path,0,I+1);
419
   return true;
420
}
421
									/*}}}*/
422
// PackageCopy::GetFile - Get the file information from the section	/*{{{*/
423
// ---------------------------------------------------------------------
424
/* */
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
425
bool PackageCopy::GetFile(string &File,unsigned long long &Size)
420 by Arch Librarian
cdrom and source support
426
{
427
   File = Section->FindS("Filename");
428
   Size = Section->FindI("Size");
429
   if (File.empty() || Size == 0)
430
      return _error->Error("Cannot find filename or size tag");
431
   return true;
432
}
433
									/*}}}*/
434
// PackageCopy::RewriteEntry - Rewrite the entry with a new filename	/*{{{*/
435
// ---------------------------------------------------------------------
436
/* */
615 by Arch Librarian
Join with aliencode
437
bool PackageCopy::RewriteEntry(FILE *Target,string File)
420 by Arch Librarian
cdrom and source support
438
{
615 by Arch Librarian
Join with aliencode
439
   TFRewriteData Changes[] = {{"Filename",File.c_str()},
440
                              {}};
441
   
442
   if (TFRewrite(Target,*Section,TFRewritePackageOrder,Changes) == false)
443
      return false;
444
   fputc('\n',Target);
445
   return true;
420 by Arch Librarian
cdrom and source support
446
}
447
									/*}}}*/
448
// SourceCopy::GetFile - Get the file information from the section	/*{{{*/
449
// ---------------------------------------------------------------------
450
/* */
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
451
bool SourceCopy::GetFile(string &File,unsigned long long &Size)
420 by Arch Librarian
cdrom and source support
452
{
453
   string Files = Section->FindS("Files");
454
   if (Files.empty() == true)
455
      return false;
456
457
   // Stash the / terminated directory prefix
458
   string Base = Section->FindS("Directory");
459
   if (Base.empty() == false && Base[Base.length()-1] != '/')
460
      Base += '/';
461
   
615 by Arch Librarian
Join with aliencode
462
   // Read the first file triplet
420 by Arch Librarian
cdrom and source support
463
   const char *C = Files.c_str();
464
   string sSize;
465
   string MD5Hash;
466
   
467
   // Parse each of the elements
468
   if (ParseQuoteWord(C,MD5Hash) == false ||
469
       ParseQuoteWord(C,sSize) == false ||
470
       ParseQuoteWord(C,File) == false)
471
      return _error->Error("Error parsing file record");
472
   
473
   // Parse the size and append the directory
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
474
   Size = strtoull(sSize.c_str(), NULL, 10);
420 by Arch Librarian
cdrom and source support
475
   File = Base + File;
476
   return true;
477
}
478
									/*}}}*/
479
// SourceCopy::RewriteEntry - Rewrite the entry with a new filename	/*{{{*/
480
// ---------------------------------------------------------------------
481
/* */
615 by Arch Librarian
Join with aliencode
482
bool SourceCopy::RewriteEntry(FILE *Target,string File)
420 by Arch Librarian
cdrom and source support
483
{
615 by Arch Librarian
Join with aliencode
484
   string Dir(File,0,File.rfind('/'));
485
   TFRewriteData Changes[] = {{"Directory",Dir.c_str()},
486
                              {}};
487
   
488
   if (TFRewrite(Target,*Section,TFRewriteSourceOrder,Changes) == false)
489
      return false;
490
   fputc('\n',Target);
491
   return true;
420 by Arch Librarian
cdrom and source support
492
}
493
									/*}}}*/
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
494
// SigVerify::Verify - Verify a files md5sum against its metaindex     	/*{{{*/
495
// ---------------------------------------------------------------------
496
/* */
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
497
bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
498
{
499
   const indexRecords::checkSum *Record = MetaIndex->Lookup(file);
1327.157.7 by David Kalnischkies
- do not create duplicated flat-archive CD-ROM sources for foreign
500
   bool const Debug = _config->FindB("Debug::aptcdrom",false);
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
501
1327.157.7 by David Kalnischkies
- do not create duplicated flat-archive CD-ROM sources for foreign
502
   // we skip non-existing files in the verifcation of the Release file
503
   // as non-existing files do not harm, but a warning scares people and
504
   // makes it hard to strip unneeded files from an ISO like uncompressed
505
   // indexes as it is done on the mirrors (see also LP: #255545 )
1327.97.1 by Julian Andres Klode
* apt-pkg/indexcopy.cc:
506
   if(!RealFileExists(prefix+file))
1327.29.18 by Michael Vogt
* apt-pkg/indexcopy.cc:
507
   {
1327.157.7 by David Kalnischkies
- do not create duplicated flat-archive CD-ROM sources for foreign
508
      if (Debug == true)
509
	 cout << "Skipping nonexistent in " << prefix << " file " << file << std::endl;
1327.29.18 by Michael Vogt
* apt-pkg/indexcopy.cc:
510
      return true;
511
   }
512
1327.157.7 by David Kalnischkies
- do not create duplicated flat-archive CD-ROM sources for foreign
513
   if (!Record)
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
514
   {
1327.29.80 by Michael Vogt
* apt-pkg/depcache.cc, apt-pkg/indexcopy.cc:
515
      _error->Warning(_("Can't find authentication record for: %s"), file.c_str());
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
516
      return false;
517
   }
518
1327.13.17 by Michael Vogt
* implement sha256/sha1/md5 checking with proper backward compatibility
519
   if (!Record->Hash.VerifyFile(prefix+file))
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
520
   {
1327.29.80 by Michael Vogt
* apt-pkg/depcache.cc, apt-pkg/indexcopy.cc:
521
      _error->Warning(_("Hash mismatch for: %s"),file.c_str());
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
522
      return false;
523
   }
524
1327.157.7 by David Kalnischkies
- do not create duplicated flat-archive CD-ROM sources for foreign
525
   if(Debug == true)
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
526
   {
527
      cout << "File: " << prefix+file << endl;
1327.13.17 by Michael Vogt
* implement sha256/sha1/md5 checking with proper backward compatibility
528
      cout << "Expected Hash " << Record->Hash.toStr() << endl;
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
529
   }
530
531
   return true;
532
}
1327.39.1 by David Kalnischkies
add the various foldmarkers in apt-pkg & cmdline (no code change)
533
									/*}}}*/
534
bool SigVerify::CopyMetaIndex(string CDROM, string CDName,		/*{{{*/
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
535
			      string prefix, string file)
536
{
537
      char S[400];
538
      snprintf(S,sizeof(S),"cdrom:[%s]/%s%s",CDName.c_str(),
539
	       (prefix).c_str() + CDROM.length(),file.c_str());
540
      string TargetF = _config->FindDir("Dir::State::lists");
541
      TargetF += URItoFileName(S);
542
543
      FileFd Target;
544
      FileFd Rel;
1327.24.476 by Julian Andres Klode
apt-pkg, methods: Convert users of WriteEmpty to WriteAtomic.
545
      Target.Open(TargetF,FileFd::WriteAtomic);
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
546
      Rel.Open(prefix + file,FileFd::ReadOnly);
547
      if (_error->PendingError() == true)
548
	 return false;
549
      if (CopyFile(Rel,Target) == false)
550
	 return false;
551
   
552
      return true;
553
}
1327.39.1 by David Kalnischkies
add the various foldmarkers in apt-pkg & cmdline (no code change)
554
									/*}}}*/
555
bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,	/*{{{*/
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
556
			      vector<string> PkgList,vector<string> SrcList)
557
{
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
558
   if (SigList.empty() == true)
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
559
      return true;
560
561
   bool Debug = _config->FindB("Debug::aptcdrom",false);
562
563
   // Read all Release files
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
564
   for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); ++I)
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
565
   { 
566
      if(Debug)
567
	 cout << "Signature verify for: " << *I << endl;
568
569
      indexRecords *MetaIndex = new indexRecords;
570
      string prefix = *I; 
571
1327.60.4 by David Kalnischkies
* apt-pkg/indexcopy.cc:
572
      string const releasegpg = *I+"Release.gpg";
573
      string const release = *I+"Release";
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
574
      string const inrelease = *I+"InRelease";
575
      bool useInRelease = true;
1327.60.4 by David Kalnischkies
* apt-pkg/indexcopy.cc:
576
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
577
      // a Release.gpg without a Release should never happen
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
578
      if (RealFileExists(inrelease) == true)
579
	 ;
580
      else if(RealFileExists(release) == false || RealFileExists(releasegpg) == false)
1327.42.10 by David Kalnischkies
[apt-pkg/indexcopy.cc] fix a (hypothetical) memory leak then the Release
581
      {
582
	 delete MetaIndex;
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
583
	 continue;
1327.42.10 by David Kalnischkies
[apt-pkg/indexcopy.cc] fix a (hypothetical) memory leak then the Release
584
      }
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
585
      else
586
	 useInRelease = false;
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
587
588
      pid_t pid = ExecFork();
589
      if(pid < 0) {
590
	 _error->Error("Fork failed");
591
	 return false;
592
      }
1327.60.7 by David Kalnischkies
enhance the split out of the gpgv commandline mangling by splitting out
593
      if(pid == 0)
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
594
      {
595
	 if (useInRelease == true)
1327.169.1 by David Kalnischkies
* apt-pkg/indexcopy.cc:
596
	    ExecGPGV(inrelease, inrelease);
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
597
	 else
1327.169.1 by David Kalnischkies
* apt-pkg/indexcopy.cc:
598
	    ExecGPGV(release, releasegpg);
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
599
      }
1327.60.7 by David Kalnischkies
enhance the split out of the gpgv commandline mangling by splitting out
600
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
601
      if(!ExecWait(pid, "gpgv")) {
602
	 _error->Warning("Signature verification failed for: %s",
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
603
			 (useInRelease ? inrelease.c_str() : releasegpg.c_str()));
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
604
	 // something went wrong, don't copy the Release.gpg
605
	 // FIXME: delete any existing gpg file?
606
	 continue;
607
      }
608
609
      // Open the Release file and add it to the MetaIndex
1327.60.4 by David Kalnischkies
* apt-pkg/indexcopy.cc:
610
      if(!MetaIndex->Load(release))
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
611
      {
1327.29.16 by Michael Vogt
fix various -Wall warnings
612
	 _error->Error("%s",MetaIndex->ErrorText.c_str());
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
613
	 return false;
614
      }
615
      
616
      // go over the Indexfiles and see if they verify
617
      // if so, remove them from our copy of the lists
618
      vector<string> keys = MetaIndex->MetaKeys();
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
619
      for (vector<string>::iterator I = keys.begin(); I != keys.end(); ++I)
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
620
      { 
621
	 if(!Verify(prefix,*I, MetaIndex)) {
622
	    // something went wrong, don't copy the Release.gpg
623
	    // FIXME: delete any existing gpg file?
1327.29.26 by Michael Vogt
apt-pkg/indexcopy.cc: discard errors after Verify()
624
	    _error->Discard();
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
625
	    continue;	 
626
	 }
627
      }
628
629
      // we need a fresh one for the Release.gpg
630
      delete MetaIndex;
631
   
632
      // everything was fine, copy the Release and Release.gpg file
1327.126.11 by David Kalnischkies
* apt-pkg/cdrom.cc:
633
      if (useInRelease == true)
634
	 CopyMetaIndex(CDROM, Name, prefix, "InRelease");
635
      else
636
      {
637
	 CopyMetaIndex(CDROM, Name, prefix, "Release");
638
	 CopyMetaIndex(CDROM, Name, prefix, "Release.gpg");
639
      }
1370 by Matt Zimmerman
Move CD-ROM handling backend into libapt-pkg
640
   }   
641
642
   return true;
643
}
1327.39.1 by David Kalnischkies
add the various foldmarkers in apt-pkg & cmdline (no code change)
644
									/*}}}*/
645
bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
646
				vector<string> &List, pkgCdromStatus *log)
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
647
{
648
   OpProgress *Progress = NULL;
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
649
   if (List.empty() == true)
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
650
      return true;
651
   
652
   if(log) 
653
      Progress = log->GetOpProgress();
654
   
655
   bool Debug = _config->FindB("Debug::aptcdrom",false);
656
   
657
   // Prepare the progress indicator
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
658
   off_t TotalSize = 0;
1327.126.3 by David Kalnischkies
use getCompressors() instead of getCompressorTypes() and use it everywhere
659
   std::vector<APT::Configuration::Compressor> const compressor = APT::Configuration::getCompressors();
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
660
   for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
661
   {
662
      struct stat Buf;
1327.126.3 by David Kalnischkies
use getCompressors() instead of getCompressorTypes() and use it everywhere
663
      bool found = false;
664
      std::string file = *I;
665
      for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
666
	   c != compressor.end(); ++c)
667
      {
668
	 if (stat(std::string(file + c->Extension).c_str(), &Buf) != 0)
669
	    continue;
670
	 found = true;
671
	 break;
672
      }
673
674
      if (found == false)
675
	 return _error->Errno("stat", "Stat failed for %s", file.c_str());
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
676
      TotalSize += Buf.st_size;
1327.126.3 by David Kalnischkies
use getCompressors() instead of getCompressorTypes() and use it everywhere
677
   }
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
678
1327.116.2 by David Kalnischkies
Support large files in the complete toolset. Indexes of this
679
   off_t CurrentSize = 0;
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
680
   unsigned int NotFound = 0;
681
   unsigned int WrongSize = 0;
682
   unsigned int Packages = 0;
1327.114.3 by David Kalnischkies
cppcheck complains about some possible speed improvements which could be
683
   for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
1327.173.1 by David Kalnischkies
various simple changes to fix cppcheck warnings
684
   {
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
685
      // Open the package file
1958 by Colin Watson
Fix IndexCopy::CopyPackages and TranslationsCopy::CopyTranslations to
686
      FileFd Pkg(*I, FileFd::ReadOnly, FileFd::Auto);
1327.126.15 by David Kalnischkies
Allow the FileFd to use an external Compressor to uncompress a given file
687
      off_t const FileSize = Pkg.Size();
688
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
689
      pkgTagFile Parser(&Pkg);
690
      if (_error->PendingError() == true)
691
	 return false;
692
      
693
      // Open the output file
694
      char S[400];
695
      snprintf(S,sizeof(S),"cdrom:[%s]/%s",Name.c_str(),
696
	       (*I).c_str() + CDROM.length());
697
      string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
698
      TargetF += URItoFileName(S);
1327.154.17 by David Kalnischkies
* apt-pkg/indexcopy.cc:
699
      FileFd Target;
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
700
      if (_config->FindB("APT::CDROM::NoAct",false) == true)
1327.154.17 by David Kalnischkies
* apt-pkg/indexcopy.cc:
701
      {
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
702
	 TargetF = "/dev/null";
1327.154.17 by David Kalnischkies
* apt-pkg/indexcopy.cc:
703
	 Target.Open(TargetF,FileFd::WriteExists);
704
      } else {
705
	 Target.Open(TargetF,FileFd::WriteAtomic);
706
      }
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
707
      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
708
      if (_error->PendingError() == true)
709
	 return false;
710
      if (TargetFl == 0)
711
	 return _error->Errno("fdopen","Failed to reopen fd");
712
      
713
      // Setup the progress meter
714
      if(Progress)
715
	 Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
716
				   string("Reading Translation Indexes"));
717
718
      // Parse
719
      if(Progress)
720
	 Progress->SubProgress(Pkg.Size());
721
      pkgTagSection Section;
722
      this->Section = &Section;
723
      string Prefix;
724
      unsigned long Hits = 0;
725
      while (Parser.Step(Section) == true)
726
      {
727
	 if(Progress)
728
	    Progress->Progress(Parser.Offset());
729
730
	 const char *Start;
731
	 const char *Stop;
732
	 Section.GetSection(Start,Stop);
733
	 fwrite(Start,Stop-Start, 1, TargetFl);
734
	 fputc('\n',TargetFl);
735
736
	 Packages++;
737
	 Hits++;
738
      }
739
      fclose(TargetFl);
740
741
      if (Debug == true)
1327.114.4 by David Kalnischkies
fix a few more cppcheck performance and scope warnings
742
	 cout << " Processed by using Prefix '" << Prefix << "' and chop " << endl;
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
743
	 
744
      if (_config->FindB("APT::CDROM::NoAct",false) == false)
745
      {
746
	 // Move out of the partial directory
747
	 Target.Close();
748
	 string FinalF = _config->FindDir("Dir::State::lists");
749
	 FinalF += URItoFileName(S);
750
	 if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
751
	    return _error->Errno("rename","Failed to rename");
752
      }
753
      
754
      
755
      CurrentSize += FileSize;
756
   }   
757
   if(Progress)
758
      Progress->Done();
759
   
760
   // Some stats
761
   if(log) {
762
      stringstream msg;
763
      if(NotFound == 0 && WrongSize == 0)
764
	 ioprintf(msg, _("Wrote %i records.\n"), Packages);
765
      else if (NotFound != 0 && WrongSize == 0)
766
	 ioprintf(msg, _("Wrote %i records with %i missing files.\n"), 
767
		  Packages, NotFound);
768
      else if (NotFound == 0 && WrongSize != 0)
769
	 ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), 
770
		  Packages, WrongSize);
771
      if (NotFound != 0 && WrongSize != 0)
772
	 ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize);
773
   }
774
   
775
   if (Packages == 0)
776
      _error->Warning("No valid records were found.");
777
778
   if (NotFound + WrongSize > 10)
1327.48.74 by David Kalnischkies
fix another mistake spotted by lintian:
779
      _error->Warning("A lot of entries were discarded, something may be wrong.\n");
1384.1.26 by Michael Vogt
* added a BUGS file with known problem, added apt-cdrom support for translated package descriptions
780
   
781
782
   return true;
783
}
1327.39.1 by David Kalnischkies
add the various foldmarkers in apt-pkg & cmdline (no code change)
784
									/*}}}*/