]> git.saurik.com Git - apt.git/commitdiff
Move CD-ROM handling backend into libapt-pkg
authorMatt Zimmerman <matt.zimmerman@canonical.com>
Fri, 4 Feb 2005 23:31:55 +0000 (23:31 +0000)
committerMatt Zimmerman <matt.zimmerman@canonical.com>
Fri, 4 Feb 2005 23:31:55 +0000 (23:31 +0000)
    - apt-cdrom.cc seperated into frontend (cmdline/apt-cdrom.cc and library
      apt-pkg/cdrom.{cc,h}) (Ubuntu #5668)

Patches applied:

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--base-0
   tag of apt@packages.debian.org/apt--main--0--patch-51

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--patch-1
   * added support for signed cdroms

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--patch-2
   * merged with apt--main, seperated cmdline/apt-cdrom.cc into a library (apt-pkg/cdrom.{cc,h})

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--patch-3
   * cleaned up the cmdline/apt-cdrom.cc code

13 files changed:
apt-pkg/cdrom.cc [new file with mode: 0644]
apt-pkg/cdrom.h [new file with mode: 0644]
apt-pkg/indexcopy.cc [new file with mode: 0644]
apt-pkg/indexcopy.h [new file with mode: 0644]
apt-pkg/indexrecords.cc
apt-pkg/indexrecords.h
apt-pkg/makefile
cmdline/apt-cdrom.cc
cmdline/indexcopy.cc [deleted file]
cmdline/indexcopy.h [deleted file]
cmdline/makefile
debian/changelog
po/apt-all.pot

diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc
new file mode 100644 (file)
index 0000000..a91fc71
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ */
+
+#ifdef __GNUG__
+#pragma implementation "apt-pkg/cdrom.h"
+#endif
+#include<apt-pkg/init.h>
+#include<apt-pkg/error.h>
+#include<apt-pkg/cdromutl.h>
+#include<apt-pkg/strutl.h>
+#include<apt-pkg/cdrom.h>
+#include<sstream>
+#include<fstream>
+#include<config.h>
+#include<apti18n.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+
+
+#include "indexcopy.h"
+
+using namespace std;
+
+// FindPackages - Find the package files on the CDROM                  /*{{{*/
+// ---------------------------------------------------------------------
+/* We look over the cdrom for package files. This is a recursive
+   search that short circuits when it his a package file in the dir.
+   This speeds it up greatly as the majority of the size is in the
+   binary-* sub dirs. */
+bool pkgCdrom::FindPackages(string CD,vector<string> &List,
+                           vector<string> &SList, vector<string> &SigList,
+                           string &InfoDir, pkgCdromStatus *log,
+                           unsigned int Depth)
+{
+   static ino_t Inodes[9];
+
+   // if we have a look we "pulse" now
+   if(log)
+      log->Update();
+
+   if (Depth >= 7)
+      return true;
+
+   if (CD[CD.length()-1] != '/')
+      CD += '/';   
+
+   if (chdir(CD.c_str()) != 0)
+      return _error->Errno("chdir","Unable to change to %s",CD.c_str());
+
+   // Look for a .disk subdirectory
+   struct stat Buf;
+   if (stat(".disk",&Buf) == 0)
+   {
+      if (InfoDir.empty() == true)
+        InfoDir = CD + ".disk/";
+   }
+
+   // Don't look into directories that have been marked to ingore.
+   if (stat(".aptignr",&Buf) == 0)
+      return true;
+
+
+   /* Check _first_ for a signature file as apt-cdrom assumes that all files
+      under a Packages/Source file are in control of that file and stops 
+      the scanning
+   */
+   if (stat("Release.gpg",&Buf) == 0)
+   {
+      SigList.push_back(CD);
+   }
+   /* Aha! We found some package files. We assume that everything under 
+      this dir is controlled by those package files so we don't look down
+      anymore */
+   if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0)
+   {
+      List.push_back(CD);
+      
+      // Continue down if thorough is given
+      if (_config->FindB("APT::CDROM::Thorough",false) == false)
+        return true;
+   }
+   if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0)
+   {
+      SList.push_back(CD);
+      
+      // Continue down if thorough is given
+      if (_config->FindB("APT::CDROM::Thorough",false) == false)
+        return true;
+   }
+   
+   DIR *D = opendir(".");
+   if (D == 0)
+      return _error->Errno("opendir","Unable to read %s",CD.c_str());
+   
+   // Run over the directory
+   for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
+   {
+      // Skip some files..
+      if (strcmp(Dir->d_name,".") == 0 ||
+         strcmp(Dir->d_name,"..") == 0 ||
+         //strcmp(Dir->d_name,"source") == 0 ||
+         strcmp(Dir->d_name,".disk") == 0 ||
+         strcmp(Dir->d_name,"experimental") == 0 ||
+         strcmp(Dir->d_name,"binary-all") == 0 ||
+          strcmp(Dir->d_name,"debian-installer") == 0)
+        continue;
+
+      // See if the name is a sub directory
+      struct stat Buf;
+      if (stat(Dir->d_name,&Buf) != 0)
+        continue;      
+      
+      if (S_ISDIR(Buf.st_mode) == 0)
+        continue;
+      
+      unsigned int I;
+      for (I = 0; I != Depth; I++)
+        if (Inodes[I] == Buf.st_ino)
+           break;
+      if (I != Depth)
+        continue;
+      
+      // Store the inodes weve seen
+      Inodes[Depth] = Buf.st_ino;
+
+      // Descend
+      if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false)
+        break;
+
+      if (chdir(CD.c_str()) != 0)
+        return _error->Errno("chdir","Unable to change to %s",CD.c_str());
+   };
+
+   closedir(D);
+   
+   return !_error->PendingError();
+}
+
+// Score - We compute a 'score' for a path                             /*{{{*/
+// ---------------------------------------------------------------------
+/* Paths are scored based on how close they come to what I consider
+   normal. That is ones that have 'dist' 'stable' 'testing' will score
+   higher than ones without. */
+int pkgCdrom::Score(string Path)
+{
+   int Res = 0;
+   if (Path.find("stable/") != string::npos)
+      Res += 29;
+   if (Path.find("/binary-") != string::npos)
+      Res += 20;
+   if (Path.find("testing/") != string::npos)
+      Res += 28;
+   if (Path.find("unstable/") != string::npos)
+      Res += 27;
+   if (Path.find("/dists/") != string::npos)
+      Res += 40;
+   if (Path.find("/main/") != string::npos)
+      Res += 20;
+   if (Path.find("/contrib/") != string::npos)
+      Res += 20;
+   if (Path.find("/non-free/") != string::npos)
+      Res += 20;
+   if (Path.find("/non-US/") != string::npos)
+      Res += 20;
+   if (Path.find("/source/") != string::npos)
+      Res += 10;
+   if (Path.find("/debian/") != string::npos)
+      Res -= 10;
+   return Res;
+}
+
+                                                                       /*}}}*/
+// DropBinaryArch - Dump dirs with a string like /binary-<foo>/                /*{{{*/
+// ---------------------------------------------------------------------
+/* Here we drop everything that is not this machines arch */
+bool pkgCdrom::DropBinaryArch(vector<string> &List)
+{
+   char S[300];
+   snprintf(S,sizeof(S),"/binary-%s/",
+           _config->Find("Apt::Architecture").c_str());
+   
+   for (unsigned int I = 0; I < List.size(); I++)
+   {
+      const char *Str = List[I].c_str();
+      
+      const char *Res;
+      if ((Res = strstr(Str,"/binary-")) == 0)
+        continue;
+
+      // Weird, remove it.
+      if (strlen(Res) < strlen(S))
+      {
+        List.erase(List.begin() + I);
+        I--;
+        continue;
+      }
+         
+      // See if it is our arch
+      if (stringcmp(Res,Res + strlen(S),S) == 0)
+        continue;
+      
+      // Erase it
+      List.erase(List.begin() + I);
+      I--;
+   }
+   
+   return true;
+}
+
+
+// DropRepeats - Drop repeated files resulting from symlinks           /*{{{*/
+// ---------------------------------------------------------------------
+/* Here we go and stat every file that we found and strip dup inodes. */
+bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
+{
+   // Get a list of all the inodes
+   ino_t *Inodes = new ino_t[List.size()];
+   for (unsigned int I = 0; I != List.size(); I++)
+   {
+      struct stat Buf;
+      if (stat((List[I] + Name).c_str(),&Buf) != 0 &&
+         stat((List[I] + Name + ".gz").c_str(),&Buf) != 0)
+        _error->Errno("stat","Failed to stat %s%s",List[I].c_str(),
+                      Name);
+      Inodes[I] = Buf.st_ino;
+   }
+   
+   if (_error->PendingError() == true)
+      return false;
+   
+   // Look for dups
+   for (unsigned int I = 0; I != List.size(); I++)
+   {
+      for (unsigned int J = I+1; J < List.size(); J++)
+      {
+        // No match
+        if (Inodes[J] != Inodes[I])
+           continue;
+        
+        // We score the two paths.. and erase one
+        int ScoreA = Score(List[I]);
+        int ScoreB = Score(List[J]);
+        if (ScoreA < ScoreB)
+        {
+           List[I] = string();
+           break;
+        }
+        
+        List[J] = string();
+      }
+   }  
+   // Wipe erased entries
+   for (unsigned int I = 0; I < List.size();)
+   {
+      if (List[I].empty() == false)
+        I++;
+      else
+        List.erase(List.begin()+I);
+   }
+   
+   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 */
+void pkgCdrom::ReduceSourcelist(string CD,vector<string> &List)
+{
+   sort(List.begin(),List.end());
+   
+   // Collect similar entries
+   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+   {
+      // Find a space..
+      string::size_type Space = (*I).find(' ');
+      if (Space == string::npos)
+        continue;
+      string::size_type SSpace = (*I).find(' ',Space + 1);
+      if (SSpace == string::npos)
+        continue;
+
+      string Word1 = string(*I,Space,SSpace-Space);
+      string Prefix = string(*I,0,Space);
+      for (vector<string>::iterator J = List.begin(); J != I; J++)
+      {
+        // Find a space..
+        string::size_type Space2 = (*J).find(' ');
+        if (Space2 == string::npos)
+           continue;
+        string::size_type SSpace2 = (*J).find(' ',Space2 + 1);
+        if (SSpace2 == string::npos)
+           continue;
+        
+        if (string(*J,0,Space2) != Prefix)
+           continue;
+        if (string(*J,Space2,SSpace2-Space2) != Word1)
+           continue;
+        
+        *J += string(*I,SSpace);
+        *I = string();
+      }
+   }   
+
+   // Wipe erased entries
+   for (unsigned int I = 0; I < List.size();)
+   {
+      if (List[I].empty() == false)
+        I++;
+      else
+        List.erase(List.begin()+I);
+   }
+}
+                                                                       /*}}}*/
+// WriteDatabase - Write the CDROM Database file                       /*{{{*/
+// ---------------------------------------------------------------------
+/* We rewrite the configuration class associated with the cdrom database. */
+bool pkgCdrom::WriteDatabase(Configuration &Cnf)
+{
+   string DFile = _config->FindFile("Dir::State::cdroms");
+   string NewFile = DFile + ".new";
+   
+   unlink(NewFile.c_str());
+   ofstream Out(NewFile.c_str());
+   if (!Out)
+      return _error->Errno("ofstream::ofstream",
+                          "Failed to open %s.new",DFile.c_str());
+   
+   /* Write out all of the configuration directives by walking the
+      configuration tree */
+   const Configuration::Item *Top = Cnf.Tree(0);
+   for (; Top != 0;)
+   {
+      // Print the config entry
+      if (Top->Value.empty() == false)
+        Out <<  Top->FullTag() + " \"" << Top->Value << "\";" << endl;
+      
+      if (Top->Child != 0)
+      {
+        Top = Top->Child;
+        continue;
+      }
+      
+      while (Top != 0 && Top->Next == 0)
+        Top = Top->Parent;
+      if (Top != 0)
+        Top = Top->Next;
+   }   
+
+   Out.close();
+   
+   rename(DFile.c_str(),string(DFile + '~').c_str());
+   if (rename(NewFile.c_str(),DFile.c_str()) != 0)
+      return _error->Errno("rename","Failed to rename %s.new to %s",
+                          DFile.c_str(),DFile.c_str());
+
+   return true;
+}
+                                                                       /*}}}*/
+// WriteSourceList - Write an updated sourcelist                       /*{{{*/
+// ---------------------------------------------------------------------
+/* This reads the old source list and copies it into the new one. It 
+   appends the new CDROM entires just after the first block of comments.
+   This places them first in the file. It also removes any old entries
+   that were the same. */
+bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
+{
+   if (List.size() == 0)
+      return true;
+
+   string File = _config->FindFile("Dir::Etc::sourcelist");
+
+   // Open the stream for reading
+   ifstream F((FileExists(File)?File.c_str():"/dev/null"),
+             ios::in );
+   if (!F != 0)
+      return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
+
+   string NewFile = File + ".new";
+   unlink(NewFile.c_str());
+   ofstream Out(NewFile.c_str());
+   if (!Out)
+      return _error->Errno("ofstream::ofstream",
+                          "Failed to open %s.new",File.c_str());
+
+   // Create a short uri without the path
+   string ShortURI = "cdrom:[" + Name + "]/";   
+   string ShortURI2 = "cdrom:" + Name + "/";     // For Compatibility
+
+   string Type;
+   if (Source == true)
+      Type = "deb-src";
+   else
+      Type = "deb";
+   
+   char Buffer[300];
+   int CurLine = 0;
+   bool First = true;
+   while (F.eof() == false)
+   {      
+      F.getline(Buffer,sizeof(Buffer));
+      CurLine++;
+      _strtabexpand(Buffer,sizeof(Buffer));
+      _strstrip(Buffer);
+            
+      // Comment or blank
+      if (Buffer[0] == '#' || Buffer[0] == 0)
+      {
+        Out << Buffer << endl;
+        continue;
+      }
+
+      if (First == true)
+      {
+        for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+        {
+           string::size_type Space = (*I).find(' ');
+           if (Space == string::npos)
+              return _error->Error("Internal error");
+           Out << Type << " cdrom:[" << Name << "]/" << string(*I,0,Space) <<
+              " " << string(*I,Space+1) << endl;
+        }
+      }
+      First = false;
+      
+      // Grok it
+      string cType;
+      string URI;
+      const char *C = Buffer;
+      if (ParseQuoteWord(C,cType) == false ||
+         ParseQuoteWord(C,URI) == false)
+      {
+        Out << Buffer << endl;
+        continue;
+      }
+
+      // Emit lines like this one
+      if (cType != Type || (string(URI,0,ShortURI.length()) != ShortURI &&
+         string(URI,0,ShortURI.length()) != ShortURI2))
+      {
+        Out << Buffer << endl;
+        continue;
+      }      
+   }
+   
+   // Just in case the file was empty
+   if (First == true)
+   {
+      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+      {
+        string::size_type Space = (*I).find(' ');
+        if (Space == string::npos)
+           return _error->Error("Internal error");
+        
+        Out << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
+           " " << string(*I,Space+1) << endl;
+      }
+   }
+   
+   Out.close();
+
+   rename(File.c_str(),string(File + '~').c_str());
+   if (rename(NewFile.c_str(),File.c_str()) != 0)
+      return _error->Errno("rename","Failed to rename %s.new to %s",
+                          File.c_str(),File.c_str());
+   
+   return true;
+}
+
+
+bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
+{
+   stringstream msg;
+
+   // Startup
+   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
+   if (CDROM[0] == '.')
+      CDROM= SafeGetCWD() + '/' + CDROM;
+
+   if(log) {
+      msg.str("");
+      ioprintf(msg, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
+                     CDROM.c_str());
+      log->Update(msg.str());
+   }
+   if (MountCdrom(CDROM) == false)
+      return _error->Error("Failed to mount the cdrom.");
+
+   // Hash the CD to get an ID
+   if(log) 
+      log->Update(_("Identifying.. "));
+   
+
+   if (IdentCdrom(CDROM,ident) == false)
+   {
+      ident = "";
+      return false;
+   }
+
+   msg.str("");
+   ioprintf(msg, "[%s]\n",ident.c_str());
+   log->Update(msg.str());
+
+
+   // Read the database
+   Configuration Database;
+   string DFile = _config->FindFile("Dir::State::cdroms");
+   if (FileExists(DFile) == true)
+   {
+      if (ReadConfigFile(Database,DFile) == false)
+        return _error->Error("Unable to read the cdrom database %s",
+                             DFile.c_str());
+   }
+   if(log) {
+      msg.str("");
+      ioprintf(msg, _("Stored Label: %s \n"),
+              Database.Find("CD::"+ident).c_str());
+      log->Update(msg.str());
+   }
+   return true;
+}
+
+
+bool pkgCdrom::Add(pkgCdromStatus *log)
+{
+   stringstream msg;
+
+   // Startup
+   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
+   if (CDROM[0] == '.')
+      CDROM= SafeGetCWD() + '/' + CDROM;
+   
+   if(log) {
+      log->SetTotal(STEP_LAST);
+      msg.str("");
+      ioprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str());
+      log->Update(msg.str(), STEP_PREPARE);
+   }
+
+   // Read the database
+   Configuration Database;
+   string DFile = _config->FindFile("Dir::State::cdroms");
+   if (FileExists(DFile) == true)
+   {
+      if (ReadConfigFile(Database,DFile) == false)
+        return _error->Error("Unable to read the cdrom database %s",
+                             DFile.c_str());
+   }
+   
+   // Unmount the CD and get the user to put in the one they want
+   if (_config->FindB("APT::CDROM::NoMount",false) == false)
+   {
+      if(log)
+        log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT);
+      UnmountCdrom(CDROM);
+
+      if(log) {
+        log->Update(_("Waiting for disc...\n"), STEP_WAIT);
+        if(!log->ChangeCdrom()) {
+           // user aborted
+           return false; 
+        }
+      }
+
+      // Mount the new CDROM
+      log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT);
+      if (MountCdrom(CDROM) == false)
+        return _error->Error("Failed to mount the cdrom.");
+   }
+   
+   // Hash the CD to get an ID
+   if(log)
+      log->Update(_("Identifying.. "), STEP_IDENT);
+   string ID;
+   if (IdentCdrom(CDROM,ID) == false)
+   {
+      log->Update("\n");
+      return false;
+   }
+   if(log) 
+      log->Update("["+ID+"]\n");
+
+   if(log) 
+      log->Update(_("Scanning Disc for index files..\n"),STEP_SCAN);
+   
+   // Get the CD structure
+   vector<string> List;
+   vector<string> SourceList;
+   vector<string> SigList;
+   string StartDir = SafeGetCWD();
+   string InfoDir;
+   if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false)
+   {
+      log->Update("\n");
+      return false;
+   }
+
+   chdir(StartDir.c_str());
+
+   if (_config->FindB("Debug::aptcdrom",false) == true)
+   {
+      cout << "I found (binary):" << endl;
+      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+        cout << *I << endl;
+      cout << "I found (source):" << endl;
+      for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
+        cout << *I << endl;
+      cout << "I found (Signatures):" << endl;
+      for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); I++)
+        cout << *I << endl;
+   }   
+
+   //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
+
+   // Fix up the list
+   DropBinaryArch(List);
+   DropRepeats(List,"Packages");
+   DropRepeats(SourceList,"Sources");
+   DropRepeats(SigList,"Release.gpg");
+   if(log) {
+      msg.str("");
+      ioprintf(msg, _("Found %i package indexes, %i source indexes and "
+                     "%i signatures\n"), 
+              List.size(), SourceList.size(), SigList.size());
+      log->Update(msg.str(), STEP_SCAN);
+   }
+
+   if (List.size() == 0 && SourceList.size() == 0)
+      return _error->Error("Unable to locate any package files, perhaps this is not a Debian Disc");
+
+   // Check if the CD is in the database
+   string Name;
+   if (Database.Exists("CD::" + ID) == false ||
+       _config->FindB("APT::CDROM::Rename",false) == true)
+   {
+      // Try to use the CDs label if at all possible
+      if (InfoDir.empty() == false &&
+         FileExists(InfoDir + "/info") == true)
+      {
+        ifstream F(string(InfoDir + "/info").c_str());
+        if (!F == 0)
+           getline(F,Name);
+
+        if (Name.empty() == false)
+        {
+           // Escape special characters
+           string::iterator J = Name.begin();
+           for (; J != Name.end(); J++)
+              if (*J == '"' || *J == ']' || *J == '[')
+                 *J = '_';
+           
+           if(log) {
+              msg.str("");
+              ioprintf(msg, "Found label '%s'\n", Name.c_str());
+              log->Update(msg.str());
+           }
+           Database.Set("CD::" + ID + "::Label",Name);
+        }       
+      }
+      
+      if (_config->FindB("APT::CDROM::Rename",false) == true ||
+         Name.empty() == true)
+      {
+        if(!log) 
+           return _error->Error("No disc name found and no way to ask for it");
+
+        while(true) {
+           if(!log->AskCdromName(Name)) {
+              // user canceld
+              return false; 
+           }
+           cout << "Name: '" << Name << "'" << endl;
+
+           if (Name.empty() == false &&
+               Name.find('"') == string::npos &&
+               Name.find('[') == string::npos &&
+               Name.find(']') == string::npos)
+              break;
+           log->Update(_("That is not a valid name, try again.\n"));
+        }
+      }      
+   }
+   else
+      Name = Database.Find("CD::" + ID);
+
+   // Escape special characters
+   string::iterator J = Name.begin();
+   for (; J != Name.end(); J++)
+      if (*J == '"' || *J == ']' || *J == '[')
+        *J = '_';
+   
+   Database.Set("CD::" + ID,Name);
+   if(log) {
+      msg.str("");
+      ioprintf(msg, _("This Disc is called: \n'%s'\n"), Name.c_str());
+      log->Update(msg.str());
+   }
+
+   log->Update(_("Copying package lists..."), STEP_COPY);
+   // take care of the signatures and copy them if they are ok
+   // (we do this before PackageCopy as it modifies "List" and "SourceList")
+   SigVerify SignVerify;
+   SignVerify.CopyAndVerify(CDROM, Name, SigList, List, SourceList);
+   
+   // Copy the package files to the state directory
+   PackageCopy Copy;
+   SourceCopy SrcCopy;
+   if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
+       SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false)
+      return false;
+
+   // reduce the List so that it takes less space in sources.list
+   ReduceSourcelist(CDROM,List);
+   ReduceSourcelist(CDROM,SourceList);
+
+   // Write the database and sourcelist
+   if (_config->FindB("APT::cdrom::NoAct",false) == false)
+   {
+      if (WriteDatabase(Database) == false)
+        return false;
+      
+      if(log) {
+        log->Update(_("Writing new source list\n"), STEP_WRITE);
+      }
+      if (WriteSourceList(Name,List,false) == false ||
+         WriteSourceList(Name,SourceList,true) == false)
+        return false;
+   }
+
+   // Print the sourcelist entries
+   if(log) 
+      log->Update(_("Source List entries for this Disc are:\n"));
+
+   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+   {
+      string::size_type Space = (*I).find(' ');
+      if (Space == string::npos)
+        return _error->Error("Internal error");
+
+      if(log) {
+        msg.str("");
+        msg << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
+           " " << string(*I,Space+1) << endl;
+        log->Update(msg.str());
+      }
+   }
+
+   for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
+   {
+      string::size_type Space = (*I).find(' ');
+      if (Space == string::npos)
+        return _error->Error("Internal error");
+
+      if(log) {
+        msg.str("");
+        msg << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) << 
+           " " << string(*I,Space+1) << endl;
+        log->Update(msg.str());
+      }
+   }
+
+   
+
+   // Unmount and finish
+   if (_config->FindB("APT::CDROM::NoMount",false) == false) {
+      log->Update(_("Unmounting CD-ROM..."), STEP_LAST);
+      UnmountCdrom(CDROM);
+   }
+
+   return true;
+}
diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h
new file mode 100644 (file)
index 0000000..085eb64
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef PKGLIB_CDROM_H
+#define PKGLIB_CDROM_H
+
+#include<apt-pkg/init.h>
+#include<string>
+#include<vector>
+
+#ifdef __GNUG__
+#pragma interface "apt-pkg/cdrom.h"
+#endif
+
+using namespace std;
+
+class pkgCdromStatus
+{
+ protected:
+   int totalSteps;
+
+ public:
+   pkgCdromStatus() {};
+   virtual ~pkgCdromStatus() {};
+
+   // total steps
+   virtual void SetTotal(int total) { totalSteps = total; };
+   // update steps, will be called regularly as a "pulse"
+   virtual void Update(string text="", int current=0) = 0;
+   
+   // ask for cdrom insert
+   virtual bool ChangeCdrom() = 0;
+   // ask for cdrom name
+   virtual bool AskCdromName(string &Name) = 0;
+   // Progress indicator for the Index rewriter
+   virtual OpProgress* GetOpProgress() {return NULL; };
+};
+
+class pkgCdrom 
+{
+ protected:
+   enum {
+      STEP_PREPARE = 1,
+      STEP_UNMOUNT,
+      STEP_WAIT,
+      STEP_MOUNT,
+      STEP_IDENT,
+      STEP_SCAN,
+      STEP_COPY,
+      STEP_WRITE,
+      STEP_UNMOUNT3,
+      STEP_LAST
+   };
+
+
+   bool FindPackages(string CD,vector<string> &List,
+                    vector<string> &SList, vector<string> &SigList,
+                    string &InfoDir, pkgCdromStatus *log,
+                    unsigned int Depth = 0);
+   bool DropBinaryArch(vector<string> &List);
+   bool DropRepeats(vector<string> &List,const char *Name);
+   void ReduceSourcelist(string CD,vector<string> &List);
+   bool WriteDatabase(Configuration &Cnf);
+   bool WriteSourceList(string Name,vector<string> &List,bool Source);
+   int Score(string Path);
+
+ public:
+   bool Ident(string &ident, pkgCdromStatus *log);
+   bool Add(pkgCdromStatus *log);
+};
+
+
+
+#endif
diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc
new file mode 100644 (file)
index 0000000..9010018
--- /dev/null
@@ -0,0 +1,644 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+// $Id: indexcopy.cc,v 1.10 2002/03/26 07:38:58 jgg Exp $
+/* ######################################################################
+
+   Index Copying - Aid for copying and verifying the index files
+   
+   This class helps apt-cache reconstruct a damaged index files. 
+   
+   ##################################################################### */
+                                                                       /*}}}*/
+// Include Files                                                       /*{{{*/
+#include "indexcopy.h"
+
+#include <apt-pkg/error.h>
+#include <apt-pkg/progress.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/indexrecords.h>
+#include <apt-pkg/md5.h>
+#include <apt-pkg/cdrom.h>
+#include <apti18n.h>
+
+#include <iostream>
+#include <sstream>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdio.h>
+                                                                       /*}}}*/
+
+using namespace std;
+
+// IndexCopy::CopyPackages - Copy the package files from the CD                /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
+                            pkgCdromStatus *log)
+{
+   OpProgress *Progress = NULL;
+   if (List.size() == 0)
+      return true;
+   
+   if(log) 
+      Progress = log->GetOpProgress();
+   
+   bool NoStat = _config->FindB("APT::CDROM::Fast",false);
+   bool Debug = _config->FindB("Debug::aptcdrom",false);
+   
+   // Prepare the progress indicator
+   unsigned long TotalSize = 0;
+   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+   {
+      struct stat Buf;
+      if (stat(string(*I + GetFileName()).c_str(),&Buf) != 0 &&
+         stat(string(*I + GetFileName() + ".gz").c_str(),&Buf) != 0)
+        return _error->Errno("stat","Stat failed for %s",
+                             string(*I + GetFileName()).c_str());
+      TotalSize += Buf.st_size;
+   }   
+
+   unsigned long CurrentSize = 0;
+   unsigned int NotFound = 0;
+   unsigned int WrongSize = 0;
+   unsigned int Packages = 0;
+   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+   {      
+      string OrigPath = string(*I,CDROM.length());
+      unsigned long FileSize = 0;
+      
+      // Open the package file
+      FileFd Pkg;
+      if (FileExists(*I + GetFileName()) == true)
+      {
+        Pkg.Open(*I + GetFileName(),FileFd::ReadOnly);
+        FileSize = Pkg.Size();
+      }      
+      else
+      {
+        FileFd From(*I + GetFileName() + ".gz",FileFd::ReadOnly);
+        if (_error->PendingError() == true)
+           return false;
+        FileSize = From.Size();
+        
+        // Get a temp file
+        FILE *tmp = tmpfile();
+        if (tmp == 0)
+           return _error->Errno("tmpfile","Unable to create a tmp file");
+        Pkg.Fd(dup(fileno(tmp)));
+        fclose(tmp);
+        
+        // Fork gzip
+        pid_t Process = fork();
+        if (Process < 0)
+           return _error->Errno("fork","Couldn't fork gzip");
+        
+        // The child
+        if (Process == 0)
+        {          
+           dup2(From.Fd(),STDIN_FILENO);
+           dup2(Pkg.Fd(),STDOUT_FILENO);
+           SetCloseExec(STDIN_FILENO,false);
+           SetCloseExec(STDOUT_FILENO,false);
+           
+           const char *Args[3];
+           string Tmp =  _config->Find("Dir::bin::gzip","gzip");
+           Args[0] = Tmp.c_str();
+           Args[1] = "-d";
+           Args[2] = 0;
+           execvp(Args[0],(char **)Args);
+           exit(100);
+        }
+        
+        // Wait for gzip to finish
+        if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
+           return _error->Error("gzip failed, perhaps the disk is full.");
+        
+        Pkg.Seek(0);
+      }
+      pkgTagFile Parser(&Pkg);
+      if (_error->PendingError() == true)
+        return false;
+      
+      // Open the output file
+      char S[400];
+      snprintf(S,sizeof(S),"cdrom:[%s]/%s%s",Name.c_str(),
+              (*I).c_str() + CDROM.length(),GetFileName());
+      string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
+      TargetF += URItoFileName(S);
+      if (_config->FindB("APT::CDROM::NoAct",false) == true)
+        TargetF = "/dev/null";
+      FileFd Target(TargetF,FileFd::WriteEmpty);
+      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
+      if (_error->PendingError() == true)
+        return false;
+      if (TargetFl == 0)
+        return _error->Errno("fdopen","Failed to reopen fd");
+      
+      // Setup the progress meter
+      if(Progress)
+        Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
+                                  string("Reading ") + Type() + " Indexes");
+
+      // Parse
+      if(Progress)
+        Progress->SubProgress(Pkg.Size());
+      pkgTagSection Section;
+      this->Section = &Section;
+      string Prefix;
+      unsigned long Hits = 0;
+      unsigned long Chop = 0;
+      while (Parser.Step(Section) == true)
+      {
+        if(Progress)
+           Progress->Progress(Parser.Offset());
+        string File;
+        unsigned long Size;
+        if (GetFile(File,Size) == false)
+        {
+           fclose(TargetFl);
+           return false;
+        }
+        
+        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 || 
+               Buf.st_size == 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++;
+        
+        if (RewriteEntry(TargetFl,File) == false)
+        {
+           fclose(TargetFl);
+           return false;
+        }
+      }
+      fclose(TargetFl);
+
+      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");
+      }
+        
+      /* 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 += FileSize;
+   }   
+   if(Progress)
+      Progress->Done();
+   
+   // Some stats
+   if(log) {
+      stringstream msg;
+      if(NotFound == 0 && WrongSize == 0)
+        ioprintf(msg, _("Wrote %i records.\n"), Packages);
+      else if (NotFound != 0 && WrongSize == 0)
+        ioprintf(msg, _("Wrote %i records with %i missing files.\n"), 
+                 Packages, NotFound);
+      else if (NotFound == 0 && WrongSize != 0)
+        ioprintf(msg, _("Wrote %i records with %i mismachted files\n"), 
+                 Packages, WrongSize);
+      if (NotFound != 0 && WrongSize != 0)
+        ioprintf(msg, _("Wrote %i records with %i missing files and %i mismachted files\n"), Packages, NotFound, WrongSize);
+   }
+   
+   if (Packages == 0)
+      _error->Warning("No valid records were found.");
+
+   if (NotFound + WrongSize > 10)
+      _error->Warning("Alot of entries were discarded, something may be wrong.\n");
+   
+
+   return true;
+}
+                                                                       /*}}}*/
+// IndexCopy::ChopDirs - Chop off the leading directory components     /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string IndexCopy::ChopDirs(string Path,unsigned int Depth)
+{
+   string::size_type I = 0;
+   do
+   {
+      I = Path.find('/',I+1);
+      Depth--;
+   }
+   while (I != string::npos && Depth != 0);
+   
+   if (I == string::npos)
+      return string();
+   
+   return string(Path,I+1);
+}
+                                                                       /*}}}*/
+// IndexCopy::ReconstructPrefix - Fix strange prefixing                        /*{{{*/
+// ---------------------------------------------------------------------
+/* This prepends dir components from the path to the package files to
+   the path to the deb until it is found */
+bool IndexCopy::ReconstructPrefix(string &Prefix,string OrigPath,string CD,
+                                 string File)
+{
+   bool Debug = _config->FindB("Debug::aptcdrom",false);
+   unsigned int Depth = 1;
+   string MyPrefix = Prefix;
+   while (1)
+   {
+      struct stat Buf;
+      if (stat(string(CD + MyPrefix + File).c_str(),&Buf) != 0)
+      {
+        if (Debug == true)
+           cout << "Failed, " << CD + MyPrefix + File << endl;
+        if (GrabFirst(OrigPath,MyPrefix,Depth++) == true)
+           continue;
+        
+        return false;
+      }
+      else
+      {
+        Prefix = MyPrefix;
+        return true;
+      }      
+   }
+   return false;
+}
+                                                                       /*}}}*/
+// IndexCopy::ReconstructChop - Fixes bad source paths                 /*{{{*/
+// ---------------------------------------------------------------------
+/* This removes path components from the filename and prepends the location
+   of the package files until a file is found */
+bool IndexCopy::ReconstructChop(unsigned long &Chop,string Dir,string File)
+{
+   // Attempt to reconstruct the filename
+   unsigned long Depth = 0;
+   while (1)
+   {
+      struct stat Buf;
+      if (stat(string(Dir + File).c_str(),&Buf) != 0)
+      {
+        File = ChopDirs(File,1);
+        Depth++;
+        if (File.empty() == false)
+           continue;
+        return false;
+      }
+      else
+      {
+        Chop = Depth;
+        return true;
+      }
+   }
+   return false;
+}
+                                                                       /*}}}*/
+// IndexCopy::ConvertToSourceList - Convert a Path to a sourcelist     /*{{{*/
+// ---------------------------------------------------------------------
+/* We look for things in dists/ notation and convert them to 
+   <dist> <component> form otherwise it is left alone. This also strips
+   the CD path. 
+   This implements a regex sort of like: 
+    (.*)/dists/([^/]*)/(.*)/binary-* 
+     ^          ^      ^- Component
+     |          |-------- Distribution
+     |------------------- Path
+   
+   It was deciced to use only a single word for dist (rather than say
+   unstable/non-us) to increase the chance that each CD gets a single
+   line in sources.list.
+ */
+void IndexCopy::ConvertToSourceList(string CD,string &Path)
+{
+   char S[300];
+   snprintf(S,sizeof(S),"binary-%s",_config->Find("Apt::Architecture").c_str());
+   
+   // Strip the cdrom base path
+   Path = string(Path,CD.length());
+   if (Path.empty() == true)
+      Path = "/";
+   
+   // Too short to be a dists/ type
+   if (Path.length() < strlen("dists/"))
+      return;
+   
+   // Not a dists type.
+   if (stringcmp(Path.c_str(),Path.c_str()+strlen("dists/"),"dists/") != 0)
+      return;
+      
+   // Isolate the dist
+   string::size_type Slash = strlen("dists/");
+   string::size_type Slash2 = Path.find('/',Slash + 1);
+   if (Slash2 == string::npos || Slash2 + 2 >= Path.length())
+      return;
+   string Dist = string(Path,Slash,Slash2 - Slash);
+   
+   // Isolate the component
+   Slash = Slash2;
+   for (unsigned I = 0; I != 10; I++)
+   {
+      Slash = Path.find('/',Slash+1);
+      if (Slash == string::npos || Slash + 2 >= Path.length())
+        return;
+      string Comp = string(Path,Slash2+1,Slash - Slash2-1);
+        
+      // Verify the trailing binary- bit
+      string::size_type BinSlash = Path.find('/',Slash + 1);
+      if (Slash == string::npos)
+        return;
+      string Binary = string(Path,Slash+1,BinSlash - Slash-1);
+      
+      if (Binary != S && Binary != "source")
+        continue;
+
+      Path = Dist + ' ' + Comp;
+      return;
+   }   
+}
+                                                                       /*}}}*/
+// IndexCopy::GrabFirst - Return the first Depth path components       /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool IndexCopy::GrabFirst(string Path,string &To,unsigned int Depth)
+{
+   string::size_type I = 0;
+   do
+   {
+      I = Path.find('/',I+1);
+      Depth--;
+   }
+   while (I != string::npos && Depth != 0);
+   
+   if (I == string::npos)
+      return false;
+
+   To = string(Path,0,I+1);
+   return true;
+}
+                                                                       /*}}}*/
+// PackageCopy::GetFile - Get the file information from the section    /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool PackageCopy::GetFile(string &File,unsigned long &Size)
+{
+   File = Section->FindS("Filename");
+   Size = Section->FindI("Size");
+   if (File.empty() || Size == 0)
+      return _error->Error("Cannot find filename or size tag");
+   return true;
+}
+                                                                       /*}}}*/
+// PackageCopy::RewriteEntry - Rewrite the entry with a new filename   /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool PackageCopy::RewriteEntry(FILE *Target,string File)
+{
+   TFRewriteData Changes[] = {{"Filename",File.c_str()},
+                              {}};
+   
+   if (TFRewrite(Target,*Section,TFRewritePackageOrder,Changes) == false)
+      return false;
+   fputc('\n',Target);
+   return true;
+}
+                                                                       /*}}}*/
+// SourceCopy::GetFile - Get the file information from the section     /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool SourceCopy::GetFile(string &File,unsigned long &Size)
+{
+   string Files = Section->FindS("Files");
+   if (Files.empty() == true)
+      return false;
+
+   // Stash the / terminated directory prefix
+   string Base = Section->FindS("Directory");
+   if (Base.empty() == false && Base[Base.length()-1] != '/')
+      Base += '/';
+   
+   // Read the first file triplet
+   const char *C = Files.c_str();
+   string sSize;
+   string MD5Hash;
+   
+   // Parse each of the elements
+   if (ParseQuoteWord(C,MD5Hash) == false ||
+       ParseQuoteWord(C,sSize) == false ||
+       ParseQuoteWord(C,File) == false)
+      return _error->Error("Error parsing file record");
+   
+   // Parse the size and append the directory
+   Size = atoi(sSize.c_str());
+   File = Base + File;
+   return true;
+}
+                                                                       /*}}}*/
+// SourceCopy::RewriteEntry - Rewrite the entry with a new filename    /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool SourceCopy::RewriteEntry(FILE *Target,string File)
+{
+   string Dir(File,0,File.rfind('/'));
+   TFRewriteData Changes[] = {{"Directory",Dir.c_str()},
+                              {}};
+   
+   if (TFRewrite(Target,*Section,TFRewriteSourceOrder,Changes) == false)
+      return false;
+   fputc('\n',Target);
+   return true;
+}
+
+
+                                                                       /*}}}*/
+
+bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
+{
+   const indexRecords::checkSum *Record = MetaIndex->Lookup(file);
+
+   if (!Record) 
+   {
+      _error->Warning("Can't find authentication record for: %s",file.c_str());
+      return false;
+   }
+
+   MD5Summation sum;
+   FileFd Fd(prefix+file, FileFd::ReadOnly);
+   sum.AddFD(Fd.Fd(), Fd.Size());
+   Fd.Close();
+   string MD5 = (string)sum.Result();
+   
+   if (Record->MD5Hash != MD5)
+   {
+      _error->Warning("MD5 mismatch for: %s",file.c_str());
+      return false;
+   }
+
+   if(_config->FindB("Debug::aptcdrom",false)) 
+   {
+      cout << "File: " << prefix+file << endl;
+      cout << "Expected MD5sum: " << Record->MD5Hash << endl;
+      cout << "got: " << MD5 << endl << endl;
+   }
+
+   return true;
+}
+
+bool SigVerify::CopyMetaIndex(string CDROM, string CDName, 
+                             string prefix, string file)
+{
+      char S[400];
+      snprintf(S,sizeof(S),"cdrom:[%s]/%s%s",CDName.c_str(),
+              (prefix).c_str() + CDROM.length(),file.c_str());
+      string TargetF = _config->FindDir("Dir::State::lists");
+      TargetF += URItoFileName(S);
+
+      FileFd Target;
+      FileFd Rel;
+      Target.Open(TargetF,FileFd::WriteEmpty);
+      Rel.Open(prefix + file,FileFd::ReadOnly);
+      if (_error->PendingError() == true)
+        return false;
+      if (CopyFile(Rel,Target) == false)
+        return false;
+   
+      return true;
+}
+
+bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
+                             vector<string> PkgList,vector<string> SrcList)
+{
+   if (SigList.size() == 0)
+      return true;
+
+   bool Debug = _config->FindB("Debug::aptcdrom",false);
+
+   // Read all Release files
+   for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); I++)
+   { 
+      if(Debug)
+        cout << "Signature verify for: " << *I << endl;
+
+      indexRecords *MetaIndex = new indexRecords;
+      string prefix = *I; 
+
+      // a Release.gpg without a Release should never happen
+      if(!FileExists(*I+"Release"))
+        continue;
+
+
+      // verify the gpg signature of "Release"
+      // gpg --verify "*I+Release.gpg", "*I+Release"
+      string gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv");
+      string pubringpath = _config->Find("Apt::GPGV::TrustedKeyring", "/etc/apt/trusted.gpg");
+      pid_t pid = ExecFork();
+      if(pid < 0) {
+        _error->Error("Fork failed");
+        return false;
+      }
+      if(pid == 0) {
+        execlp(gpgvpath.c_str(), gpgvpath.c_str(), "--keyring", 
+               pubringpath.c_str(), string(*I+"Release.gpg").c_str(), 
+               string(*I+"Release").c_str(), NULL);
+      }
+      if(!ExecWait(pid, "gpgv")) {
+        _error->Warning("Signature verification failed for: %s",
+                        string(*I+"Release.gpg").c_str());
+        // something went wrong, don't copy the Release.gpg
+        // FIXME: delete any existing gpg file?
+        continue;
+      }
+
+      // Open the Release file and add it to the MetaIndex
+      if(!MetaIndex->Load(*I+"Release"))
+      {
+        _error->Error(MetaIndex->ErrorText.c_str());
+        return false;
+      }
+      
+      // go over the Indexfiles and see if they verify
+      // if so, remove them from our copy of the lists
+      vector<string> keys = MetaIndex->MetaKeys();
+      for (vector<string>::iterator I = keys.begin(); I != keys.end(); I++)
+      { 
+        if(!Verify(prefix,*I, MetaIndex)) {
+           // something went wrong, don't copy the Release.gpg
+           // FIXME: delete any existing gpg file?
+           continue;    
+        }
+      }
+
+      // we need a fresh one for the Release.gpg
+      delete MetaIndex;
+   
+      // everything was fine, copy the Release and Release.gpg file
+      CopyMetaIndex(CDROM, Name, prefix, "Release");
+      CopyMetaIndex(CDROM, Name, prefix, "Release.gpg");
+   }   
+
+   return true;
+}
diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h
new file mode 100644 (file)
index 0000000..fa8e9c1
--- /dev/null
@@ -0,0 +1,83 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+// $Id: indexcopy.h,v 1.3 2001/05/27 04:46:54 jgg Exp $
+/* ######################################################################
+
+   Index Copying - Aid for copying and verifying the index files
+   
+   ##################################################################### */
+                                                                       /*}}}*/
+#ifndef INDEXCOPY_H
+#define INDEXCOPY_H
+
+#include <vector>
+#include <string>
+#include <stdio.h>
+
+using std::string;
+using std::vector;
+
+class pkgTagSection;
+class FileFd;
+class indexRecords;
+class pkgCdromStatus;
+
+class IndexCopy
+{
+   protected:
+   
+   pkgTagSection *Section;
+   
+   string ChopDirs(string Path,unsigned int Depth);
+   bool ReconstructPrefix(string &Prefix,string OrigPath,string CD,
+                         string File);
+   bool ReconstructChop(unsigned long &Chop,string Dir,string File);
+   void ConvertToSourceList(string CD,string &Path);
+   bool GrabFirst(string Path,string &To,unsigned int Depth);
+   virtual bool GetFile(string &Filename,unsigned long &Size) = 0;
+   virtual bool RewriteEntry(FILE *Target,string File) = 0;
+   virtual const char *GetFileName() = 0;
+   virtual const char *Type() = 0;
+   
+   public:
+
+   bool CopyPackages(string CDROM,string Name,vector<string> &List,
+                    pkgCdromStatus *log);
+};
+
+class PackageCopy : public IndexCopy
+{
+   protected:
+   
+   virtual bool GetFile(string &Filename,unsigned long &Size);
+   virtual bool RewriteEntry(FILE *Target,string File);
+   virtual const char *GetFileName() {return "Packages";};
+   virtual const char *Type() {return "Package";};
+   
+   public:
+};
+
+class SourceCopy : public IndexCopy
+{
+   protected:
+   
+   virtual bool GetFile(string &Filename,unsigned long &Size);
+   virtual bool RewriteEntry(FILE *Target,string File);
+   virtual const char *GetFileName() {return "Sources";};
+   virtual const char *Type() {return "Source";};
+   
+   public:
+};
+
+class SigVerify 
+{
+   bool Verify(string prefix,string file, indexRecords *records);
+   bool CopyMetaIndex(string CDROM, string CDName, 
+                     string prefix, string file);
+
+ public:
+   bool CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
+                     vector<string> PkgList,vector<string> SrcList);
+};
+
+#endif
index c4b8a82353802a6cbad7647dac9435a8a3a92a81..06ed7921cbb0cdfb90f5bed5a4449d93b18be8a5 100644 (file)
@@ -83,6 +83,17 @@ bool indexRecords::Load(const string Filename)
    return true;
 }
 
+vector<string> indexRecords::MetaKeys()
+{
+   std::vector<std::string> keys;
+   std::map<string,checkSum *>::iterator I = Entries.begin();
+   while(I != Entries.end()) {
+      keys.push_back((*I).first);
+      ++I;
+   }
+   return keys;
+}
+
 bool indexRecords::parseSumData(const char *&Start, const char *End,
                                   string &Name, string &Hash, size_t &Size)
 {
index 277280620909a8ef521c3399f50e64b4e302c008..414faceaa8ebc2e6ad344647b8cfaf2c2da0f555 100644 (file)
@@ -12,6 +12,7 @@
 #include <apt-pkg/fileutl.h>
 
 #include <map>
+#include <vector>
 
 class indexRecords
 {
@@ -34,7 +35,8 @@ class indexRecords
 
    // Lookup function
    virtual const checkSum *Lookup(const string MetaKey);
-   
+   std::vector<std::string> MetaKeys();
+
    virtual bool Load(string Filename);
    string GetDist() const;
    virtual bool CheckDist(const string MaybeDist) const;
index 41045f91ab9261263fb79af5d52b8b525f549904..5f48f0f529bf2aaf202c1aa6aaf94a0a82ff1727 100644 (file)
@@ -13,7 +13,7 @@ include ../buildlib/defaults.mak
 # methods/makefile - FIXME
 LIBRARY=apt-pkg
 LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
-MAJOR=3.8
+MAJOR=3.9
 MINOR=0
 SLIBS=$(PTHREADLIB) $(INTLLIBS)
 APT_DOMAIN:=libapt-pkg$(MAJOR)
@@ -34,14 +34,14 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
         acquire-worker.cc acquire-method.cc init.cc clean.cc \
         srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
         pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
-        indexrecords.cc vendor.cc vendorlist.cc
+        indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
          orderlist.h sourcelist.h packagemanager.h tagfile.h \
          init.h pkgcache.h version.h progress.h pkgrecords.h \
          acquire.h acquire-worker.h acquire-item.h acquire-method.h \
          clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
          pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
-          vendorlist.h
+          vendorlist.h cdrom.h indexcopy.h
 
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..
index 7367a55a316f23187e15e541806a0eae1bb0a097..5767062e4ccc101cfe646f4a58e0e585c4d13d03 100644 (file)
 #include <apt-pkg/progress.h>
 #include <apt-pkg/cdromutl.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/acquire.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/cdrom.h>
 #include <config.h>
 #include <apti18n.h>
     
-#include "indexcopy.h"
+//#include "indexcopy.h"
 
 #include <locale.h>
 #include <iostream>
 
 using namespace std;
 
-// FindPackages - Find the package files on the CDROM                  /*{{{*/
-// ---------------------------------------------------------------------
-/* We look over the cdrom for package files. This is a recursive
-   search that short circuits when it his a package file in the dir.
-   This speeds it up greatly as the majority of the size is in the
-   binary-* sub dirs. */
-bool FindPackages(string CD,vector<string> &List,vector<string> &SList,
-                 string &InfoDir,unsigned int Depth = 0)
+                                                                        /*{{{*/
+class pkgCdromTextStatus : public pkgCdromStatus
 {
-   static ino_t Inodes[9];
-   if (Depth >= 7)
-      return true;
-
-   if (CD[CD.length()-1] != '/')
-      CD += '/';   
-
-   if (chdir(CD.c_str()) != 0)
-      return _error->Errno("chdir","Unable to change to %s",CD.c_str());
-
-   // Look for a .disk subdirectory
-   struct stat Buf;
-   if (stat(".disk",&Buf) == 0)
-   {
-      if (InfoDir.empty() == true)
-        InfoDir = CD + ".disk/";
-   }
-
-   // Don't look into directories that have been marked to ingore.
-   if (stat(".aptignr",&Buf) == 0)
-      return true;
-   
-   /* Aha! We found some package files. We assume that everything under 
-      this dir is controlled by those package files so we don't look down
-      anymore */
-   if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0)
-   {
-      List.push_back(CD);
-      
-      // Continue down if thorough is given
-      if (_config->FindB("APT::CDROM::Thorough",false) == false)
-        return true;
-   }
-   if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0)
-   {
-      SList.push_back(CD);
-      
-      // Continue down if thorough is given
-      if (_config->FindB("APT::CDROM::Thorough",false) == false)
-        return true;
-   }
-   
-   DIR *D = opendir(".");
-   if (D == 0)
-      return _error->Errno("opendir","Unable to read %s",CD.c_str());
-   
-   // Run over the directory
-   for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
-   {
-      // Skip some files..
-      if (strcmp(Dir->d_name,".") == 0 ||
-         strcmp(Dir->d_name,"..") == 0 ||
-         //strcmp(Dir->d_name,"source") == 0 ||
-         strcmp(Dir->d_name,".disk") == 0 ||
-         strcmp(Dir->d_name,"experimental") == 0 ||
-         strcmp(Dir->d_name,"binary-all") == 0 ||
-          strcmp(Dir->d_name,"debian-installer") == 0)
-        continue;
-
-      // See if the name is a sub directory
-      struct stat Buf;
-      if (stat(Dir->d_name,&Buf) != 0)
-        continue;      
-      
-      if (S_ISDIR(Buf.st_mode) == 0)
-        continue;
-      
-      unsigned int I;
-      for (I = 0; I != Depth; I++)
-        if (Inodes[I] == Buf.st_ino)
-           break;
-      if (I != Depth)
-        continue;
-      
-      // Store the inodes weve seen
-      Inodes[Depth] = Buf.st_ino;
-
-      // Descend
-      if (FindPackages(CD + Dir->d_name,List,SList,InfoDir,Depth+1) == false)
-        break;
-
-      if (chdir(CD.c_str()) != 0)
-        return _error->Errno("chdir","Unable to change to %s",CD.c_str());
-   };
-
-   closedir(D);
-   
-   return !_error->PendingError();
+protected:
+   OpTextProgress Progress;
+   void Prompt(const char *Text); 
+   string PromptLine(const char *Text);
+   bool AskCdromName(string &name);
+
+public:
+   virtual void Update(string text, int current);
+   virtual bool ChangeCdrom();
+   virtual OpProgress* GetOpProgress();
 }
-                                                                       /*}}}*/
-// DropBinaryArch - Dump dirs with a string like /binary-<foo>/                /*{{{*/
-// ---------------------------------------------------------------------
-/* Here we drop everything that is not this machines arch */
-bool DropBinaryArch(vector<string> &List)
-{
-   char S[300];
-   snprintf(S,sizeof(S),"/binary-%s/",
-           _config->Find("Apt::Architecture").c_str());
-   
-   for (unsigned int I = 0; I < List.size(); I++)
-   {
-      const char *Str = List[I].c_str();
-      
-      const char *Res;
-      if ((Res = strstr(Str,"/binary-")) == 0)
-        continue;
 
-      // Weird, remove it.
-      if (strlen(Res) < strlen(S))
-      {
-        List.erase(List.begin() + I);
-        I--;
-        continue;
-      }
-         
-      // See if it is our arch
-      if (stringcmp(Res,Res + strlen(S),S) == 0)
-        continue;
-      
-      // Erase it
-      List.erase(List.begin() + I);
-      I--;
-   }
-   
-   return true;
-}
-                                                                       /*}}}*/
-// Score - We compute a 'score' for a path                             /*{{{*/
-// ---------------------------------------------------------------------
-/* Paths are scored based on how close they come to what I consider
-   normal. That is ones that have 'dist' 'stable' 'testing' will score
-   higher than ones without. */
-int Score(string Path)
+void pkgCdromTextStatus::Prompt(const char *Text) 
 {
-   int Res = 0;
-   if (Path.find("stable/") != string::npos)
-      Res += 29;
-   if (Path.find("/binary-") != string::npos)
-      Res += 20;
-   if (Path.find("testing/") != string::npos)
-      Res += 28;
-   if (Path.find("unstable/") != string::npos)
-      Res += 27;
-   if (Path.find("/dists/") != string::npos)
-      Res += 40;
-   if (Path.find("/main/") != string::npos)
-      Res += 20;
-   if (Path.find("/contrib/") != string::npos)
-      Res += 20;
-   if (Path.find("/non-free/") != string::npos)
-      Res += 20;
-   if (Path.find("/non-US/") != string::npos)
-      Res += 20;
-   if (Path.find("/source/") != string::npos)
-      Res += 10;
-   if (Path.find("/debian/") != string::npos)
-      Res -= 10;
-   return Res;
-}
-                                                                       /*}}}*/
-// DropRepeats - Drop repeated files resulting from symlinks           /*{{{*/
-// ---------------------------------------------------------------------
-/* Here we go and stat every file that we found and strip dup inodes. */
-bool DropRepeats(vector<string> &List,const char *Name)
-{
-   // Get a list of all the inodes
-   ino_t *Inodes = new ino_t[List.size()];
-   for (unsigned int I = 0; I != List.size(); I++)
-   {
-      struct stat Buf;
-      if (stat((List[I] + Name).c_str(),&Buf) != 0 &&
-         stat((List[I] + Name + ".gz").c_str(),&Buf) != 0)
-        _error->Errno("stat","Failed to stat %s%s",List[I].c_str(),
-                      Name);
-      Inodes[I] = Buf.st_ino;
-   }
-   
-   if (_error->PendingError() == true)
-      return false;
-   
-   // Look for dups
-   for (unsigned int I = 0; I != List.size(); I++)
-   {
-      for (unsigned int J = I+1; J < List.size(); J++)
-      {
-        // No match
-        if (Inodes[J] != Inodes[I])
-           continue;
-        
-        // We score the two paths.. and erase one
-        int ScoreA = Score(List[I]);
-        int ScoreB = Score(List[J]);
-        if (ScoreA < ScoreB)
-        {
-           List[I] = string();
-           break;
-        }
-        
-        List[J] = string();
-      }
-   }  
-   // Wipe erased entries
-   for (unsigned int I = 0; I < List.size();)
-   {
-      if (List[I].empty() == false)
-        I++;
-      else
-        List.erase(List.begin()+I);
-   }
-   
-   return true;
+   char C;
+   cout << Text << ' ' << flush;
+   read(STDIN_FILENO,&C,1);
+   if (C != '\n')
+      cout << 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 */
-void ReduceSourcelist(string CD,vector<string> &List)
+string pkgCdromTextStatus::PromptLine(const char *Text)
 {
-   sort(List.begin(),List.end());
+   cout << Text << ':' << endl;
    
-   // Collect similar entries
-   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
-   {
-      // Find a space..
-      string::size_type Space = (*I).find(' ');
-      if (Space == string::npos)
-        continue;
-      string::size_type SSpace = (*I).find(' ',Space + 1);
-      if (SSpace == string::npos)
-        continue;
-
-      string Word1 = string(*I,Space,SSpace-Space);
-      string Prefix = string(*I,0,Space);
-      for (vector<string>::iterator J = List.begin(); J != I; J++)
-      {
-        // Find a space..
-        string::size_type Space2 = (*J).find(' ');
-        if (Space2 == string::npos)
-           continue;
-        string::size_type SSpace2 = (*J).find(' ',Space2 + 1);
-        if (SSpace2 == string::npos)
-           continue;
-        
-        if (string(*J,0,Space2) != Prefix)
-           continue;
-        if (string(*J,Space2,SSpace2-Space2) != Word1)
-           continue;
-        
-        *J += string(*I,SSpace);
-        *I = string();
-      }
-   }   
-
-   // Wipe erased entries
-   for (unsigned int I = 0; I < List.size();)
-   {
-      if (List[I].empty() == false)
-        I++;
-      else
-        List.erase(List.begin()+I);
-   }
+   string Res;
+   getline(cin,Res);
+   return Res;
 }
-                                                                       /*}}}*/
-// WriteDatabase - Write the CDROM Database file                       /*{{{*/
-// ---------------------------------------------------------------------
-/* We rewrite the configuration class associated with the cdrom database. */
-bool WriteDatabase(Configuration &Cnf)
-{
-   string DFile = _config->FindFile("Dir::State::cdroms");
-   string NewFile = DFile + ".new";
-   
-   unlink(NewFile.c_str());
-   ofstream Out(NewFile.c_str());
-   if (!Out)
-      return _error->Errno("ofstream::ofstream",
-                          "Failed to open %s.new",DFile.c_str());
-   
-   /* Write out all of the configuration directives by walking the
-      configuration tree */
-   const Configuration::Item *Top = Cnf.Tree(0);
-   for (; Top != 0;)
-   {
-      // Print the config entry
-      if (Top->Value.empty() == false)
-        Out <<  Top->FullTag() + " \"" << Top->Value << "\";" << endl;
-      
-      if (Top->Child != 0)
-      {
-        Top = Top->Child;
-        continue;
-      }
-      
-      while (Top != 0 && Top->Next == 0)
-        Top = Top->Parent;
-      if (Top != 0)
-        Top = Top->Next;
-   }   
 
-   Out.close();
-   
-   rename(DFile.c_str(),string(DFile + '~').c_str());
-   if (rename(NewFile.c_str(),DFile.c_str()) != 0)
-      return _error->Errno("rename","Failed to rename %s.new to %s",
-                          DFile.c_str(),DFile.c_str());
-
-   return true;
-}
-                                                                       /*}}}*/
-// WriteSourceList - Write an updated sourcelist                       /*{{{*/
-// ---------------------------------------------------------------------
-/* This reads the old source list and copies it into the new one. It 
-   appends the new CDROM entires just after the first block of comments.
-   This places them first in the file. It also removes any old entries
-   that were the same. */
-bool WriteSourceList(string Name,vector<string> &List,bool Source)
+bool pkgCdromTextStatus::AskCdromName(string &name) 
 {
-   if (List.size() == 0)
-      return true;
-
-   string File = _config->FindFile("Dir::Etc::sourcelist");
-
-   // Open the stream for reading
-   ifstream F((FileExists(File)?File.c_str():"/dev/null"),
-             ios::in );
-   if (!F != 0)
-      return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
-
-   string NewFile = File + ".new";
-   unlink(NewFile.c_str());
-   ofstream Out(NewFile.c_str());
-   if (!Out)
-      return _error->Errno("ofstream::ofstream",
-                          "Failed to open %s.new",File.c_str());
-
-   // Create a short uri without the path
-   string ShortURI = "cdrom:[" + Name + "]/";   
-   string ShortURI2 = "cdrom:" + Name + "/";     // For Compatibility
-
-   const char *Type;
-   if (Source == true)
-      Type = "deb-src";
-   else
-      Type = "deb";
-   
-   char Buffer[300];
-   int CurLine = 0;
-   bool First = true;
-   while (F.eof() == false)
-   {      
-      F.getline(Buffer,sizeof(Buffer));
-      CurLine++;
-      _strtabexpand(Buffer,sizeof(Buffer));
-      _strstrip(Buffer);
-            
-      // Comment or blank
-      if (Buffer[0] == '#' || Buffer[0] == 0)
-      {
-        Out << Buffer << endl;
-        continue;
-      }
-
-      if (First == true)
-      {
-        for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
-        {
-           string::size_type Space = (*I).find(' ');
-           if (Space == string::npos)
-              return _error->Error("Internal error");
-           Out << Type << " cdrom:[" << Name << "]/" << string(*I,0,Space) <<
-              " " << string(*I,Space+1) << endl;
-        }
-      }
-      First = false;
-      
-      // Grok it
-      string cType;
-      string URI;
-      const char *C = Buffer;
-      if (ParseQuoteWord(C,cType) == false ||
-         ParseQuoteWord(C,URI) == false)
-      {
-        Out << Buffer << endl;
-        continue;
-      }
-
-      // Emit lines like this one
-      if (cType != Type || (string(URI,0,ShortURI.length()) != ShortURI &&
-         string(URI,0,ShortURI.length()) != ShortURI2))
-      {
-        Out << Buffer << endl;
-        continue;
-      }      
-   }
-   
-   // Just in case the file was empty
-   if (First == true)
-   {
-      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
-      {
-        string::size_type Space = (*I).find(' ');
-        if (Space == string::npos)
-           return _error->Error("Internal error");
+   cout << "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'" << flush;
+   name = PromptLine("");
         
-        Out << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
-           " " << string(*I,Space+1) << endl;
-      }
-   }
-   
-   Out.close();
-
-   rename(File.c_str(),string(File + '~').c_str());
-   if (rename(NewFile.c_str(),File.c_str()) != 0)
-      return _error->Errno("rename","Failed to rename %s.new to %s",
-                          File.c_str(),File.c_str());
-   
    return true;
 }
-                                                                       /*}}}*/
+   
 
-// Prompt - Simple prompt                                              /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void Prompt(const char *Text)
+void pkgCdromTextStatus::Update(string text, int current) 
 {
-   char C;
-   cout << Text << ' ' << flush;
-   read(STDIN_FILENO,&C,1);
-   if (C != '\n')
-      cout << endl;
+   if(text.size() > 0)
+      cout << text << flush;
 }
-                                                                       /*}}}*/
-// PromptLine - Prompt for an input line                               /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string PromptLine(const char *Text)
+
+virtual bool pkgCdromTextStatus::ChangeCdrom() 
 {
-   cout << Text << ':' << endl;
-   
-   string Res;
-   getline(cin,Res);
-   return Res;
+   Prompt("Please insert a Disc in the drive and press enter");
+   return true;
 }
+
+virtual OpProgress* pkgCdromTextStatus::GetOpProgress() 
+{ 
+   return &Progress; 
+};
+
                                                                        /*}}}*/
 
 // DoAdd - Add a new CDROM                                             /*{{{*/
@@ -501,186 +109,13 @@ string PromptLine(const char *Text)
    verify them. Then rewrite the database files */
 bool DoAdd(CommandLine &)
 {
-   // Startup
-   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
-   if (CDROM[0] == '.')
-      CDROM= SafeGetCWD() + '/' + CDROM;
-   
-   cout << "Using CD-ROM mount point " << CDROM << endl;
-      
-   // Read the database
-   Configuration Database;
-   string DFile = _config->FindFile("Dir::State::cdroms");
-   if (FileExists(DFile) == true)
-   {
-      if (ReadConfigFile(Database,DFile) == false)
-        return _error->Error("Unable to read the cdrom database %s",
-                             DFile.c_str());
-   }
-   
-   // Unmount the CD and get the user to put in the one they want
-   if (_config->FindB("APT::CDROM::NoMount",false) == false)
-   {
-      cout << "Unmounting CD-ROM" << endl;
-      UnmountCdrom(CDROM);
-
-      // Mount the new CDROM
-      Prompt("Please insert a Disc in the drive and press enter");
-      cout << "Mounting CD-ROM" << endl;
-      if (MountCdrom(CDROM) == false)
-        return _error->Error("Failed to mount the cdrom.");
-   }
-   
-   // Hash the CD to get an ID
-   cout << "Identifying.. " << flush;
-   string ID;
-   if (IdentCdrom(CDROM,ID) == false)
-   {
-      cout << endl;
-      return false;
-   }
-   
-   cout << '[' << ID << ']' << endl;
-
-   cout << "Scanning Disc for index files..  " << flush;
-   // Get the CD structure
-   vector<string> List;
-   vector<string> sList;
-   string StartDir = SafeGetCWD();
-   string InfoDir;
-   if (FindPackages(CDROM,List,sList,InfoDir) == false)
-   {
-      cout << endl;
-      return false;
-   }
-   
-   chdir(StartDir.c_str());
-
-   if (_config->FindB("Debug::aptcdrom",false) == true)
-   {
-      cout << "I found (binary):" << endl;
-      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
-        cout << *I << endl;
-      cout << "I found (source):" << endl;
-      for (vector<string>::iterator I = sList.begin(); I != sList.end(); I++)
-        cout << *I << endl;
-   }   
-   
-   // Fix up the list
-   DropBinaryArch(List);
-   DropRepeats(List,"Packages");
-   DropRepeats(sList,"Sources");
-   cout << "Found " << List.size() << " package indexes and " << sList.size() << 
-      " source indexes." << endl;
-
-   if (List.size() == 0 && sList.size() == 0)
-      return _error->Error("Unable to locate any package files, perhaps this is not a Debian Disc");
-   
-   // Check if the CD is in the database
-   string Name;
-   if (Database.Exists("CD::" + ID) == false ||
-       _config->FindB("APT::CDROM::Rename",false) == true)
-   {
-      // Try to use the CDs label if at all possible
-      if (InfoDir.empty() == false &&
-         FileExists(InfoDir + "/info") == true)
-      {
-        ifstream F(string(InfoDir + "/info").c_str());
-        if (!F == 0)
-           getline(F,Name);
-
-        if (Name.empty() == false)
-        {
-           // Escape special characters
-           string::iterator J = Name.begin();
-           for (; J != Name.end(); J++)
-              if (*J == '"' || *J == ']' || *J == '[')
-                 *J = '_';
-           
-           cout << "Found label '" << Name << "'" << endl;
-           Database.Set("CD::" + ID + "::Label",Name);
-        }       
-      }
-      
-      if (_config->FindB("APT::CDROM::Rename",false) == true ||
-         Name.empty() == true)
-      {
-        cout << "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'";
-        while (1)
-        {
-           Name = PromptLine("");
-           if (Name.empty() == false &&
-               Name.find('"') == string::npos &&
-               Name.find('[') == string::npos &&
-               Name.find(']') == string::npos)
-              break;
-           cout << "That is not a valid name, try again " << endl;
-        }       
-      }      
-   }
-   else
-      Name = Database.Find("CD::" + ID);
-
-   // Escape special characters
-   string::iterator J = Name.begin();
-   for (; J != Name.end(); J++)
-      if (*J == '"' || *J == ']' || *J == '[')
-        *J = '_';
-   
-   Database.Set("CD::" + ID,Name);
-   cout << "This Disc is called:" << endl << " '" << Name << "'" << endl;
-   
-   // Copy the package files to the state directory
-   PackageCopy Copy;
-   SourceCopy SrcCopy;
-   if (Copy.CopyPackages(CDROM,Name,List) == false ||
-       SrcCopy.CopyPackages(CDROM,Name,sList) == false)
-      return false;
-   
-   ReduceSourcelist(CDROM,List);
-   ReduceSourcelist(CDROM,sList);
-
-   // Write the database and sourcelist
-   if (_config->FindB("APT::cdrom::NoAct",false) == false)
-   {
-      if (WriteDatabase(Database) == false)
-        return false;
-      
-      cout << "Writing new source list" << endl;
-      if (WriteSourceList(Name,List,false) == false ||
-         WriteSourceList(Name,sList,true) == false)
-        return false;
-   }
-
-   // Print the sourcelist entries
-   cout << "Source List entries for this Disc are:" << endl;
-   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
-   {
-      string::size_type Space = (*I).find(' ');
-      if (Space == string::npos)
-        return _error->Error("Internal error");
-
-      cout << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
-        " " << string(*I,Space+1) << endl;
-   }
-
-   for (vector<string>::iterator I = sList.begin(); I != sList.end(); I++)
-   {
-      string::size_type Space = (*I).find(' ');
-      if (Space == string::npos)
-        return _error->Error("Internal error");
-
-      cout << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) << 
-        " " << string(*I,Space+1) << endl;
-   }
-
-   cout << "Repeat this process for the rest of the CDs in your set." << endl;
-
-   // Unmount and finish
-   if (_config->FindB("APT::CDROM::NoMount",false) == false)
-      UnmountCdrom(CDROM);
-   
-   return true;
+   bool res = false;
+   pkgCdromTextStatus log;
+   pkgCdrom cdrom;
+   res = cdrom.Add(&log);
+   if(res)
+      cout << "Repeat this process for the rest of the CDs in your set." << endl;
+   return res;
 }
                                                                        /*}}}*/
 // DoIdent - Ident a CDROM                                             /*{{{*/
@@ -688,38 +123,10 @@ bool DoAdd(CommandLine &)
 /* */
 bool DoIdent(CommandLine &)
 {
-   // Startup
-   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
-   if (CDROM[0] == '.')
-      CDROM= SafeGetCWD() + '/' + CDROM;
-   
-   cout << "Using CD-ROM mount point " << CDROM << endl;
-   cout << "Mounting CD-ROM" << endl;
-   if (MountCdrom(CDROM) == false)
-      return _error->Error("Failed to mount the cdrom.");
-   
-   // Hash the CD to get an ID
-   cout << "Identifying.. " << flush;
-   string ID;
-   if (IdentCdrom(CDROM,ID) == false)
-   {
-      cout << endl;
-      return false;
-   }
-   
-   cout << '[' << ID << ']' << endl;
-
-   // Read the database
-   Configuration Database;
-   string DFile = _config->FindFile("Dir::State::cdroms");
-   if (FileExists(DFile) == true)
-   {
-      if (ReadConfigFile(Database,DFile) == false)
-        return _error->Error("Unable to read the cdrom database %s",
-                             DFile.c_str());
-   }
-   cout << "Stored Label: '" << Database.Find("CD::" + ID) << "'" << endl;
-   return true;
+   string ident;
+   pkgCdromTextStatus log;
+   pkgCdrom cdrom;
+   return cdrom.Ident(ident, &log);
 }
                                                                        /*}}}*/
 
diff --git a/cmdline/indexcopy.cc b/cmdline/indexcopy.cc
deleted file mode 100644 (file)
index 0a3cd15..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-// -*- mode: cpp; mode: fold -*-
-// Description                                                         /*{{{*/
-// $Id: indexcopy.cc,v 1.10 2002/03/26 07:38:58 jgg Exp $
-/* ######################################################################
-
-   Index Copying - Aid for copying and verifying the index files
-   
-   This class helps apt-cache reconstruct a damaged index files. 
-   
-   ##################################################################### */
-                                                                       /*}}}*/
-// Include Files                                                       /*{{{*/
-#include "indexcopy.h"
-
-#include <apt-pkg/error.h>
-#include <apt-pkg/progress.h>
-#include <apt-pkg/strutl.h>
-#include <apt-pkg/fileutl.h>
-#include <apt-pkg/configuration.h>
-#include <apt-pkg/tagfile.h>
-
-#include <iostream>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <stdio.h>
-                                                                       /*}}}*/
-
-using namespace std;
-
-// IndexCopy::CopyPackages - Copy the package files from the CD                /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List)
-{
-   if (List.size() == 0)
-      return true;
-   
-   OpTextProgress Progress;
-   
-   bool NoStat = _config->FindB("APT::CDROM::Fast",false);
-   bool Debug = _config->FindB("Debug::aptcdrom",false);
-   
-   // Prepare the progress indicator
-   unsigned long TotalSize = 0;
-   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
-   {
-      struct stat Buf;
-      if (stat(string(*I + GetFileName()).c_str(),&Buf) != 0 &&
-         stat(string(*I + GetFileName() + ".gz").c_str(),&Buf) != 0)
-        return _error->Errno("stat","Stat failed for %s",
-                             string(*I + GetFileName()).c_str());
-      TotalSize += Buf.st_size;
-   }   
-
-   unsigned long CurrentSize = 0;
-   unsigned int NotFound = 0;
-   unsigned int WrongSize = 0;
-   unsigned int Packages = 0;
-   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
-   {      
-      string OrigPath = string(*I,CDROM.length());
-      unsigned long FileSize = 0;
-      
-      // Open the package file
-      FileFd Pkg;
-      if (FileExists(*I + GetFileName()) == true)
-      {
-        Pkg.Open(*I + GetFileName(),FileFd::ReadOnly);
-        FileSize = Pkg.Size();
-      }      
-      else
-      {
-        FileFd From(*I + GetFileName() + ".gz",FileFd::ReadOnly);
-        if (_error->PendingError() == true)
-           return false;
-        FileSize = From.Size();
-        
-        // Get a temp file
-        FILE *tmp = tmpfile();
-        if (tmp == 0)
-           return _error->Errno("tmpfile","Unable to create a tmp file");
-        Pkg.Fd(dup(fileno(tmp)));
-        fclose(tmp);
-        
-        // Fork gzip
-        pid_t Process = fork();
-        if (Process < 0)
-           return _error->Errno("fork","Couldn't fork gzip");
-        
-        // The child
-        if (Process == 0)
-        {          
-           dup2(From.Fd(),STDIN_FILENO);
-           dup2(Pkg.Fd(),STDOUT_FILENO);
-           SetCloseExec(STDIN_FILENO,false);
-           SetCloseExec(STDOUT_FILENO,false);
-           
-           const char *Args[3];
-           string Tmp =  _config->Find("Dir::bin::gzip","gzip");
-           Args[0] = Tmp.c_str();
-           Args[1] = "-d";
-           Args[2] = 0;
-           execvp(Args[0],(char **)Args);
-           exit(100);
-        }
-        
-        // Wait for gzip to finish
-        if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
-           return _error->Error("gzip failed, perhaps the disk is full.");
-        
-        Pkg.Seek(0);
-      }
-      pkgTagFile Parser(&Pkg);
-      if (_error->PendingError() == true)
-        return false;
-      
-      // Open the output file
-      char S[400];
-      snprintf(S,sizeof(S),"cdrom:[%s]/%s%s",Name.c_str(),
-              (*I).c_str() + CDROM.length(),GetFileName());
-      string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
-      TargetF += URItoFileName(S);
-      if (_config->FindB("APT::CDROM::NoAct",false) == true)
-        TargetF = "/dev/null";
-      FileFd Target(TargetF,FileFd::WriteEmpty);
-      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
-      if (_error->PendingError() == true)
-        return false;
-      if (TargetFl == 0)
-        return _error->Errno("fdopen","Failed to reopen fd");
-      
-      // Setup the progress meter
-      Progress.OverallProgress(CurrentSize,TotalSize,FileSize,
-                              string("Reading ") + Type() + " Indexes");
-
-      // Parse
-      Progress.SubProgress(Pkg.Size());
-      pkgTagSection Section;
-      this->Section = &Section;
-      string Prefix;
-      unsigned long Hits = 0;
-      unsigned long Chop = 0;
-      while (Parser.Step(Section) == true)
-      {
-        Progress.Progress(Parser.Offset());
-        string File;
-        unsigned long Size;
-        if (GetFile(File,Size) == false)
-        {
-           fclose(TargetFl);
-           return false;
-        }
-        
-        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 || 
-               Buf.st_size == 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++;
-        
-        if (RewriteEntry(TargetFl,File) == false)
-        {
-           fclose(TargetFl);
-           return false;
-        }
-      }
-      fclose(TargetFl);
-
-      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
-        snprintf(S,sizeof(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 += FileSize;
-   }   
-   Progress.Done();
-   
-   // Some stats
-   cout << "Wrote " << Packages << " 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)
-      _error->Warning("No valid records were found.");
-
-   if (NotFound + WrongSize > 10)
-      cout << "Alot of entries were discarded, something may be wrong." << endl;
-
-   return true;
-}
-                                                                       /*}}}*/
-// IndexCopy::ChopDirs - Chop off the leading directory components     /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string IndexCopy::ChopDirs(string Path,unsigned int Depth)
-{
-   string::size_type I = 0;
-   do
-   {
-      I = Path.find('/',I+1);
-      Depth--;
-   }
-   while (I != string::npos && Depth != 0);
-   
-   if (I == string::npos)
-      return string();
-   
-   return string(Path,I+1);
-}
-                                                                       /*}}}*/
-// IndexCopy::ReconstructPrefix - Fix strange prefixing                        /*{{{*/
-// ---------------------------------------------------------------------
-/* This prepends dir components from the path to the package files to
-   the path to the deb until it is found */
-bool IndexCopy::ReconstructPrefix(string &Prefix,string OrigPath,string CD,
-                                 string File)
-{
-   bool Debug = _config->FindB("Debug::aptcdrom",false);
-   unsigned int Depth = 1;
-   string MyPrefix = Prefix;
-   while (1)
-   {
-      struct stat Buf;
-      if (stat(string(CD + MyPrefix + File).c_str(),&Buf) != 0)
-      {
-        if (Debug == true)
-           cout << "Failed, " << CD + MyPrefix + File << endl;
-        if (GrabFirst(OrigPath,MyPrefix,Depth++) == true)
-           continue;
-        
-        return false;
-      }
-      else
-      {
-        Prefix = MyPrefix;
-        return true;
-      }      
-   }
-   return false;
-}
-                                                                       /*}}}*/
-// IndexCopy::ReconstructChop - Fixes bad source paths                 /*{{{*/
-// ---------------------------------------------------------------------
-/* This removes path components from the filename and prepends the location
-   of the package files until a file is found */
-bool IndexCopy::ReconstructChop(unsigned long &Chop,string Dir,string File)
-{
-   // Attempt to reconstruct the filename
-   unsigned long Depth = 0;
-   while (1)
-   {
-      struct stat Buf;
-      if (stat(string(Dir + File).c_str(),&Buf) != 0)
-      {
-        File = ChopDirs(File,1);
-        Depth++;
-        if (File.empty() == false)
-           continue;
-        return false;
-      }
-      else
-      {
-        Chop = Depth;
-        return true;
-      }
-   }
-   return false;
-}
-                                                                       /*}}}*/
-// IndexCopy::ConvertToSourceList - Convert a Path to a sourcelist     /*{{{*/
-// ---------------------------------------------------------------------
-/* We look for things in dists/ notation and convert them to 
-   <dist> <component> form otherwise it is left alone. This also strips
-   the CD path. 
-   This implements a regex sort of like: 
-    (.*)/dists/([^/]*)/(.*)/binary-* 
-     ^          ^      ^- Component
-     |          |-------- Distribution
-     |------------------- Path
-   
-   It was deciced to use only a single word for dist (rather than say
-   unstable/non-us) to increase the chance that each CD gets a single
-   line in sources.list.
- */
-void IndexCopy::ConvertToSourceList(string CD,string &Path)
-{
-   char S[300];
-   snprintf(S,sizeof(S),"binary-%s",_config->Find("Apt::Architecture").c_str());
-   
-   // Strip the cdrom base path
-   Path = string(Path,CD.length());
-   if (Path.empty() == true)
-      Path = "/";
-   
-   // Too short to be a dists/ type
-   if (Path.length() < strlen("dists/"))
-      return;
-   
-   // Not a dists type.
-   if (stringcmp(Path.c_str(),Path.c_str()+strlen("dists/"),"dists/") != 0)
-      return;
-      
-   // Isolate the dist
-   string::size_type Slash = strlen("dists/");
-   string::size_type Slash2 = Path.find('/',Slash + 1);
-   if (Slash2 == string::npos || Slash2 + 2 >= Path.length())
-      return;
-   string Dist = string(Path,Slash,Slash2 - Slash);
-   
-   // Isolate the component
-   Slash = Slash2;
-   for (unsigned I = 0; I != 10; I++)
-   {
-      Slash = Path.find('/',Slash+1);
-      if (Slash == string::npos || Slash + 2 >= Path.length())
-        return;
-      string Comp = string(Path,Slash2+1,Slash - Slash2-1);
-        
-      // Verify the trailing binary- bit
-      string::size_type BinSlash = Path.find('/',Slash + 1);
-      if (Slash == string::npos)
-        return;
-      string Binary = string(Path,Slash+1,BinSlash - Slash-1);
-      
-      if (Binary != S && Binary != "source")
-        continue;
-
-      Path = Dist + ' ' + Comp;
-      return;
-   }   
-}
-                                                                       /*}}}*/
-// IndexCopy::GrabFirst - Return the first Depth path components       /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool IndexCopy::GrabFirst(string Path,string &To,unsigned int Depth)
-{
-   string::size_type I = 0;
-   do
-   {
-      I = Path.find('/',I+1);
-      Depth--;
-   }
-   while (I != string::npos && Depth != 0);
-   
-   if (I == string::npos)
-      return false;
-
-   To = string(Path,0,I+1);
-   return true;
-}
-                                                                       /*}}}*/
-// PackageCopy::GetFile - Get the file information from the section    /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool PackageCopy::GetFile(string &File,unsigned long &Size)
-{
-   File = Section->FindS("Filename");
-   Size = Section->FindI("Size");
-   if (File.empty() || Size == 0)
-      return _error->Error("Cannot find filename or size tag");
-   return true;
-}
-                                                                       /*}}}*/
-// PackageCopy::RewriteEntry - Rewrite the entry with a new filename   /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool PackageCopy::RewriteEntry(FILE *Target,string File)
-{
-   TFRewriteData Changes[] = {{"Filename",File.c_str()},
-                              {}};
-   
-   if (TFRewrite(Target,*Section,TFRewritePackageOrder,Changes) == false)
-      return false;
-   fputc('\n',Target);
-   return true;
-}
-                                                                       /*}}}*/
-// SourceCopy::GetFile - Get the file information from the section     /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool SourceCopy::GetFile(string &File,unsigned long &Size)
-{
-   string Files = Section->FindS("Files");
-   if (Files.empty() == true)
-      return false;
-
-   // Stash the / terminated directory prefix
-   string Base = Section->FindS("Directory");
-   if (Base.empty() == false && Base[Base.length()-1] != '/')
-      Base += '/';
-   
-   // Read the first file triplet
-   const char *C = Files.c_str();
-   string sSize;
-   string MD5Hash;
-   
-   // Parse each of the elements
-   if (ParseQuoteWord(C,MD5Hash) == false ||
-       ParseQuoteWord(C,sSize) == false ||
-       ParseQuoteWord(C,File) == false)
-      return _error->Error("Error parsing file record");
-   
-   // Parse the size and append the directory
-   Size = atoi(sSize.c_str());
-   File = Base + File;
-   return true;
-}
-                                                                       /*}}}*/
-// SourceCopy::RewriteEntry - Rewrite the entry with a new filename    /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool SourceCopy::RewriteEntry(FILE *Target,string File)
-{
-   string Dir(File,0,File.rfind('/'));
-   TFRewriteData Changes[] = {{"Directory",Dir.c_str()},
-                              {}};
-   
-   if (TFRewrite(Target,*Section,TFRewriteSourceOrder,Changes) == false)
-      return false;
-   fputc('\n',Target);
-   return true;
-}
-                                                                       /*}}}*/
diff --git a/cmdline/indexcopy.h b/cmdline/indexcopy.h
deleted file mode 100644 (file)
index e44a917..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// -*- mode: cpp; mode: fold -*-
-// Description                                                         /*{{{*/
-// $Id: indexcopy.h,v 1.3 2001/05/27 04:46:54 jgg Exp $
-/* ######################################################################
-
-   Index Copying - Aid for copying and verifying the index files
-   
-   ##################################################################### */
-                                                                       /*}}}*/
-#ifndef INDEXCOPY_H
-#define INDEXCOPY_H
-
-#include <vector>
-#include <string>
-#include <stdio.h>
-
-using std::string;
-using std::vector;
-
-class pkgTagSection;
-class FileFd;
-
-class IndexCopy
-{
-   protected:
-   
-   pkgTagSection *Section;
-   
-   string ChopDirs(string Path,unsigned int Depth);
-   bool ReconstructPrefix(string &Prefix,string OrigPath,string CD,
-                         string File);
-   bool ReconstructChop(unsigned long &Chop,string Dir,string File);
-   void ConvertToSourceList(string CD,string &Path);
-   bool GrabFirst(string Path,string &To,unsigned int Depth);
-   virtual bool GetFile(string &Filename,unsigned long &Size) = 0;
-   virtual bool RewriteEntry(FILE *Target,string File) = 0;
-   virtual const char *GetFileName() = 0;
-   virtual const char *Type() = 0;
-   
-   public:
-
-   bool CopyPackages(string CDROM,string Name,vector<string> &List);
-};
-
-class PackageCopy : public IndexCopy
-{
-   protected:
-   
-   virtual bool GetFile(string &Filename,unsigned long &Size);
-   virtual bool RewriteEntry(FILE *Target,string File);
-   virtual const char *GetFileName() {return "Packages";};
-   virtual const char *Type() {return "Package";};
-   
-   public:
-};
-
-class SourceCopy : public IndexCopy
-{
-   protected:
-   
-   virtual bool GetFile(string &Filename,unsigned long &Size);
-   virtual bool RewriteEntry(FILE *Target,string File);
-   virtual const char *GetFileName() {return "Sources";};
-   virtual const char *Type() {return "Source";};
-   
-   public:
-};
-
-#endif
index 21a6d47d4833c151e1702ea97cf0636c651f2668..882a0e1b564a9d8125225e6a92b1f961a874392b 100644 (file)
@@ -30,7 +30,7 @@ include $(PROGRAM_H)
 PROGRAM=apt-cdrom
 SLIBS = -lapt-pkg
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-cdrom.cc indexcopy.cc
+SOURCE = apt-cdrom.cc 
 include $(PROGRAM_H)
 
 # The apt-sortpkgs program
index 0ca0b5223811efc9e12d4387795e6c9f8cad6779..c384c399d2d8cb7536ccf8600370193fd61a8a77 100644 (file)
@@ -1,11 +1,15 @@
 apt (0.6.31) hoary; urgency=low
 
-  * Remove debugging output from apt.cron.daily (no one noticed?)
-  * Apply patch from Anthony Towns to allow SHA1Summation to process a file
-    descriptor until EOF, rather than requiring that the length of input be
-    specified (Closes: #291338)
-  * Fix build/install of Polish offline documentation, based on patch from
-    Christian Perrier (Closes: #270404)
+  * Matt Zimmerman
+    - Remove debugging output from apt.cron.daily (no one noticed?)
+    - Apply patch from Anthony Towns to allow SHA1Summation to process a file
+      descriptor until EOF, rather than requiring that the length of input be
+      specified (Closes: #291338)
+    - Fix build/install of Polish offline documentation, based on patch from
+      Christian Perrier (Closes: #270404)
+  * Michael Vogt
+    - apt-cdrom.cc seperated into frontend (cmdline/apt-cdrom.cc and library
+      apt-pkg/cdrom.{cc,h}) (Ubuntu #5668)
 
  -- Matt Zimmerman <mdz@ubuntu.com>  Fri,  4 Feb 2005 10:23:01 -0800
 
index 4d0e156585bb3975b2d18bb398cd97cf89d48b65..c91fca0212c39f589cdfcf5b7020167030f89470 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2004-12-20 10:20+0100\n"
+"POT-Creation-Date: 2005-01-26 18:00+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -146,7 +146,7 @@ msgstr ""
 msgid "       %4i %s\n"
 msgstr ""
 
-#: cmdline/apt-cache.cc:1651 cmdline/apt-cdrom.cc:731 cmdline/apt-config.cc:70
+#: cmdline/apt-cache.cc:1651 cmdline/apt-cdrom.cc:353 cmdline/apt-config.cc:70
 #: cmdline/apt-extracttemplates.cc:225 ftparchive/apt-ftparchive.cc:545
 #: cmdline/apt-get.cc:2313 cmdline/apt-sortpkgs.cc:144
 #, c-format
@@ -2259,31 +2259,31 @@ msgstr ""
 msgid "rename failed, %s (%s -> %s)."
 msgstr ""
 
-#: apt-pkg/acquire-item.cc:235 apt-pkg/acquire-item.cc:897
+#: apt-pkg/acquire-item.cc:235 apt-pkg/acquire-item.cc:904
 msgid "MD5Sum mismatch"
 msgstr ""
 
-#: apt-pkg/acquire-item.cc:711
+#: apt-pkg/acquire-item.cc:718
 #, c-format
 msgid ""
 "I wasn't able to locate a file for the %s package. This might mean you need "
 "to manually fix this package. (due to missing arch)"
 msgstr ""
 
-#: apt-pkg/acquire-item.cc:764
+#: apt-pkg/acquire-item.cc:771
 #, c-format
 msgid ""
 "I wasn't able to locate file for the %s package. This might mean you need to "
 "manually fix this package."
 msgstr ""
 
-#: apt-pkg/acquire-item.cc:800
+#: apt-pkg/acquire-item.cc:807
 #, c-format
 msgid ""
 "The package index files are corrupted. No Filename: field for package %s."
 msgstr ""
 
-#: apt-pkg/acquire-item.cc:887
+#: apt-pkg/acquire-item.cc:894
 msgid "Size mismatch"
 msgstr ""
 
@@ -2291,3 +2291,93 @@ msgstr ""
 #, c-format
 msgid "Vendor block %s contains no fingerprint"
 msgstr ""
+
+#: apt-pkg/cdrom.cc:487
+#, c-format
+msgid ""
+"Using CD-ROM mount point %s\n"
+"Mounting CD-ROM\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:496 apt-pkg/cdrom.cc:578
+msgid "Identifying.. "
+msgstr ""
+
+#: apt-pkg/cdrom.cc:521
+#, c-format
+msgid "Stored Label: %s \n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:541
+#, c-format
+msgid "Using CD-ROM mount point %s\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:559
+msgid "Unmounting CD-ROM\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:563
+msgid "Waiting for disc...\n"
+msgstr ""
+
+#. Mount the new CDROM
+#: apt-pkg/cdrom.cc:571
+msgid "Mounting CD-ROM...\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:589
+msgid "Scanning Disc for index files..\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:627
+#, c-format
+msgid "Found %i package indexes, %i source indexes and %i signatures\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:684
+msgid "That is not a valid name, try again.\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:700
+#, c-format
+msgid ""
+"This Disc is called: \n"
+"'%s'\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:704
+msgid "Copying package lists..."
+msgstr ""
+
+#: apt-pkg/cdrom.cc:728
+msgid "Writing new source list\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:737
+msgid "Source List entries for this Disc are:\n"
+msgstr ""
+
+#: apt-pkg/cdrom.cc:771
+msgid "Unmounting CD-ROM..."
+msgstr ""
+
+#: apt-pkg/indexcopy.cc:261
+#, c-format
+msgid "Wrote %i records.\n"
+msgstr ""
+
+#: apt-pkg/indexcopy.cc:263
+#, c-format
+msgid "Wrote %i records with %i missing files.\n"
+msgstr ""
+
+#: apt-pkg/indexcopy.cc:266
+#, c-format
+msgid "Wrote %i records with %i mismachted files\n"
+msgstr ""
+
+#: apt-pkg/indexcopy.cc:269
+#, c-format
+msgid "Wrote %i records with %i missing files and %i mismachted files\n"
+msgstr ""