]>
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 /*{{{*/
13 #include "indexcopy.h"
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>
30 #include <sys/types.h>
39 // IndexCopy::CopyPackages - Copy the package files from the CD /*{{{*/
40 // ---------------------------------------------------------------------
42 bool IndexCopy::CopyPackages(string CDROM
,string Name
,vector
<string
> &List
,
45 OpProgress
*Progress
= NULL
;
50 Progress
= log
->GetOpProgress();
52 bool NoStat
= _config
->FindB("APT::CDROM::Fast",false);
53 bool Debug
= _config
->FindB("Debug::aptcdrom",false);
55 // Prepare the progress indicator
56 unsigned long TotalSize
= 0;
57 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
60 if (stat(string(*I
+ GetFileName()).c_str(),&Buf
) != 0 &&
61 stat(string(*I
+ GetFileName() + ".gz").c_str(),&Buf
) != 0)
62 return _error
->Errno("stat","Stat failed for %s",
63 string(*I
+ GetFileName()).c_str());
64 TotalSize
+= Buf
.st_size
;
67 unsigned long CurrentSize
= 0;
68 unsigned int NotFound
= 0;
69 unsigned int WrongSize
= 0;
70 unsigned int Packages
= 0;
71 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
73 string OrigPath
= string(*I
,CDROM
.length());
74 unsigned long FileSize
= 0;
76 // Open the package file
78 if (FileExists(*I
+ GetFileName()) == true)
80 Pkg
.Open(*I
+ GetFileName(),FileFd::ReadOnly
);
81 FileSize
= Pkg
.Size();
85 FileFd
From(*I
+ GetFileName() + ".gz",FileFd::ReadOnly
);
86 if (_error
->PendingError() == true)
88 FileSize
= From
.Size();
91 FILE *tmp
= tmpfile();
93 return _error
->Errno("tmpfile","Unable to create a tmp file");
94 Pkg
.Fd(dup(fileno(tmp
)));
98 pid_t Process
= fork();
100 return _error
->Errno("fork","Couldn't fork gzip");
105 dup2(From
.Fd(),STDIN_FILENO
);
106 dup2(Pkg
.Fd(),STDOUT_FILENO
);
107 SetCloseExec(STDIN_FILENO
,false);
108 SetCloseExec(STDOUT_FILENO
,false);
111 string Tmp
= _config
->Find("Dir::bin::gzip","gzip");
112 Args
[0] = Tmp
.c_str();
115 execvp(Args
[0],(char **)Args
);
119 // Wait for gzip to finish
120 if (ExecWait(Process
,_config
->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
121 return _error
->Error("gzip failed, perhaps the disk is full.");
125 pkgTagFile
Parser(&Pkg
);
126 if (_error
->PendingError() == true)
129 // Open the output file
131 snprintf(S
,sizeof(S
),"cdrom:[%s]/%s%s",Name
.c_str(),
132 (*I
).c_str() + CDROM
.length(),GetFileName());
133 string TargetF
= _config
->FindDir("Dir::State::lists") + "partial/";
134 TargetF
+= URItoFileName(S
);
135 if (_config
->FindB("APT::CDROM::NoAct",false) == true)
136 TargetF
= "/dev/null";
137 FileFd
Target(TargetF
,FileFd::WriteEmpty
);
138 FILE *TargetFl
= fdopen(dup(Target
.Fd()),"w");
139 if (_error
->PendingError() == true)
142 return _error
->Errno("fdopen","Failed to reopen fd");
144 // Setup the progress meter
146 Progress
->OverallProgress(CurrentSize
,TotalSize
,FileSize
,
147 string("Reading ") + Type() + " Indexes");
151 Progress
->SubProgress(Pkg
.Size());
152 pkgTagSection Section
;
153 this->Section
= &Section
;
155 unsigned long Hits
= 0;
156 unsigned long Chop
= 0;
157 while (Parser
.Step(Section
) == true)
160 Progress
->Progress(Parser
.Offset());
163 if (GetFile(File
,Size
) == false)
170 File
= OrigPath
+ ChopDirs(File
,Chop
);
172 // See if the file exists
173 bool Mangled
= false;
174 if (NoStat
== false || Hits
< 10)
176 // Attempt to fix broken structure
179 if (ReconstructPrefix(Prefix
,OrigPath
,CDROM
,File
) == false &&
180 ReconstructChop(Chop
,*I
,File
) == false)
183 clog
<< "Missed: " << File
<< endl
;
188 File
= OrigPath
+ ChopDirs(File
,Chop
);
193 if (stat(string(CDROM
+ Prefix
+ File
).c_str(),&Buf
) != 0 ||
196 // Attempt to fix busted symlink support for one instance
197 string OrigFile
= File
;
198 string::size_type Start
= File
.find("binary-");
199 string::size_type End
= File
.find("/",Start
+3);
200 if (Start
!= string::npos
&& End
!= string::npos
)
202 File
.replace(Start
,End
-Start
,"binary-all");
206 if (Mangled
== false ||
207 stat(string(CDROM
+ Prefix
+ File
).c_str(),&Buf
) != 0)
210 clog
<< "Missed(2): " << OrigFile
<< endl
;
217 if ((unsigned)Buf
.st_size
!= Size
)
220 clog
<< "Wrong Size: " << File
<< endl
;
229 if (RewriteEntry(TargetFl
,File
) == false)
238 cout
<< " Processed by using Prefix '" << Prefix
<< "' and chop " << Chop
<< endl
;
240 if (_config
->FindB("APT::CDROM::NoAct",false) == false)
242 // Move out of the partial directory
244 string FinalF
= _config
->FindDir("Dir::State::lists");
245 FinalF
+= URItoFileName(S
);
246 if (rename(TargetF
.c_str(),FinalF
.c_str()) != 0)
247 return _error
->Errno("rename","Failed to rename");
250 /* Mangle the source to be in the proper notation with
251 prefix dist [component] */
252 *I
= string(*I
,Prefix
.length());
253 ConvertToSourceList(CDROM
,*I
);
254 *I
= Prefix
+ ' ' + *I
;
256 CurrentSize
+= FileSize
;
264 if(NotFound
== 0 && WrongSize
== 0)
265 ioprintf(msg
, _("Wrote %i records.\n"), Packages
);
266 else if (NotFound
!= 0 && WrongSize
== 0)
267 ioprintf(msg
, _("Wrote %i records with %i missing files.\n"),
269 else if (NotFound
== 0 && WrongSize
!= 0)
270 ioprintf(msg
, _("Wrote %i records with %i mismatched files\n"),
271 Packages
, WrongSize
);
272 if (NotFound
!= 0 && WrongSize
!= 0)
273 ioprintf(msg
, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages
, NotFound
, WrongSize
);
277 _error
->Warning("No valid records were found.");
279 if (NotFound
+ WrongSize
> 10)
280 _error
->Warning("A lot of entries were discarded, something may be wrong.\n");
286 // IndexCopy::ChopDirs - Chop off the leading directory components /*{{{*/
287 // ---------------------------------------------------------------------
289 string
IndexCopy::ChopDirs(string Path
,unsigned int Depth
)
291 string::size_type I
= 0;
294 I
= Path
.find('/',I
+1);
297 while (I
!= string::npos
&& Depth
!= 0);
299 if (I
== string::npos
)
302 return string(Path
,I
+1);
305 // IndexCopy::ReconstructPrefix - Fix strange prefixing /*{{{*/
306 // ---------------------------------------------------------------------
307 /* This prepends dir components from the path to the package files to
308 the path to the deb until it is found */
309 bool IndexCopy::ReconstructPrefix(string
&Prefix
,string OrigPath
,string CD
,
312 bool Debug
= _config
->FindB("Debug::aptcdrom",false);
313 unsigned int Depth
= 1;
314 string MyPrefix
= Prefix
;
318 if (stat(string(CD
+ MyPrefix
+ File
).c_str(),&Buf
) != 0)
321 cout
<< "Failed, " << CD
+ MyPrefix
+ File
<< endl
;
322 if (GrabFirst(OrigPath
,MyPrefix
,Depth
++) == true)
336 // IndexCopy::ReconstructChop - Fixes bad source paths /*{{{*/
337 // ---------------------------------------------------------------------
338 /* This removes path components from the filename and prepends the location
339 of the package files until a file is found */
340 bool IndexCopy::ReconstructChop(unsigned long &Chop
,string Dir
,string File
)
342 // Attempt to reconstruct the filename
343 unsigned long Depth
= 0;
347 if (stat(string(Dir
+ File
).c_str(),&Buf
) != 0)
349 File
= ChopDirs(File
,1);
351 if (File
.empty() == false)
364 // IndexCopy::ConvertToSourceList - Convert a Path to a sourcelist /*{{{*/
365 // ---------------------------------------------------------------------
366 /* We look for things in dists/ notation and convert them to
367 <dist> <component> form otherwise it is left alone. This also strips
370 This implements a regex sort of like:
371 (.*)/dists/([^/]*)/(.*)/binary-*
373 | |-------- Distribution
374 |------------------- Path
376 It was deciced to use only a single word for dist (rather than say
377 unstable/non-us) to increase the chance that each CD gets a single
378 line in sources.list.
380 void IndexCopy::ConvertToSourceList(string CD
,string
&Path
)
383 snprintf(S
,sizeof(S
),"binary-%s",_config
->Find("Apt::Architecture").c_str());
385 // Strip the cdrom base path
386 Path
= string(Path
,CD
.length());
387 if (Path
.empty() == true)
390 // Too short to be a dists/ type
391 if (Path
.length() < strlen("dists/"))
395 if (stringcmp(Path
.c_str(),Path
.c_str()+strlen("dists/"),"dists/") != 0)
399 string::size_type Slash
= strlen("dists/");
400 string::size_type Slash2
= Path
.find('/',Slash
+ 1);
401 if (Slash2
== string::npos
|| Slash2
+ 2 >= Path
.length())
403 string Dist
= string(Path
,Slash
,Slash2
- Slash
);
405 // Isolate the component
407 for (unsigned I
= 0; I
!= 10; I
++)
409 Slash
= Path
.find('/',Slash
+1);
410 if (Slash
== string::npos
|| Slash
+ 2 >= Path
.length())
412 string Comp
= string(Path
,Slash2
+1,Slash
- Slash2
-1);
414 // Verify the trailing binary- bit
415 string::size_type BinSlash
= Path
.find('/',Slash
+ 1);
416 if (Slash
== string::npos
)
418 string Binary
= string(Path
,Slash
+1,BinSlash
- Slash
-1);
420 if (Binary
!= S
&& Binary
!= "source")
423 Path
= Dist
+ ' ' + Comp
;
428 // IndexCopy::GrabFirst - Return the first Depth path components /*{{{*/
429 // ---------------------------------------------------------------------
431 bool IndexCopy::GrabFirst(string Path
,string
&To
,unsigned int Depth
)
433 string::size_type I
= 0;
436 I
= Path
.find('/',I
+1);
439 while (I
!= string::npos
&& Depth
!= 0);
441 if (I
== string::npos
)
444 To
= string(Path
,0,I
+1);
448 // PackageCopy::GetFile - Get the file information from the section /*{{{*/
449 // ---------------------------------------------------------------------
451 bool PackageCopy::GetFile(string
&File
,unsigned long &Size
)
453 File
= Section
->FindS("Filename");
454 Size
= Section
->FindI("Size");
455 if (File
.empty() || Size
== 0)
456 return _error
->Error("Cannot find filename or size tag");
460 // PackageCopy::RewriteEntry - Rewrite the entry with a new filename /*{{{*/
461 // ---------------------------------------------------------------------
463 bool PackageCopy::RewriteEntry(FILE *Target
,string File
)
465 TFRewriteData Changes
[] = {{"Filename",File
.c_str()},
468 if (TFRewrite(Target
,*Section
,TFRewritePackageOrder
,Changes
) == false)
474 // SourceCopy::GetFile - Get the file information from the section /*{{{*/
475 // ---------------------------------------------------------------------
477 bool SourceCopy::GetFile(string
&File
,unsigned long &Size
)
479 string Files
= Section
->FindS("Files");
480 if (Files
.empty() == true)
483 // Stash the / terminated directory prefix
484 string Base
= Section
->FindS("Directory");
485 if (Base
.empty() == false && Base
[Base
.length()-1] != '/')
488 // Read the first file triplet
489 const char *C
= Files
.c_str();
493 // Parse each of the elements
494 if (ParseQuoteWord(C
,MD5Hash
) == false ||
495 ParseQuoteWord(C
,sSize
) == false ||
496 ParseQuoteWord(C
,File
) == false)
497 return _error
->Error("Error parsing file record");
499 // Parse the size and append the directory
500 Size
= atoi(sSize
.c_str());
505 // SourceCopy::RewriteEntry - Rewrite the entry with a new filename /*{{{*/
506 // ---------------------------------------------------------------------
508 bool SourceCopy::RewriteEntry(FILE *Target
,string File
)
510 string
Dir(File
,0,File
.rfind('/'));
511 TFRewriteData Changes
[] = {{"Directory",Dir
.c_str()},
514 if (TFRewrite(Target
,*Section
,TFRewriteSourceOrder
,Changes
) == false)
520 // SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/
521 // ---------------------------------------------------------------------
523 bool SigVerify::Verify(string prefix
, string file
, indexRecords
*MetaIndex
)
525 const indexRecords::checkSum
*Record
= MetaIndex
->Lookup(file
);
527 // we skip non-existing files in the verifcation to support a cdrom
528 // with no Packages file (just a Package.gz), see LP: #255545
529 // (non-existing files are not considered a error)
530 if(!FileExists(prefix
+file
))
532 _error
->Warning(_("Skipping nonexistent file %s"), string(prefix
+file
).c_str());
538 _error
->Warning(_("Can't find authentication record for: %s"), file
.c_str());
542 if (!Record
->Hash
.VerifyFile(prefix
+file
))
544 _error
->Warning(_("Hash mismatch for: %s"),file
.c_str());
548 if(_config
->FindB("Debug::aptcdrom",false))
550 cout
<< "File: " << prefix
+file
<< endl
;
551 cout
<< "Expected Hash " << Record
->Hash
.toStr() << endl
;
557 bool SigVerify::CopyMetaIndex(string CDROM
, string CDName
, /*{{{*/
558 string prefix
, string file
)
561 snprintf(S
,sizeof(S
),"cdrom:[%s]/%s%s",CDName
.c_str(),
562 (prefix
).c_str() + CDROM
.length(),file
.c_str());
563 string TargetF
= _config
->FindDir("Dir::State::lists");
564 TargetF
+= URItoFileName(S
);
568 Target
.Open(TargetF
,FileFd::WriteEmpty
);
569 Rel
.Open(prefix
+ file
,FileFd::ReadOnly
);
570 if (_error
->PendingError() == true)
572 if (CopyFile(Rel
,Target
) == false)
578 bool SigVerify::CopyAndVerify(string CDROM
,string Name
,vector
<string
> &SigList
, /*{{{*/
579 vector
<string
> PkgList
,vector
<string
> SrcList
)
581 if (SigList
.size() == 0)
584 bool Debug
= _config
->FindB("Debug::aptcdrom",false);
586 // Read all Release files
587 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); I
++)
590 cout
<< "Signature verify for: " << *I
<< endl
;
592 indexRecords
*MetaIndex
= new indexRecords
;
595 string
const releasegpg
= *I
+"Release.gpg";
596 string
const release
= *I
+"Release";
598 // a Release.gpg without a Release should never happen
599 if(FileExists(release
) == false)
605 pid_t pid
= ExecFork();
607 _error
->Error("Fork failed");
611 RunGPGV(release
, releasegpg
);
613 if(!ExecWait(pid
, "gpgv")) {
614 _error
->Warning("Signature verification failed for: %s",
616 // something went wrong, don't copy the Release.gpg
617 // FIXME: delete any existing gpg file?
621 // Open the Release file and add it to the MetaIndex
622 if(!MetaIndex
->Load(release
))
624 _error
->Error("%s",MetaIndex
->ErrorText
.c_str());
628 // go over the Indexfiles and see if they verify
629 // if so, remove them from our copy of the lists
630 vector
<string
> keys
= MetaIndex
->MetaKeys();
631 for (vector
<string
>::iterator I
= keys
.begin(); I
!= keys
.end(); I
++)
633 if(!Verify(prefix
,*I
, MetaIndex
)) {
634 // something went wrong, don't copy the Release.gpg
635 // FIXME: delete any existing gpg file?
641 // we need a fresh one for the Release.gpg
644 // everything was fine, copy the Release and Release.gpg file
645 CopyMetaIndex(CDROM
, Name
, prefix
, "Release");
646 CopyMetaIndex(CDROM
, Name
, prefix
, "Release.gpg");
652 // SigVerify::RunGPGV - returns the command needed for verify /*{{{*/
653 // ---------------------------------------------------------------------
654 /* Generating the commandline for calling gpgv is somehow complicated as
655 we need to add multiple keyrings and user supplied options. Also, as
656 the cdrom code currently can not use the gpgv method we have two places
657 these need to be done - so the place for this method is wrong but better
658 than code duplication… */
659 bool SigVerify::RunGPGV(std::string
const &File
, std::string
const &FileGPG
,
660 int const &statusfd
, int fd
[2])
662 string
const gpgvpath
= _config
->Find("Dir::Bin::gpg", "/usr/bin/gpgv");
663 // FIXME: remove support for deprecated APT::GPGV setting
664 string
const trustedFile
= _config
->FindFile("Dir::Etc::Trusted",
665 _config
->Find("APT::GPGV::TrustedKeyring", "/etc/apt/trusted.gpg").c_str());
666 string
const trustedPath
= _config
->FindDir("Dir::Etc::TrustedParts", "/etc/apt/trusted.gpg.d");
668 bool const Debug
= _config
->FindB("Debug::Acquire::gpgv", false);
672 std::clog
<< "gpgv path: " << gpgvpath
<< std::endl
;
673 std::clog
<< "Keyring file: " << trustedFile
<< std::endl
;
674 std::clog
<< "Keyring path: " << trustedPath
<< std::endl
;
677 std::vector
<string
> keyrings
= GetListOfFilesInDir(trustedPath
, "gpg", false);
678 if (FileExists(trustedFile
) == true)
679 keyrings
.push_back(trustedFile
);
681 std::vector
<const char *> Args
;
684 if (keyrings
.empty() == true)
687 Args
.push_back(gpgvpath
.c_str());
688 Args
.push_back("--ignore-time-conflict");
692 Args
.push_back("--status-fd");
694 snprintf(fd
, sizeof(fd
), "%i", statusfd
);
698 for (vector
<string
>::const_iterator K
= keyrings
.begin();
699 K
!= keyrings
.end(); ++K
)
701 Args
.push_back("--keyring");
702 Args
.push_back(K
->c_str());
705 Configuration::Item
const *Opts
;
706 Opts
= _config
->Tree("Acquire::gpgv::Options");
710 for (; Opts
!= 0; Opts
= Opts
->Next
)
712 if (Opts
->Value
.empty() == true)
714 Args
.push_back(Opts
->Value
.c_str());
718 Args
.push_back(FileGPG
.c_str());
719 Args
.push_back(File
.c_str());
720 Args
.push_back(NULL
);
724 std::clog
<< "Preparing to exec: " << gpgvpath
;
725 for (std::vector
<const char *>::const_iterator a
= Args
.begin(); *a
!= NULL
; ++a
)
726 std::clog
<< " " << *a
;
727 std::clog
<< std::endl
;
732 int const nullfd
= open("/dev/null", O_RDONLY
);
734 // Redirect output to /dev/null; we read from the status fd
735 dup2(nullfd
, STDOUT_FILENO
);
736 dup2(nullfd
, STDERR_FILENO
);
737 // Redirect the pipe to the status fd (3)
738 dup2(fd
[1], statusfd
);
740 putenv((char *)"LANG=");
741 putenv((char *)"LC_ALL=");
742 putenv((char *)"LC_MESSAGES=");
745 execvp(gpgvpath
.c_str(), (char **) &Args
[0]);
749 bool TranslationsCopy::CopyTranslations(string CDROM
,string Name
, /*{{{*/
750 vector
<string
> &List
, pkgCdromStatus
*log
)
752 OpProgress
*Progress
= NULL
;
753 if (List
.size() == 0)
757 Progress
= log
->GetOpProgress();
759 bool Debug
= _config
->FindB("Debug::aptcdrom",false);
761 // Prepare the progress indicator
762 unsigned long TotalSize
= 0;
763 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
766 if (stat(string(*I
).c_str(),&Buf
) != 0 &&
767 stat(string(*I
+ ".gz").c_str(),&Buf
) != 0)
768 return _error
->Errno("stat","Stat failed for %s",
770 TotalSize
+= Buf
.st_size
;
773 unsigned long CurrentSize
= 0;
774 unsigned int NotFound
= 0;
775 unsigned int WrongSize
= 0;
776 unsigned int Packages
= 0;
777 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
779 string OrigPath
= string(*I
,CDROM
.length());
780 unsigned long FileSize
= 0;
782 // Open the package file
784 if (FileExists(*I
) == true)
786 Pkg
.Open(*I
,FileFd::ReadOnly
);
787 FileSize
= Pkg
.Size();
791 FileFd
From(*I
+ ".gz",FileFd::ReadOnly
);
792 if (_error
->PendingError() == true)
794 FileSize
= From
.Size();
797 FILE *tmp
= tmpfile();
799 return _error
->Errno("tmpfile","Unable to create a tmp file");
800 Pkg
.Fd(dup(fileno(tmp
)));
804 pid_t Process
= fork();
806 return _error
->Errno("fork","Couldn't fork gzip");
811 dup2(From
.Fd(),STDIN_FILENO
);
812 dup2(Pkg
.Fd(),STDOUT_FILENO
);
813 SetCloseExec(STDIN_FILENO
,false);
814 SetCloseExec(STDOUT_FILENO
,false);
817 string Tmp
= _config
->Find("Dir::bin::gzip","gzip");
818 Args
[0] = Tmp
.c_str();
821 execvp(Args
[0],(char **)Args
);
825 // Wait for gzip to finish
826 if (ExecWait(Process
,_config
->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
827 return _error
->Error("gzip failed, perhaps the disk is full.");
831 pkgTagFile
Parser(&Pkg
);
832 if (_error
->PendingError() == true)
835 // Open the output file
837 snprintf(S
,sizeof(S
),"cdrom:[%s]/%s",Name
.c_str(),
838 (*I
).c_str() + CDROM
.length());
839 string TargetF
= _config
->FindDir("Dir::State::lists") + "partial/";
840 TargetF
+= URItoFileName(S
);
841 if (_config
->FindB("APT::CDROM::NoAct",false) == true)
842 TargetF
= "/dev/null";
843 FileFd
Target(TargetF
,FileFd::WriteEmpty
);
844 FILE *TargetFl
= fdopen(dup(Target
.Fd()),"w");
845 if (_error
->PendingError() == true)
848 return _error
->Errno("fdopen","Failed to reopen fd");
850 // Setup the progress meter
852 Progress
->OverallProgress(CurrentSize
,TotalSize
,FileSize
,
853 string("Reading Translation Indexes"));
857 Progress
->SubProgress(Pkg
.Size());
858 pkgTagSection Section
;
859 this->Section
= &Section
;
861 unsigned long Hits
= 0;
862 unsigned long Chop
= 0;
863 while (Parser
.Step(Section
) == true)
866 Progress
->Progress(Parser
.Offset());
870 Section
.GetSection(Start
,Stop
);
871 fwrite(Start
,Stop
-Start
, 1, TargetFl
);
872 fputc('\n',TargetFl
);
880 cout
<< " Processed by using Prefix '" << Prefix
<< "' and chop " << Chop
<< endl
;
882 if (_config
->FindB("APT::CDROM::NoAct",false) == false)
884 // Move out of the partial directory
886 string FinalF
= _config
->FindDir("Dir::State::lists");
887 FinalF
+= URItoFileName(S
);
888 if (rename(TargetF
.c_str(),FinalF
.c_str()) != 0)
889 return _error
->Errno("rename","Failed to rename");
893 CurrentSize
+= FileSize
;
901 if(NotFound
== 0 && WrongSize
== 0)
902 ioprintf(msg
, _("Wrote %i records.\n"), Packages
);
903 else if (NotFound
!= 0 && WrongSize
== 0)
904 ioprintf(msg
, _("Wrote %i records with %i missing files.\n"),
906 else if (NotFound
== 0 && WrongSize
!= 0)
907 ioprintf(msg
, _("Wrote %i records with %i mismatched files\n"),
908 Packages
, WrongSize
);
909 if (NotFound
!= 0 && WrongSize
!= 0)
910 ioprintf(msg
, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages
, NotFound
, WrongSize
);
914 _error
->Warning("No valid records were found.");
916 if (NotFound
+ WrongSize
> 10)
917 _error
->Warning("A lot of entries were discarded, something may be wrong.\n");