]>
git.saurik.com Git - apt.git/blob - apt-pkg/indexcopy.cc
   1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: indexcopy.cc,v 1.10 2002/03/26 07:38:58 jgg Exp $ 
   4 /* ###################################################################### 
   6    Index Copying - Aid for copying and verifying the index files 
   8    This class helps apt-cache reconstruct a damaged index files.  
  10    ##################################################################### */ 
  12 // Include Files                                                        /*{{{*/ 
  15 #include <apt-pkg/error.h> 
  16 #include <apt-pkg/progress.h> 
  17 #include <apt-pkg/strutl.h> 
  18 #include <apt-pkg/fileutl.h> 
  19 #include <apt-pkg/aptconfiguration.h> 
  20 #include <apt-pkg/configuration.h> 
  21 #include <apt-pkg/tagfile.h> 
  22 #include <apt-pkg/metaindex.h> 
  23 #include <apt-pkg/cdrom.h> 
  24 #include <apt-pkg/gpgv.h> 
  25 #include <apt-pkg/hashes.h> 
  26 #include <apt-pkg/debmetaindex.h> 
  36 #include "indexcopy.h" 
  42 // IndexCopy::CopyPackages - Copy the package files from the CD         /*{{{*/ 
  43 // --------------------------------------------------------------------- 
  45 bool IndexCopy::CopyPackages(string CDROM
,string Name
,vector
<string
> &List
, 
  48    OpProgress 
*Progress 
= NULL
; 
  49    if (List
.empty() == true) 
  53       Progress 
= log
->GetOpProgress(); 
  55    bool NoStat 
= _config
->FindB("APT::CDROM::Fast",false); 
  56    bool Debug 
= _config
->FindB("Debug::aptcdrom",false); 
  58    // Prepare the progress indicator 
  60    std::vector
<APT::Configuration::Compressor
> const compressor 
= APT::Configuration::getCompressors(); 
  61    for (vector
<string
>::iterator I 
= List
.begin(); I 
!= List
.end(); ++I
) 
  65       std::string file 
= std::string(*I
).append(GetFileName()); 
  66       for (std::vector
<APT::Configuration::Compressor
>::const_iterator c 
= compressor
.begin(); 
  67            c 
!= compressor
.end(); ++c
) 
  69          if (stat((file 
+ c
->Extension
).c_str(), &Buf
) != 0) 
  76          return _error
->Errno("stat", "Stat failed for %s", file
.c_str()); 
  77       TotalSize 
+= Buf
.st_size
; 
  80    off_t CurrentSize 
= 0; 
  81    unsigned int NotFound 
= 0; 
  82    unsigned int WrongSize 
= 0; 
  83    unsigned int Packages 
= 0; 
  84    for (vector
<string
>::iterator I 
= List
.begin(); I 
!= List
.end(); ++I
) 
  86       string OrigPath 
= string(*I
,CDROM
.length()); 
  88       // Open the package file 
  89       FileFd 
Pkg(*I 
+ GetFileName(), FileFd::ReadOnly
, FileFd::Auto
); 
  90       off_t 
const FileSize 
= Pkg
.Size(); 
  92       pkgTagFile 
Parser(&Pkg
); 
  93       if (_error
->PendingError() == true) 
  96       // Open the output file 
  98       snprintf(S
,sizeof(S
),"cdrom:[%s]/%s%s",Name
.c_str(), 
  99                (*I
).c_str() + CDROM
.length(),GetFileName()); 
 100       string TargetF 
= _config
->FindDir("Dir::State::lists") + "partial/"; 
 101       TargetF 
+= URItoFileName(S
); 
 103       if (_config
->FindB("APT::CDROM::NoAct",false) == true) 
 105          TargetF 
= "/dev/null"; 
 106          Target
.Open(TargetF
,FileFd::WriteExists
); 
 108          Target
.Open(TargetF
,FileFd::WriteAtomic
); 
 110       if (_error
->PendingError() == true) 
 113       // Setup the progress meter 
 115          Progress
->OverallProgress(CurrentSize
,TotalSize
,FileSize
, 
 116                                    string("Reading ") + Type() + " Indexes"); 
 120          Progress
->SubProgress(Pkg
.Size()); 
 121       pkgTagSection Section
; 
 122       this->Section 
= &Section
; 
 124       unsigned long Hits 
= 0; 
 125       unsigned long Chop 
= 0; 
 126       while (Parser
.Step(Section
) == true) 
 129             Progress
->Progress(Parser
.Offset()); 
 131          unsigned long long Size
; 
 132          if (GetFile(File
,Size
) == false) 
 136             File 
= OrigPath 
+ ChopDirs(File
,Chop
); 
 138          // See if the file exists 
 139          if (NoStat 
== false || Hits 
< 10) 
 141             // Attempt to fix broken structure 
 144                if (ReconstructPrefix(Prefix
,OrigPath
,CDROM
,File
) == false && 
 145                    ReconstructChop(Chop
,*I
,File
) == false) 
 148                      clog 
<< "Missed: " << File 
<< endl
; 
 153                   File 
= OrigPath 
+ ChopDirs(File
,Chop
); 
 158             if (stat((CDROM 
+ Prefix 
+ File
).c_str(),&Buf
) != 0 || 
 161                bool Mangled 
= false; 
 162                // Attempt to fix busted symlink support for one instance 
 163                string OrigFile 
= File
; 
 164                string::size_type Start 
= File
.find("binary-"); 
 165                string::size_type End 
= File
.find("/",Start
+3); 
 166                if (Start 
!= string::npos 
&& End 
!= string::npos
) 
 168                   File
.replace(Start
,End
-Start
,"binary-all"); 
 172                if (Mangled 
== false || 
 173                    stat((CDROM 
+ Prefix 
+ File
).c_str(),&Buf
) != 0) 
 176                      clog 
<< "Missed(2): " << OrigFile 
<< endl
; 
 183             if ((unsigned long long)Buf
.st_size 
!= Size
) 
 186                   clog 
<< "Wrong Size: " << File 
<< endl
; 
 195          if (RewriteEntry(Target
, File
) == false) 
 200          cout 
<< " Processed by using Prefix '" << Prefix 
<< "' and chop " << Chop 
<< endl
; 
 202       if (_config
->FindB("APT::CDROM::NoAct",false) == false) 
 204          // Move out of the partial directory 
 206          string FinalF 
= _config
->FindDir("Dir::State::lists"); 
 207          FinalF 
+= URItoFileName(S
); 
 208          if (rename(TargetF
.c_str(),FinalF
.c_str()) != 0) 
 209             return _error
->Errno("rename","Failed to rename"); 
 210          ChangeOwnerAndPermissionOfFile("CopyPackages", FinalF
.c_str(), "root", "root", 0644); 
 213       /* Mangle the source to be in the proper notation with 
 214          prefix dist [component] */ 
 215       *I 
= string(*I
,Prefix
.length()); 
 216       ConvertToSourceList(CDROM
,*I
); 
 217       *I 
= Prefix 
+ ' ' + *I
; 
 219       CurrentSize 
+= FileSize
; 
 227       if(NotFound 
== 0 && WrongSize 
== 0) 
 228          ioprintf(msg
, _("Wrote %i records.\n"), Packages
); 
 229       else if (NotFound 
!= 0 && WrongSize 
== 0) 
 230          ioprintf(msg
, _("Wrote %i records with %i missing files.\n"), 
 232       else if (NotFound 
== 0 && WrongSize 
!= 0) 
 233          ioprintf(msg
, _("Wrote %i records with %i mismatched files\n"), 
 234                   Packages
, WrongSize
); 
 235       if (NotFound 
!= 0 && WrongSize 
!= 0) 
 236          ioprintf(msg
, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages
, NotFound
, WrongSize
); 
 240       _error
->Warning("No valid records were found."); 
 242    if (NotFound 
+ WrongSize 
> 10) 
 243       _error
->Warning("A lot of entries were discarded, something may be wrong.\n"); 
 248 // IndexCopy::ChopDirs - Chop off the leading directory components      /*{{{*/ 
 249 // --------------------------------------------------------------------- 
 251 string 
IndexCopy::ChopDirs(string Path
,unsigned int Depth
) 
 253    string::size_type I 
= 0; 
 256       I 
= Path
.find('/',I
+1); 
 259    while (I 
!= string::npos 
&& Depth 
!= 0); 
 261    if (I 
== string::npos
) 
 264    return string(Path
,I
+1); 
 267 // IndexCopy::ReconstructPrefix - Fix strange prefixing                 /*{{{*/ 
 268 // --------------------------------------------------------------------- 
 269 /* This prepends dir components from the path to the package files to 
 270    the path to the deb until it is found */ 
 271 bool IndexCopy::ReconstructPrefix(string 
&Prefix
,string OrigPath
,string CD
, 
 274    bool Debug 
= _config
->FindB("Debug::aptcdrom",false); 
 275    unsigned int Depth 
= 1; 
 276    string MyPrefix 
= Prefix
; 
 280       if (stat((CD 
+ MyPrefix 
+ File
).c_str(),&Buf
) != 0) 
 283             cout 
<< "Failed, " << CD 
+ MyPrefix 
+ File 
<< endl
; 
 284          if (GrabFirst(OrigPath
,MyPrefix
,Depth
++) == true) 
 298 // IndexCopy::ReconstructChop - Fixes bad source paths                  /*{{{*/ 
 299 // --------------------------------------------------------------------- 
 300 /* This removes path components from the filename and prepends the location 
 301    of the package files until a file is found */ 
 302 bool IndexCopy::ReconstructChop(unsigned long &Chop
,string Dir
,string File
) 
 304    // Attempt to reconstruct the filename 
 305    unsigned long Depth 
= 0; 
 309       if (stat((Dir 
+ File
).c_str(),&Buf
) != 0) 
 311          File 
= ChopDirs(File
,1); 
 313          if (File
.empty() == false) 
 326 // IndexCopy::ConvertToSourceList - Convert a Path to a sourcelist      /*{{{*/ 
 327 // --------------------------------------------------------------------- 
 328 /* We look for things in dists/ notation and convert them to  
 329    <dist> <component> form otherwise it is left alone. This also strips 
 332    This implements a regex sort of like:  
 333     (.*)/dists/([^/]*)/(.*)/binary-*  
 335      |          |-------- Distribution 
 336      |------------------- Path 
 338    It was deciced to use only a single word for dist (rather than say 
 339    unstable/non-us) to increase the chance that each CD gets a single 
 340    line in sources.list. 
 342 void IndexCopy::ConvertToSourceList(string CD
,string 
&Path
) 
 344    // Strip the cdrom base path 
 345    Path 
= string(Path
,CD
.length()); 
 346    if (Path
.empty() == true) 
 349    // Too short to be a dists/ type 
 350    if (Path
.length() < strlen("dists/")) 
 354    if (stringcmp(Path
.c_str(),Path
.c_str()+strlen("dists/"),"dists/") != 0) 
 358    string::size_type Slash 
= strlen("dists/"); 
 359    string::size_type Slash2 
= Path
.find('/',Slash 
+ 1); 
 360    if (Slash2 
== string::npos 
|| Slash2 
+ 2 >= Path
.length()) 
 362    string Dist 
= string(Path
,Slash
,Slash2 
- Slash
); 
 364    // Isolate the component 
 366    for (unsigned I 
= 0; I 
!= 10; I
++) 
 368       Slash 
= Path
.find('/',Slash
+1); 
 369       if (Slash 
== string::npos 
|| Slash 
+ 2 >= Path
.length()) 
 371       string Comp 
= string(Path
,Slash2
+1,Slash 
- Slash2
-1); 
 373       // Verify the trailing binary- bit 
 374       string::size_type BinSlash 
= Path
.find('/',Slash 
+ 1); 
 375       if (Slash 
== string::npos
) 
 377       string Binary 
= string(Path
,Slash
+1,BinSlash 
- Slash
-1); 
 379       if (strncmp(Binary
.c_str(), "binary-", strlen("binary-")) == 0) 
 381          Binary
.erase(0, strlen("binary-")); 
 382          if (APT::Configuration::checkArchitecture(Binary
) == false) 
 385       else if (Binary 
!= "source") 
 388       Path 
= Dist 
+ ' ' + Comp
; 
 393 // IndexCopy::GrabFirst - Return the first Depth path components        /*{{{*/ 
 394 // --------------------------------------------------------------------- 
 396 bool IndexCopy::GrabFirst(string Path
,string 
&To
,unsigned int Depth
) 
 398    string::size_type I 
= 0; 
 401       I 
= Path
.find('/',I
+1); 
 404    while (I 
!= string::npos 
&& Depth 
!= 0); 
 406    if (I 
== string::npos
) 
 409    To 
= string(Path
,0,I
+1); 
 413 // PackageCopy::GetFile - Get the file information from the section     /*{{{*/ 
 414 // --------------------------------------------------------------------- 
 416 bool PackageCopy::GetFile(string 
&File
,unsigned long long &Size
) 
 418    File 
= Section
->FindS("Filename"); 
 419    Size 
= Section
->FindI("Size"); 
 420    if (File
.empty() || Size 
== 0) 
 421       return _error
->Error("Cannot find filename or size tag"); 
 425 // PackageCopy::RewriteEntry - Rewrite the entry with a new filename    /*{{{*/ 
 426 bool PackageCopy::RewriteEntry(FileFd 
&Target
,string 
const &File
) 
 428    std::vector
<pkgTagSection::Tag
> Changes
; 
 429    Changes
.push_back(pkgTagSection::Tag::Rewrite("Filename", File
)); 
 431    if (Section
->Write(Target
, TFRewritePackageOrder
, Changes
) == false) 
 433    return Target
.Write("\n", 1); 
 436 // SourceCopy::GetFile - Get the file information from the section      /*{{{*/ 
 437 // --------------------------------------------------------------------- 
 439 bool SourceCopy::GetFile(string 
&File
,unsigned long long &Size
) 
 441    string Files 
= Section
->FindS("Files"); 
 442    if (Files
.empty() == true) 
 445    // Stash the / terminated directory prefix 
 446    string Base 
= Section
->FindS("Directory"); 
 447    if (Base
.empty() == false && Base
[Base
.length()-1] != '/') 
 450    // Read the first file triplet 
 451    const char *C 
= Files
.c_str(); 
 455    // Parse each of the elements 
 456    if (ParseQuoteWord(C
,MD5Hash
) == false || 
 457        ParseQuoteWord(C
,sSize
) == false || 
 458        ParseQuoteWord(C
,File
) == false) 
 459       return _error
->Error("Error parsing file record"); 
 461    // Parse the size and append the directory 
 462    Size 
= strtoull(sSize
.c_str(), NULL
, 10); 
 467 // SourceCopy::RewriteEntry - Rewrite the entry with a new filename     /*{{{*/ 
 468 bool SourceCopy::RewriteEntry(FileFd 
&Target
, std::string 
const &File
) 
 470    string 
const Dir(File
,0,File
.rfind('/')); 
 471    std::vector
<pkgTagSection::Tag
> Changes
; 
 472    Changes
.push_back(pkgTagSection::Tag::Rewrite("Directory", Dir
)); 
 474    if (Section
->Write(Target
, TFRewriteSourceOrder
, Changes
) == false) 
 476    return Target
.Write("\n", 1); 
 479 // SigVerify::Verify - Verify a files md5sum against its metaindex      /*{{{*/ 
 480 bool SigVerify::Verify(string prefix
, string file
, metaIndex 
*MetaIndex
) 
 482    const metaIndex::checkSum 
*Record 
= MetaIndex
->Lookup(file
); 
 483    bool const Debug 
= _config
->FindB("Debug::aptcdrom",false); 
 485    // we skip non-existing files in the verifcation of the Release file 
 486    // as non-existing files do not harm, but a warning scares people and 
 487    // makes it hard to strip unneeded files from an ISO like uncompressed 
 488    // indexes as it is done on the mirrors (see also LP: #255545 ) 
 489    if(!RealFileExists(prefix
+file
)) 
 492          cout 
<< "Skipping nonexistent in " << prefix 
<< " file " << file 
<< std::endl
; 
 498       _error
->Warning(_("Can't find authentication record for: %s"), file
.c_str()); 
 502    if (!Record
->Hashes
.VerifyFile(prefix
+file
)) 
 504       _error
->Warning(_("Hash mismatch for: %s"),file
.c_str()); 
 510       cout 
<< "File: " << prefix
+file 
<< endl
 
 511          << "Expected Hash " << endl
; 
 512       for (HashStringList::const_iterator hs 
= Record
->Hashes
.begin(); hs 
!= Record
->Hashes
.end(); ++hs
) 
 513          std::cout 
<<  "\t- " << hs
->toStr() << std::endl
; 
 519 bool SigVerify::CopyMetaIndex(string CDROM
, string CDName
,              /*{{{*/ 
 520                               string prefix
, string file
) 
 523       snprintf(S
,sizeof(S
),"cdrom:[%s]/%s%s",CDName
.c_str(), 
 524                (prefix
).c_str() + CDROM
.length(),file
.c_str()); 
 525       string TargetF 
= _config
->FindDir("Dir::State::lists"); 
 526       TargetF 
+= URItoFileName(S
); 
 530       Target
.Open(TargetF
,FileFd::WriteAtomic
); 
 531       Rel
.Open(prefix 
+ file
,FileFd::ReadOnly
); 
 532       if (CopyFile(Rel
,Target
) == false || Target
.Close() == false) 
 533          return _error
->Error("Copying of '%s' for '%s' from '%s' failed", file
.c_str(), CDName
.c_str(), prefix
.c_str()); 
 534       ChangeOwnerAndPermissionOfFile("CopyPackages", TargetF
.c_str(), "root", "root", 0644); 
 539 bool SigVerify::CopyAndVerify(string CDROM
,string Name
,vector
<string
> &SigList
, /*{{{*/ 
 540                               vector
<string
> /*PkgList*/,vector
<string
> /*SrcList*/) 
 542    if (SigList
.empty() == true) 
 545    bool Debug 
= _config
->FindB("Debug::aptcdrom",false); 
 547    // Read all Release files 
 548    for (vector
<string
>::iterator I 
= SigList
.begin(); I 
!= SigList
.end(); ++I
) 
 551          cout 
<< "Signature verify for: " << *I 
<< endl
; 
 553       metaIndex 
*MetaIndex 
= new debReleaseIndex("",""); 
 556       string 
const releasegpg 
= *I
+"Release.gpg"; 
 557       string 
const release 
= *I
+"Release"; 
 558       string 
const inrelease 
= *I
+"InRelease"; 
 559       bool useInRelease 
= true; 
 561       // a Release.gpg without a Release should never happen 
 562       if (RealFileExists(inrelease
) == true) 
 564       else if(RealFileExists(release
) == false || RealFileExists(releasegpg
) == false) 
 570          useInRelease 
= false; 
 572       pid_t pid 
= ExecFork(); 
 574          _error
->Error("Fork failed"); 
 579          if (useInRelease 
== true) 
 580             ExecGPGV(inrelease
, inrelease
); 
 582             ExecGPGV(release
, releasegpg
); 
 585       if(!ExecWait(pid
, "gpgv")) { 
 586          _error
->Warning("Signature verification failed for: %s", 
 587                          (useInRelease 
? inrelease
.c_str() : releasegpg
.c_str())); 
 588          // something went wrong, don't copy the Release.gpg 
 589          // FIXME: delete any existing gpg file? 
 594       // Open the Release file and add it to the MetaIndex 
 595       std::string ErrorText
; 
 596       if(MetaIndex
->Load(release
, &ErrorText
) == false) 
 598          _error
->Error("%s", ErrorText
.c_str()); 
 602       // go over the Indexfiles and see if they verify 
 603       // if so, remove them from our copy of the lists 
 604       vector
<string
> keys 
= MetaIndex
->MetaKeys(); 
 605       for (vector
<string
>::iterator I 
= keys
.begin(); I 
!= keys
.end(); ++I
) 
 607          if(!Verify(prefix
,*I
, MetaIndex
)) { 
 608             // something went wrong, don't copy the Release.gpg 
 609             // FIXME: delete any existing gpg file? 
 615       // we need a fresh one for the Release.gpg 
 618       // everything was fine, copy the Release and Release.gpg file 
 619       if (useInRelease 
== true) 
 620          CopyMetaIndex(CDROM
, Name
, prefix
, "InRelease"); 
 623          CopyMetaIndex(CDROM
, Name
, prefix
, "Release"); 
 624          CopyMetaIndex(CDROM
, Name
, prefix
, "Release.gpg"); 
 631 // SigVerify::RunGPGV - deprecated wrapper calling ExecGPGV             /*{{{*/ 
 632 APT_NORETURN 
bool SigVerify::RunGPGV(std::string 
const &File
, std::string 
const &FileOut
, 
 633       int const &statusfd
, int fd
[2]) { 
 634    ExecGPGV(File
, FileOut
, statusfd
, fd
); 
 636 APT_NORETURN 
bool SigVerify::RunGPGV(std::string 
const &File
, std::string 
const &FileOut
, 
 637       int const &statusfd
) { 
 638    ExecGPGV(File
, FileOut
, statusfd
); 
 641 bool TranslationsCopy::CopyTranslations(string CDROM
,string Name
,       /*{{{*/ 
 642                                 vector
<string
> &List
, pkgCdromStatus 
*log
) 
 644    OpProgress 
*Progress 
= NULL
; 
 645    if (List
.empty() == true) 
 649       Progress 
= log
->GetOpProgress(); 
 651    bool Debug 
= _config
->FindB("Debug::aptcdrom",false); 
 653    // Prepare the progress indicator 
 655    std::vector
<APT::Configuration::Compressor
> const compressor 
= APT::Configuration::getCompressors(); 
 656    for (vector
<string
>::iterator I 
= List
.begin(); I 
!= List
.end(); ++I
) 
 660       std::string file 
= *I
; 
 661       for (std::vector
<APT::Configuration::Compressor
>::const_iterator c 
= compressor
.begin(); 
 662            c 
!= compressor
.end(); ++c
) 
 664          if (stat((file 
+ c
->Extension
).c_str(), &Buf
) != 0) 
 671          return _error
->Errno("stat", "Stat failed for %s", file
.c_str()); 
 672       TotalSize 
+= Buf
.st_size
; 
 675    off_t CurrentSize 
= 0; 
 676    unsigned int NotFound 
= 0; 
 677    unsigned int WrongSize 
= 0; 
 678    unsigned int Packages 
= 0; 
 679    for (vector
<string
>::iterator I 
= List
.begin(); I 
!= List
.end(); ++I
) 
 681       // Open the package file 
 682       FileFd 
Pkg(*I
, FileFd::ReadOnly
, FileFd::Auto
); 
 683       off_t 
const FileSize 
= Pkg
.Size(); 
 685       pkgTagFile 
Parser(&Pkg
); 
 686       if (_error
->PendingError() == true) 
 689       // Open the output file 
 691       snprintf(S
,sizeof(S
),"cdrom:[%s]/%s",Name
.c_str(), 
 692                (*I
).c_str() + CDROM
.length()); 
 693       string TargetF 
= _config
->FindDir("Dir::State::lists") + "partial/"; 
 694       TargetF 
+= URItoFileName(S
); 
 696       if (_config
->FindB("APT::CDROM::NoAct",false) == true) 
 698          TargetF 
= "/dev/null"; 
 699          Target
.Open(TargetF
,FileFd::WriteExists
); 
 701          Target
.Open(TargetF
,FileFd::WriteAtomic
); 
 703       if (_error
->PendingError() == true) 
 706       // Setup the progress meter 
 708          Progress
->OverallProgress(CurrentSize
,TotalSize
,FileSize
, 
 709                                    string("Reading Translation Indexes")); 
 713          Progress
->SubProgress(Pkg
.Size()); 
 714       pkgTagSection Section
; 
 715       this->Section 
= &Section
; 
 717       unsigned long Hits 
= 0; 
 718       while (Parser
.Step(Section
) == true) 
 721             Progress
->Progress(Parser
.Offset()); 
 723          if (Section
.Write(Target
) == false || Target
.Write("\n", 1) == false) 
 731          cout 
<< " Processed by using Prefix '" << Prefix 
<< "' and chop " << endl
; 
 733       if (_config
->FindB("APT::CDROM::NoAct",false) == false) 
 735          // Move out of the partial directory 
 737          string FinalF 
= _config
->FindDir("Dir::State::lists"); 
 738          FinalF 
+= URItoFileName(S
); 
 739          if (rename(TargetF
.c_str(),FinalF
.c_str()) != 0) 
 740             return _error
->Errno("rename","Failed to rename"); 
 741          ChangeOwnerAndPermissionOfFile("CopyTranslations", FinalF
.c_str(), "root", "root", 0644); 
 744       CurrentSize 
+= FileSize
; 
 752       if(NotFound 
== 0 && WrongSize 
== 0) 
 753          ioprintf(msg
, _("Wrote %i records.\n"), Packages
); 
 754       else if (NotFound 
!= 0 && WrongSize 
== 0) 
 755          ioprintf(msg
, _("Wrote %i records with %i missing files.\n"), 
 757       else if (NotFound 
== 0 && WrongSize 
!= 0) 
 758          ioprintf(msg
, _("Wrote %i records with %i mismatched files\n"), 
 759                   Packages
, WrongSize
); 
 760       if (NotFound 
!= 0 && WrongSize 
!= 0) 
 761          ioprintf(msg
, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages
, NotFound
, WrongSize
); 
 765       _error
->Warning("No valid records were found."); 
 767    if (NotFound 
+ WrongSize 
> 10) 
 768       _error
->Warning("A lot of entries were discarded, something may be wrong.\n"); 
 774 IndexCopy::IndexCopy() : d(NULL
) {} 
 775 APT_CONST 
IndexCopy::~IndexCopy() {} 
 777 PackageCopy::PackageCopy() : IndexCopy(), d(NULL
) {} 
 778 APT_CONST 
PackageCopy::~PackageCopy() {} 
 779 SourceCopy::SourceCopy() : IndexCopy(), d(NULL
) {} 
 780 APT_CONST 
SourceCopy::~SourceCopy() {} 
 781 TranslationsCopy::TranslationsCopy() : d(NULL
) {} 
 782 APT_CONST 
TranslationsCopy::~TranslationsCopy() {} 
 783 SigVerify::SigVerify() : d(NULL
) {} 
 784 APT_CONST 
SigVerify::~SigVerify() {}