]>
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/configuration.h>
20 #include <apt-pkg/tagfile.h>
21 #include <apt-pkg/indexrecords.h>
22 #include <apt-pkg/md5.h>
23 #include <apt-pkg/cdrom.h>
29 #include <sys/types.h>
34 #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 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
63 if (stat(string(*I
+ GetFileName()).c_str(),&Buf
) != 0 &&
64 stat(string(*I
+ GetFileName() + ".gz").c_str(),&Buf
) != 0)
65 return _error
->Errno("stat","Stat failed for %s",
66 string(*I
+ GetFileName()).c_str());
67 TotalSize
+= Buf
.st_size
;
70 off_t CurrentSize
= 0;
71 unsigned int NotFound
= 0;
72 unsigned int WrongSize
= 0;
73 unsigned int Packages
= 0;
74 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
76 string OrigPath
= string(*I
,CDROM
.length());
79 // Open the package file
81 if (RealFileExists(*I
+ GetFileName()) == true)
83 Pkg
.Open(*I
+ GetFileName(),FileFd::ReadOnly
);
84 FileSize
= Pkg
.Size();
88 FileFd
From(*I
+ GetFileName() + ".gz",FileFd::ReadOnly
);
89 if (_error
->PendingError() == true)
91 FileSize
= From
.Size();
94 FILE *tmp
= tmpfile();
96 return _error
->Errno("tmpfile","Unable to create a tmp file");
97 Pkg
.Fd(dup(fileno(tmp
)));
101 pid_t Process
= fork();
103 return _error
->Errno("fork","Couldn't fork gzip");
108 dup2(From
.Fd(),STDIN_FILENO
);
109 dup2(Pkg
.Fd(),STDOUT_FILENO
);
110 SetCloseExec(STDIN_FILENO
,false);
111 SetCloseExec(STDOUT_FILENO
,false);
114 string Tmp
= _config
->Find("Dir::bin::gzip","gzip");
115 Args
[0] = Tmp
.c_str();
118 execvp(Args
[0],(char **)Args
);
122 // Wait for gzip to finish
123 if (ExecWait(Process
,_config
->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
124 return _error
->Error("gzip failed, perhaps the disk is full.");
128 pkgTagFile
Parser(&Pkg
);
129 if (_error
->PendingError() == true)
132 // Open the output file
134 snprintf(S
,sizeof(S
),"cdrom:[%s]/%s%s",Name
.c_str(),
135 (*I
).c_str() + CDROM
.length(),GetFileName());
136 string TargetF
= _config
->FindDir("Dir::State::lists") + "partial/";
137 TargetF
+= URItoFileName(S
);
139 if (_config
->FindB("APT::CDROM::NoAct",false) == true)
141 TargetF
= "/dev/null";
142 Target
.Open(TargetF
,FileFd::WriteExists
);
144 Target
.Open(TargetF
,FileFd::WriteAtomic
);
146 FILE *TargetFl
= fdopen(dup(Target
.Fd()),"w");
147 if (_error
->PendingError() == true)
150 return _error
->Errno("fdopen","Failed to reopen fd");
152 // Setup the progress meter
154 Progress
->OverallProgress(CurrentSize
,TotalSize
,FileSize
,
155 string("Reading ") + Type() + " Indexes");
159 Progress
->SubProgress(Pkg
.Size());
160 pkgTagSection Section
;
161 this->Section
= &Section
;
163 unsigned long Hits
= 0;
164 unsigned long Chop
= 0;
165 while (Parser
.Step(Section
) == true)
168 Progress
->Progress(Parser
.Offset());
170 unsigned long long Size
;
171 if (GetFile(File
,Size
) == false)
178 File
= OrigPath
+ ChopDirs(File
,Chop
);
180 // See if the file exists
181 bool Mangled
= false;
182 if (NoStat
== false || Hits
< 10)
184 // Attempt to fix broken structure
187 if (ReconstructPrefix(Prefix
,OrigPath
,CDROM
,File
) == false &&
188 ReconstructChop(Chop
,*I
,File
) == false)
191 clog
<< "Missed: " << File
<< endl
;
196 File
= OrigPath
+ ChopDirs(File
,Chop
);
201 if (stat(string(CDROM
+ Prefix
+ File
).c_str(),&Buf
) != 0 ||
204 // Attempt to fix busted symlink support for one instance
205 string OrigFile
= File
;
206 string::size_type Start
= File
.find("binary-");
207 string::size_type End
= File
.find("/",Start
+3);
208 if (Start
!= string::npos
&& End
!= string::npos
)
210 File
.replace(Start
,End
-Start
,"binary-all");
214 if (Mangled
== false ||
215 stat(string(CDROM
+ Prefix
+ File
).c_str(),&Buf
) != 0)
218 clog
<< "Missed(2): " << OrigFile
<< endl
;
225 if ((unsigned long long)Buf
.st_size
!= Size
)
228 clog
<< "Wrong Size: " << File
<< endl
;
237 if (RewriteEntry(TargetFl
,File
) == false)
246 cout
<< " Processed by using Prefix '" << Prefix
<< "' and chop " << Chop
<< endl
;
248 if (_config
->FindB("APT::CDROM::NoAct",false) == false)
250 // Move out of the partial directory
252 string FinalF
= _config
->FindDir("Dir::State::lists");
253 FinalF
+= URItoFileName(S
);
254 if (rename(TargetF
.c_str(),FinalF
.c_str()) != 0)
255 return _error
->Errno("rename","Failed to rename");
258 /* Mangle the source to be in the proper notation with
259 prefix dist [component] */
260 *I
= string(*I
,Prefix
.length());
261 ConvertToSourceList(CDROM
,*I
);
262 *I
= Prefix
+ ' ' + *I
;
264 CurrentSize
+= FileSize
;
272 if(NotFound
== 0 && WrongSize
== 0)
273 ioprintf(msg
, _("Wrote %i records.\n"), Packages
);
274 else if (NotFound
!= 0 && WrongSize
== 0)
275 ioprintf(msg
, _("Wrote %i records with %i missing files.\n"),
277 else if (NotFound
== 0 && WrongSize
!= 0)
278 ioprintf(msg
, _("Wrote %i records with %i mismatched files\n"),
279 Packages
, WrongSize
);
280 if (NotFound
!= 0 && WrongSize
!= 0)
281 ioprintf(msg
, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages
, NotFound
, WrongSize
);
285 _error
->Warning("No valid records were found.");
287 if (NotFound
+ WrongSize
> 10)
288 _error
->Warning("A lot of entries were discarded, something may be wrong.\n");
294 // IndexCopy::ChopDirs - Chop off the leading directory components /*{{{*/
295 // ---------------------------------------------------------------------
297 string
IndexCopy::ChopDirs(string Path
,unsigned int Depth
)
299 string::size_type I
= 0;
302 I
= Path
.find('/',I
+1);
305 while (I
!= string::npos
&& Depth
!= 0);
307 if (I
== string::npos
)
310 return string(Path
,I
+1);
313 // IndexCopy::ReconstructPrefix - Fix strange prefixing /*{{{*/
314 // ---------------------------------------------------------------------
315 /* This prepends dir components from the path to the package files to
316 the path to the deb until it is found */
317 bool IndexCopy::ReconstructPrefix(string
&Prefix
,string OrigPath
,string CD
,
320 bool Debug
= _config
->FindB("Debug::aptcdrom",false);
321 unsigned int Depth
= 1;
322 string MyPrefix
= Prefix
;
326 if (stat(string(CD
+ MyPrefix
+ File
).c_str(),&Buf
) != 0)
329 cout
<< "Failed, " << CD
+ MyPrefix
+ File
<< endl
;
330 if (GrabFirst(OrigPath
,MyPrefix
,Depth
++) == true)
344 // IndexCopy::ReconstructChop - Fixes bad source paths /*{{{*/
345 // ---------------------------------------------------------------------
346 /* This removes path components from the filename and prepends the location
347 of the package files until a file is found */
348 bool IndexCopy::ReconstructChop(unsigned long &Chop
,string Dir
,string File
)
350 // Attempt to reconstruct the filename
351 unsigned long Depth
= 0;
355 if (stat(string(Dir
+ File
).c_str(),&Buf
) != 0)
357 File
= ChopDirs(File
,1);
359 if (File
.empty() == false)
372 // IndexCopy::ConvertToSourceList - Convert a Path to a sourcelist /*{{{*/
373 // ---------------------------------------------------------------------
374 /* We look for things in dists/ notation and convert them to
375 <dist> <component> form otherwise it is left alone. This also strips
378 This implements a regex sort of like:
379 (.*)/dists/([^/]*)/(.*)/binary-*
381 | |-------- Distribution
382 |------------------- Path
384 It was deciced to use only a single word for dist (rather than say
385 unstable/non-us) to increase the chance that each CD gets a single
386 line in sources.list.
388 void IndexCopy::ConvertToSourceList(string CD
,string
&Path
)
391 snprintf(S
,sizeof(S
),"binary-%s",_config
->Find("Apt::Architecture").c_str());
393 // Strip the cdrom base path
394 Path
= string(Path
,CD
.length());
395 if (Path
.empty() == true)
398 // Too short to be a dists/ type
399 if (Path
.length() < strlen("dists/"))
403 if (stringcmp(Path
.c_str(),Path
.c_str()+strlen("dists/"),"dists/") != 0)
407 string::size_type Slash
= strlen("dists/");
408 string::size_type Slash2
= Path
.find('/',Slash
+ 1);
409 if (Slash2
== string::npos
|| Slash2
+ 2 >= Path
.length())
411 string Dist
= string(Path
,Slash
,Slash2
- Slash
);
413 // Isolate the component
415 for (unsigned I
= 0; I
!= 10; I
++)
417 Slash
= Path
.find('/',Slash
+1);
418 if (Slash
== string::npos
|| Slash
+ 2 >= Path
.length())
420 string Comp
= string(Path
,Slash2
+1,Slash
- Slash2
-1);
422 // Verify the trailing binary- bit
423 string::size_type BinSlash
= Path
.find('/',Slash
+ 1);
424 if (Slash
== string::npos
)
426 string Binary
= string(Path
,Slash
+1,BinSlash
- Slash
-1);
428 if (Binary
!= S
&& Binary
!= "source")
431 Path
= Dist
+ ' ' + Comp
;
436 // IndexCopy::GrabFirst - Return the first Depth path components /*{{{*/
437 // ---------------------------------------------------------------------
439 bool IndexCopy::GrabFirst(string Path
,string
&To
,unsigned int Depth
)
441 string::size_type I
= 0;
444 I
= Path
.find('/',I
+1);
447 while (I
!= string::npos
&& Depth
!= 0);
449 if (I
== string::npos
)
452 To
= string(Path
,0,I
+1);
456 // PackageCopy::GetFile - Get the file information from the section /*{{{*/
457 // ---------------------------------------------------------------------
459 bool PackageCopy::GetFile(string
&File
,unsigned long long &Size
)
461 File
= Section
->FindS("Filename");
462 Size
= Section
->FindI("Size");
463 if (File
.empty() || Size
== 0)
464 return _error
->Error("Cannot find filename or size tag");
468 // PackageCopy::RewriteEntry - Rewrite the entry with a new filename /*{{{*/
469 // ---------------------------------------------------------------------
471 bool PackageCopy::RewriteEntry(FILE *Target
,string File
)
473 TFRewriteData Changes
[] = {{"Filename",File
.c_str()},
476 if (TFRewrite(Target
,*Section
,TFRewritePackageOrder
,Changes
) == false)
482 // SourceCopy::GetFile - Get the file information from the section /*{{{*/
483 // ---------------------------------------------------------------------
485 bool SourceCopy::GetFile(string
&File
,unsigned long long &Size
)
487 string Files
= Section
->FindS("Files");
488 if (Files
.empty() == true)
491 // Stash the / terminated directory prefix
492 string Base
= Section
->FindS("Directory");
493 if (Base
.empty() == false && Base
[Base
.length()-1] != '/')
496 // Read the first file triplet
497 const char *C
= Files
.c_str();
501 // Parse each of the elements
502 if (ParseQuoteWord(C
,MD5Hash
) == false ||
503 ParseQuoteWord(C
,sSize
) == false ||
504 ParseQuoteWord(C
,File
) == false)
505 return _error
->Error("Error parsing file record");
507 // Parse the size and append the directory
508 Size
= strtoull(sSize
.c_str(), NULL
, 10);
513 // SourceCopy::RewriteEntry - Rewrite the entry with a new filename /*{{{*/
514 // ---------------------------------------------------------------------
516 bool SourceCopy::RewriteEntry(FILE *Target
,string File
)
518 string
Dir(File
,0,File
.rfind('/'));
519 TFRewriteData Changes
[] = {{"Directory",Dir
.c_str()},
522 if (TFRewrite(Target
,*Section
,TFRewriteSourceOrder
,Changes
) == false)
528 // SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/
529 // ---------------------------------------------------------------------
531 bool SigVerify::Verify(string prefix
, string file
, indexRecords
*MetaIndex
)
533 const indexRecords::checkSum
*Record
= MetaIndex
->Lookup(file
);
535 // we skip non-existing files in the verifcation to support a cdrom
536 // with no Packages file (just a Package.gz), see LP: #255545
537 // (non-existing files are not considered a error)
538 if(!RealFileExists(prefix
+file
))
540 _error
->Warning(_("Skipping nonexistent file %s"), string(prefix
+file
).c_str());
546 _error
->Warning(_("Can't find authentication record for: %s"), file
.c_str());
550 if (!Record
->Hash
.VerifyFile(prefix
+file
))
552 _error
->Warning(_("Hash mismatch for: %s"),file
.c_str());
556 if(_config
->FindB("Debug::aptcdrom",false))
558 cout
<< "File: " << prefix
+file
<< endl
;
559 cout
<< "Expected Hash " << Record
->Hash
.toStr() << endl
;
565 bool SigVerify::CopyMetaIndex(string CDROM
, string CDName
, /*{{{*/
566 string prefix
, string file
)
569 snprintf(S
,sizeof(S
),"cdrom:[%s]/%s%s",CDName
.c_str(),
570 (prefix
).c_str() + CDROM
.length(),file
.c_str());
571 string TargetF
= _config
->FindDir("Dir::State::lists");
572 TargetF
+= URItoFileName(S
);
576 Target
.Open(TargetF
,FileFd::WriteAtomic
);
577 Rel
.Open(prefix
+ file
,FileFd::ReadOnly
);
578 if (_error
->PendingError() == true)
580 if (CopyFile(Rel
,Target
) == false)
586 bool SigVerify::CopyAndVerify(string CDROM
,string Name
,vector
<string
> &SigList
, /*{{{*/
587 vector
<string
> PkgList
,vector
<string
> SrcList
)
589 if (SigList
.empty() == true)
592 bool Debug
= _config
->FindB("Debug::aptcdrom",false);
594 // Read all Release files
595 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
598 cout
<< "Signature verify for: " << *I
<< endl
;
600 indexRecords
*MetaIndex
= new indexRecords
;
603 string
const releasegpg
= *I
+"Release.gpg";
604 string
const release
= *I
+"Release";
606 // a Release.gpg without a Release should never happen
607 if(RealFileExists(release
) == false)
613 pid_t pid
= ExecFork();
615 _error
->Error("Fork failed");
619 RunGPGV(release
, releasegpg
);
621 if(!ExecWait(pid
, "gpgv")) {
622 _error
->Warning("Signature verification failed for: %s",
624 // something went wrong, don't copy the Release.gpg
625 // FIXME: delete any existing gpg file?
629 // Open the Release file and add it to the MetaIndex
630 if(!MetaIndex
->Load(release
))
632 _error
->Error("%s",MetaIndex
->ErrorText
.c_str());
636 // go over the Indexfiles and see if they verify
637 // if so, remove them from our copy of the lists
638 vector
<string
> keys
= MetaIndex
->MetaKeys();
639 for (vector
<string
>::iterator I
= keys
.begin(); I
!= keys
.end(); ++I
)
641 if(!Verify(prefix
,*I
, MetaIndex
)) {
642 // something went wrong, don't copy the Release.gpg
643 // FIXME: delete any existing gpg file?
649 // we need a fresh one for the Release.gpg
652 // everything was fine, copy the Release and Release.gpg file
653 CopyMetaIndex(CDROM
, Name
, prefix
, "Release");
654 CopyMetaIndex(CDROM
, Name
, prefix
, "Release.gpg");
660 // SigVerify::RunGPGV - returns the command needed for verify /*{{{*/
661 // ---------------------------------------------------------------------
662 /* Generating the commandline for calling gpgv is somehow complicated as
663 we need to add multiple keyrings and user supplied options. Also, as
664 the cdrom code currently can not use the gpgv method we have two places
665 these need to be done - so the place for this method is wrong but better
666 than code duplication… */
667 bool SigVerify::RunGPGV(std::string
const &File
, std::string
const &FileGPG
,
668 int const &statusfd
, int fd
[2])
672 #define SIGMSG "-----BEGIN PGP SIGNED MESSAGE-----\n"
673 char buffer
[sizeof(SIGMSG
)];
674 FILE* gpg
= fopen(File
.c_str(), "r");
676 return _error
->Errno("RunGPGV", _("Could not open file %s"), File
.c_str());
677 char const * const test
= fgets(buffer
, sizeof(buffer
), gpg
);
679 if (test
== NULL
|| strcmp(buffer
, SIGMSG
) != 0)
680 return _error
->Error(_("File %s doesn't start with a clearsigned message"), File
.c_str());
685 string
const gpgvpath
= _config
->Find("Dir::Bin::gpg", "/usr/bin/gpgv");
686 // FIXME: remove support for deprecated APT::GPGV setting
687 string
const trustedFile
= _config
->Find("APT::GPGV::TrustedKeyring", _config
->FindFile("Dir::Etc::Trusted"));
688 string
const trustedPath
= _config
->FindDir("Dir::Etc::TrustedParts");
690 bool const Debug
= _config
->FindB("Debug::Acquire::gpgv", false);
694 std::clog
<< "gpgv path: " << gpgvpath
<< std::endl
;
695 std::clog
<< "Keyring file: " << trustedFile
<< std::endl
;
696 std::clog
<< "Keyring path: " << trustedPath
<< std::endl
;
699 std::vector
<string
> keyrings
;
700 if (DirectoryExists(trustedPath
))
701 keyrings
= GetListOfFilesInDir(trustedPath
, "gpg", false, true);
702 if (RealFileExists(trustedFile
) == true)
703 keyrings
.push_back(trustedFile
);
705 std::vector
<const char *> Args
;
708 if (keyrings
.empty() == true)
710 // TRANSLATOR: %s is the trusted keyring parts directory
711 return _error
->Error(_("No keyring installed in %s."),
712 _config
->FindDir("Dir::Etc::TrustedParts").c_str());
715 Args
.push_back(gpgvpath
.c_str());
716 Args
.push_back("--ignore-time-conflict");
720 Args
.push_back("--status-fd");
722 snprintf(fd
, sizeof(fd
), "%i", statusfd
);
726 for (vector
<string
>::const_iterator K
= keyrings
.begin();
727 K
!= keyrings
.end(); ++K
)
729 Args
.push_back("--keyring");
730 Args
.push_back(K
->c_str());
733 Configuration::Item
const *Opts
;
734 Opts
= _config
->Tree("Acquire::gpgv::Options");
738 for (; Opts
!= 0; Opts
= Opts
->Next
)
740 if (Opts
->Value
.empty() == true)
742 Args
.push_back(Opts
->Value
.c_str());
746 Args
.push_back(FileGPG
.c_str());
748 Args
.push_back(File
.c_str());
749 Args
.push_back(NULL
);
753 std::clog
<< "Preparing to exec: " << gpgvpath
;
754 for (std::vector
<const char *>::const_iterator a
= Args
.begin(); *a
!= NULL
; ++a
)
755 std::clog
<< " " << *a
;
756 std::clog
<< std::endl
;
761 int const nullfd
= open("/dev/null", O_RDONLY
);
763 // Redirect output to /dev/null; we read from the status fd
764 dup2(nullfd
, STDOUT_FILENO
);
765 dup2(nullfd
, STDERR_FILENO
);
766 // Redirect the pipe to the status fd (3)
767 dup2(fd
[1], statusfd
);
769 putenv((char *)"LANG=");
770 putenv((char *)"LC_ALL=");
771 putenv((char *)"LC_MESSAGES=");
774 execvp(gpgvpath
.c_str(), (char **) &Args
[0]);
778 bool TranslationsCopy::CopyTranslations(string CDROM
,string Name
, /*{{{*/
779 vector
<string
> &List
, pkgCdromStatus
*log
)
781 OpProgress
*Progress
= NULL
;
782 if (List
.empty() == true)
786 Progress
= log
->GetOpProgress();
788 bool Debug
= _config
->FindB("Debug::aptcdrom",false);
790 // Prepare the progress indicator
792 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
795 if (stat(string(*I
).c_str(),&Buf
) != 0 &&
796 stat(string(*I
+ ".gz").c_str(),&Buf
) != 0)
797 return _error
->Errno("stat","Stat failed for %s",
799 TotalSize
+= Buf
.st_size
;
802 off_t CurrentSize
= 0;
803 unsigned int NotFound
= 0;
804 unsigned int WrongSize
= 0;
805 unsigned int Packages
= 0;
806 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
808 string OrigPath
= string(*I
,CDROM
.length());
811 // Open the package file
813 if (RealFileExists(*I
) == true)
815 Pkg
.Open(*I
,FileFd::ReadOnly
);
816 FileSize
= Pkg
.Size();
820 FileFd
From(*I
+ ".gz",FileFd::ReadOnly
);
821 if (_error
->PendingError() == true)
823 FileSize
= From
.Size();
826 FILE *tmp
= tmpfile();
828 return _error
->Errno("tmpfile","Unable to create a tmp file");
829 Pkg
.Fd(dup(fileno(tmp
)));
833 pid_t Process
= fork();
835 return _error
->Errno("fork","Couldn't fork gzip");
840 dup2(From
.Fd(),STDIN_FILENO
);
841 dup2(Pkg
.Fd(),STDOUT_FILENO
);
842 SetCloseExec(STDIN_FILENO
,false);
843 SetCloseExec(STDOUT_FILENO
,false);
846 string Tmp
= _config
->Find("Dir::bin::gzip","gzip");
847 Args
[0] = Tmp
.c_str();
850 execvp(Args
[0],(char **)Args
);
854 // Wait for gzip to finish
855 if (ExecWait(Process
,_config
->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
856 return _error
->Error("gzip failed, perhaps the disk is full.");
860 pkgTagFile
Parser(&Pkg
);
861 if (_error
->PendingError() == true)
864 // Open the output file
866 snprintf(S
,sizeof(S
),"cdrom:[%s]/%s",Name
.c_str(),
867 (*I
).c_str() + CDROM
.length());
868 string TargetF
= _config
->FindDir("Dir::State::lists") + "partial/";
869 TargetF
+= URItoFileName(S
);
870 if (_config
->FindB("APT::CDROM::NoAct",false) == true)
871 TargetF
= "/dev/null";
872 FileFd
Target(TargetF
,FileFd::WriteAtomic
);
873 FILE *TargetFl
= fdopen(dup(Target
.Fd()),"w");
874 if (_error
->PendingError() == true)
877 return _error
->Errno("fdopen","Failed to reopen fd");
879 // Setup the progress meter
881 Progress
->OverallProgress(CurrentSize
,TotalSize
,FileSize
,
882 string("Reading Translation Indexes"));
886 Progress
->SubProgress(Pkg
.Size());
887 pkgTagSection Section
;
888 this->Section
= &Section
;
890 unsigned long Hits
= 0;
891 while (Parser
.Step(Section
) == true)
894 Progress
->Progress(Parser
.Offset());
898 Section
.GetSection(Start
,Stop
);
899 fwrite(Start
,Stop
-Start
, 1, TargetFl
);
900 fputc('\n',TargetFl
);
908 cout
<< " Processed by using Prefix '" << Prefix
<< "' and chop " << endl
;
910 if (_config
->FindB("APT::CDROM::NoAct",false) == false)
912 // Move out of the partial directory
914 string FinalF
= _config
->FindDir("Dir::State::lists");
915 FinalF
+= URItoFileName(S
);
916 if (rename(TargetF
.c_str(),FinalF
.c_str()) != 0)
917 return _error
->Errno("rename","Failed to rename");
921 CurrentSize
+= FileSize
;
929 if(NotFound
== 0 && WrongSize
== 0)
930 ioprintf(msg
, _("Wrote %i records.\n"), Packages
);
931 else if (NotFound
!= 0 && WrongSize
== 0)
932 ioprintf(msg
, _("Wrote %i records with %i missing files.\n"),
934 else if (NotFound
== 0 && WrongSize
!= 0)
935 ioprintf(msg
, _("Wrote %i records with %i mismatched files\n"),
936 Packages
, WrongSize
);
937 if (NotFound
!= 0 && WrongSize
!= 0)
938 ioprintf(msg
, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages
, NotFound
, WrongSize
);
942 _error
->Warning("No valid records were found.");
944 if (NotFound
+ WrongSize
> 10)
945 _error
->Warning("A lot of entries were discarded, something may be wrong.\n");