+ // Setup the progress meter
+ Progress.OverallProgress(CurrentSize,TotalSize,Pkg.Size(),
+ "Reading Package Lists");
+
+ // Parse
+ Progress.SubProgress(Pkg.Size());
+ pkgTagSection Section;
+ string Prefix;
+ unsigned long Hits = 0;
+ unsigned long Chop = 0;
+ while (Parser.Step(Section) == true)
+ {
+ Progress.Progress(Parser.Offset());
+
+ string File = Section.FindS("Filename");
+ unsigned long Size = Section.FindI("Size");
+ if (File.empty() || Size == 0)
+ return _error->Error("Cannot find filename or size tag");
+
+ if (Chop != 0)
+ File = OrigPath + ChopDirs(File,Chop);
+
+ // See if the file exists
+ bool Mangled = false;
+ if (NoStat == false || Hits < 10)
+ {
+ // Attempt to fix broken structure
+ if (Hits == 0)
+ {
+ if (ReconstructPrefix(Prefix,OrigPath,CDROM,File) == false &&
+ ReconstructChop(Chop,*I,File) == false)
+ {
+ if (Debug == true)
+ clog << "Missed: " << File << endl;
+ NotFound++;
+ continue;
+ }
+ if (Chop != 0)
+ File = OrigPath + ChopDirs(File,Chop);
+ }
+
+ // Get the size
+ struct stat Buf;
+ if (stat(string(CDROM + Prefix + File).c_str(),&Buf) != 0)
+ {
+ // Attempt to fix busted symlink support for one instance
+ string OrigFile = File;
+ string::size_type Start = File.find("binary-");
+ string::size_type End = File.find("/",Start+3);
+ if (Start != string::npos && End != string::npos)
+ {
+ File.replace(Start,End-Start,"binary-all");
+ Mangled = true;
+ }
+
+ if (Mangled == false ||
+ stat(string(CDROM + Prefix + File).c_str(),&Buf) != 0)
+ {
+ if (Debug == true)
+ clog << "Missed(2): " << OrigFile << endl;
+ NotFound++;
+ continue;
+ }
+ }
+
+ // Size match
+ if ((unsigned)Buf.st_size != Size)
+ {
+ if (Debug == true)
+ clog << "Wrong Size: " << File << endl;
+ WrongSize++;
+ continue;
+ }
+ }
+
+ Packages++;
+ Hits++;
+
+ // Copy it to the target package file
+ const char *Start;
+ const char *Stop;
+ if (Chop != 0 || Mangled == true)
+ {
+ // Mangle the output filename
+ const char *Filename;
+ Section.Find("Filename",Filename,Stop);
+
+ /* We need to rewrite the filename field so we emit
+ all fields except the filename file and rewrite that one */
+ for (unsigned int I = 0; I != Section.Count(); I++)
+ {
+ Section.Get(Start,Stop,I);
+ if (Start <= Filename && Stop > Filename)
+ {
+ char S[500];
+ sprintf(S,"Filename: %s\n",File.c_str());
+ if (I + 1 == Section.Count())
+ strcat(S,"\n");
+ if (Target.Write(S,strlen(S)) == false)
+ return false;
+ }
+ else
+ {
+ if (Target.Write(Start,Stop-Start) == false)
+ return false;
+ if (Stop[-1] != '\n')
+ if (Target.Write("\n",1) == false)
+ return false;
+ }
+ }
+ if (Target.Write("\n",1) == false)
+ return false;
+ }
+ else
+ {
+ Section.GetSection(Start,Stop);
+ if (Target.Write(Start,Stop-Start) == false)
+ return false;
+ }
+ }
+
+ if (Debug == true)
+ cout << " Processed by using Prefix '" << Prefix << "' and chop " << Chop << endl;
+
+ if (_config->FindB("APT::CDROM::NoAct",false) == false)
+ {
+ // Move out of the partial directory
+ Target.Close();
+ string FinalF = _config->FindDir("Dir::State::lists");
+ FinalF += URItoFileName(S);
+ if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
+ return _error->Errno("rename","Failed to rename");
+
+ // Copy the release file
+ sprintf(S,"cdrom:%s/%sRelease",Name.c_str(),(*I).c_str() + CDROM.length());
+ string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
+ TargetF += URItoFileName(S);
+ if (FileExists(*I + "Release") == true)
+ {
+ FileFd Target(TargetF,FileFd::WriteEmpty);
+ FileFd Rel(*I + "Release",FileFd::ReadOnly);
+ if (_error->PendingError() == true)
+ return false;
+
+ if (CopyFile(Rel,Target) == false)
+ return false;
+ }
+ else
+ {
+ // Empty release file
+ FileFd Target(TargetF,FileFd::WriteEmpty);
+ }
+
+ // Rename the release file
+ FinalF = _config->FindDir("Dir::State::lists");
+ FinalF += URItoFileName(S);
+ if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
+ return _error->Errno("rename","Failed to rename");
+ }
+
+ /* Mangle the source to be in the proper notation with
+ prefix dist [component] */
+ *I = string(*I,Prefix.length());
+ ConvertToSourceList(CDROM,*I);
+ *I = Prefix + ' ' + *I;
+
+ CurrentSize += Pkg.Size();
+ }
+ Progress.Done();
+
+ // Some stats
+ cout << "Wrote " << Packages << " package records" ;
+ if (NotFound != 0)
+ cout << " with " << NotFound << " missing files";
+ if (NotFound != 0 && WrongSize != 0)
+ cout << " and";
+ if (WrongSize != 0)
+ cout << " with " << WrongSize << " mismatched files";
+ cout << '.' << endl;
+
+ if (Packages == 0)
+ return _error->Error("No valid package records were found.");
+
+ if (NotFound + WrongSize > 10)
+ cout << "Alot of package entries were discarded, perhaps this CD is funny?" << endl;
+
+ return true;
+}
+ /*}}}*/
+
+// ReduceSourceList - Takes the path list and reduces it /*{{{*/
+// ---------------------------------------------------------------------
+/* This takes the list of source list expressed entires and collects
+ similar ones to form a single entry for each dist */
+bool ReduceSourcelist(string CD,vector<string> &List)
+{
+ sort(List.begin(),List.end());