+ // 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;
+ 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");
+
+ // See if the file exists
+ if (NoStat == false || Hits < 10)
+ {
+ struct stat Buf;
+ unsigned int Depth = 1;
+ string MyPrefix = Prefix;
+ while (1)
+ {
+ if (stat(string(CDROM + MyPrefix + File).c_str(),&Buf) != 0)
+ {
+ if (Prefix.empty() == true)
+ {
+ if (GrabFirst(OrigPath,MyPrefix,Depth++) == true)
+ continue;
+ }
+
+ NotFound++;
+ Depth = 0;
+ break;
+ }
+ else
+ break;
+ }
+
+ // Failed
+ if (Depth == 0)
+ continue;
+
+ // Store the new prefix
+ if (Depth != 1)
+ Prefix = MyPrefix;
+
+ // Size match
+ if ((unsigned)Buf.st_size != Size)
+ {
+ WrongSize++;
+ continue;
+ }
+ }
+
+ Packages++;
+ Hits++;
+
+ // Copy it to the target package file
+ const char *Start;
+ const char *Stop;
+ Section.GetSection(Start,Stop);
+ if (Target.Write(Start,Stop-Start) == false)
+ return false;
+ }
+
+ 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 entires were discarded, perhaps this CD is funny?" << endl;
+}
+ /*}}}*/
+
+// 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());