]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/cdrom.cc
merge with debian/experimental
[apt.git] / apt-pkg / cdrom.cc
index 157f0ea3c2f3bbebfff5ee7f93a0e593e97f104d..392cd890e648d0d520741277f886ffc05ff0419a 100644 (file)
@@ -1,15 +1,16 @@
 /*
  */
+#include<config.h>
 
 #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<apt-pkg/aptconfiguration.h>
+
 #include<sstream>
 #include<fstream>
-#include<config.h>
-#include<apti18n.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
@@ -20,6 +21,8 @@
 
 #include "indexcopy.h"
 
+#include<apti18n.h>
+
 using namespace std;
 
 // FindPackages - Find the package files on the CDROM                  /*{{{*/
@@ -153,14 +156,18 @@ bool pkgCdrom::FindPackages(string CD,
         break;
 
       if (chdir(CD.c_str()) != 0)
-        return _error->Errno("chdir","Unable to change to %s",CD.c_str());
+      {
+        _error->Errno("chdir","Unable to change to %s", CD.c_str());
+        closedir(D);
+        return false;
+      }
    };
 
    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
@@ -196,7 +203,7 @@ int pkgCdrom::Score(string Path)
    // a symlink gets a big penalty
    struct stat Buf;
    string statPath = flNotFile(Path);
-   string cdromPath = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
+   string cdromPath = _config->FindDir("Acquire::cdrom::mount");
    while(statPath != cdromPath && statPath != "./") {
       statPath.resize(statPath.size()-1);  // remove the trailing '/'
       if (lstat(statPath.c_str(),&Buf) == 0) {
@@ -210,46 +217,34 @@ int pkgCdrom::Score(string Path)
 
    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)
+      const char *Start, *End;
+      if ((Start = 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
+      // Between Start and End is the architecture
+      Start += 8;
+      if ((End = strstr(Start,"/")) != 0 && Start != End &&
+          APT::Configuration::checkArchitecture(string(Start, End)) == true)
+        continue; // okay, architecture is accepted
+
+      // not accepted -> Erase it
       List.erase(List.begin() + I);
-      I--;
+      --I; // the next entry is at the same index after the erase
    }
    
    return true;
 }
-
-
+                                                                       /*}}}*/
 // DropRepeats - Drop repeated files resulting from symlinks           /*{{{*/
 // ---------------------------------------------------------------------
 /* Here we go and stat every file that we found and strip dup inodes. */
@@ -267,8 +262,10 @@ bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
       Inodes[I] = Buf.st_ino;
    }
    
-   if (_error->PendingError() == true)
+   if (_error->PendingError() == true) {
+      delete[] Inodes;
       return false;
+   }
    
    // Look for dups
    for (unsigned int I = 0; I != List.size(); I++)
@@ -291,7 +288,8 @@ bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
         List[J] = string();
       }
    }  
+   delete[] Inodes;
+
    // Wipe erased entries
    for (unsigned int I = 0; I < List.size();)
    {
@@ -304,7 +302,6 @@ bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
    return true;
 }
                                                                        /*}}}*/
-
 // ReduceSourceList - Takes the path list and reduces it               /*{{{*/
 // ---------------------------------------------------------------------
 /* This takes the list of source list expressed entires and collects
@@ -314,7 +311,7 @@ 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++)
+   for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
    {
       // Find a space..
       string::size_type Space = (*I).find(' ');
@@ -326,7 +323,7 @@ void pkgCdrom::ReduceSourcelist(string CD,vector<string> &List)
 
       string Word1 = string(*I,Space,SSpace-Space);
       string Prefix = string(*I,0,Space);
-      for (vector<string>::iterator J = List.begin(); J != I; J++)
+      for (vector<string>::iterator J = List.begin(); J != I; ++J)
       {
         // Find a space..
         string::size_type Space2 = (*J).find(' ');
@@ -393,7 +390,7 @@ bool pkgCdrom::WriteDatabase(Configuration &Cnf)
 
    Out.close();
    
-   rename(DFile.c_str(),string(DFile + '~').c_str());
+   link(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());
@@ -409,7 +406,7 @@ bool pkgCdrom::WriteDatabase(Configuration &Cnf)
    that were the same. */
 bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
 {
-   if (List.size() == 0)
+   if (List.empty() == true)
       return true;
 
    string File = _config->FindFile("Dir::Etc::sourcelist");
@@ -459,7 +456,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
 
       if (First == true)
       {
-        for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+        for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
         {
            string::size_type Space = (*I).find(' ');
            if (Space == string::npos)
@@ -493,7 +490,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
    // Just in case the file was empty
    if (First == true)
    {
-      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+      for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
       {
         string::size_type Space = (*I).find(' ');
         if (Space == string::npos)
@@ -513,18 +510,18 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
    
    return true;
 }
-
-
-bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
+                                                                       /*}}}*/
+bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)               /*{{{*/
 {
    stringstream msg;
 
    // Startup
-   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
+   string CDROM = _config->FindDir("Acquire::cdrom::mount");
    if (CDROM[0] == '.')
       CDROM= SafeGetCWD() + '/' + CDROM;
 
-   if(log) {
+   if (log != NULL)
+   {
       msg.str("");
       ioprintf(msg, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
                      CDROM.c_str());
@@ -534,7 +531,7 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
       return _error->Error("Failed to mount the cdrom.");
 
    // Hash the CD to get an ID
-   if(log) 
+   if (log != NULL)
       log->Update(_("Identifying.. "));
    
 
@@ -544,10 +541,12 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
       return false;
    }
 
-   msg.str("");
-   ioprintf(msg, "[%s]\n",ident.c_str());
-   log->Update(msg.str());
-
+   if (log != NULL)
+   {
+      msg.str("");
+      ioprintf(msg, "[%s]\n",ident.c_str());
+      log->Update(msg.str());
+   }
 
    // Read the database
    Configuration Database;
@@ -558,7 +557,8 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
         return _error->Error("Unable to read the cdrom database %s",
                              DFile.c_str());
    }
-   if(log) {
+   if (log != NULL)
+   {
       msg.str("");
       ioprintf(msg, _("Stored label: %s\n"),
       Database.Find("CD::"+ident).c_str());
@@ -566,25 +566,27 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
    }
 
    // Unmount and finish
-   if (_config->FindB("APT::CDROM::NoMount",false) == false) {
-      log->Update(_("Unmounting CD-ROM...\n"), STEP_LAST);
+   if (_config->FindB("APT::CDROM::NoMount",false) == false)
+   {
+      if (log != NULL)
+        log->Update(_("Unmounting CD-ROM...\n"), STEP_LAST);
       UnmountCdrom(CDROM);
    }
 
    return true;
 }
-
-
-bool pkgCdrom::Add(pkgCdromStatus *log)
+                                                                       /*}}}*/
+bool pkgCdrom::Add(pkgCdromStatus *log)                                        /*{{{*/
 {
    stringstream msg;
 
    // Startup
-   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
+   string CDROM = _config->FindDir("Acquire::cdrom::mount");
    if (CDROM[0] == '.')
       CDROM= SafeGetCWD() + '/' + CDROM;
    
-   if(log) {
+   if(log != NULL)
+   {
       log->SetTotal(STEP_LAST);
       msg.str("");
       ioprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str());
@@ -604,11 +606,12 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
    // Unmount the CD and get the user to put in the one they want
    if (_config->FindB("APT::CDROM::NoMount",false) == false)
    {
-      if(log)
+      if(log != NULL)
         log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT);
       UnmountCdrom(CDROM);
 
-      if(log) {
+      if(log != NULL)
+      {
         log->Update(_("Waiting for disc...\n"), STEP_WAIT);
         if(!log->ChangeCdrom()) {
            // user aborted
@@ -617,26 +620,29 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
       }
 
       // Mount the new CDROM
-      log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT);
+      if(log != NULL)
+        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)
+   if(log != NULL)
       log->Update(_("Identifying.. "), STEP_IDENT);
    string ID;
    if (IdentCdrom(CDROM,ID) == false)
    {
-      log->Update("\n");
+      if (log != NULL)
+        log->Update("\n");
       return false;
    }
-   if(log) 
+   if(log != NULL)
+   {
       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;
@@ -646,7 +652,8 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
    string InfoDir;
    if (FindPackages(CDROM,List,SourceList, SigList,TransList,InfoDir,log) == false)
    {
-      log->Update("\n");
+      if (log != NULL)
+        log->Update("\n");
       return false;
    }
 
@@ -655,13 +662,13 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
    if (_config->FindB("Debug::aptcdrom",false) == true)
    {
       cout << "I found (binary):" << endl;
-      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+      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++)
+      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++)
+      for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); ++I)
         cout << *I << endl;
    }   
 
@@ -673,7 +680,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
    DropRepeats(SourceList,"Sources");
    DropRepeats(SigList,"Release.gpg");
    DropRepeats(TransList,"");
-   if(log) {
+   if(log != NULL) {
       msg.str("");
       ioprintf(msg, _("Found %zu package indexes, %zu source indexes, "
                      "%zu translation indexes and %zu signatures\n"), 
@@ -682,7 +689,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
       log->Update(msg.str(), STEP_SCAN);
    }
 
-   if (List.size() == 0 && SourceList.size() == 0
+   if (List.empty() == true && SourceList.empty() == true
    {
       if (_config->FindB("APT::CDROM::NoMount",false) == false) 
         UnmountCdrom(CDROM);
@@ -706,11 +713,12 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
         {
            // Escape special characters
            string::iterator J = Name.begin();
-           for (; J != Name.end(); J++)
+           for (; J != Name.end(); ++J)
               if (*J == '"' || *J == ']' || *J == '[')
                  *J = '_';
            
-           if(log) {
+           if(log != NULL)
+           {
               msg.str("");
               ioprintf(msg, _("Found label '%s'\n"), Name.c_str());
               log->Update(msg.str());
@@ -722,7 +730,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
       if (_config->FindB("APT::CDROM::Rename",false) == true ||
          Name.empty() == true)
       {
-        if(!log
+        if(log == NULL
          {
            if (_config->FindB("APT::CDROM::NoMount",false) == false) 
               UnmountCdrom(CDROM);
@@ -750,18 +758,18 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
 
    // Escape special characters
    string::iterator J = Name.begin();
-   for (; J != Name.end(); J++)
+   for (; J != Name.end(); ++J)
       if (*J == '"' || *J == ']' || *J == '[')
         *J = '_';
    
    Database.Set("CD::" + ID,Name);
-   if(log) {
+   if(log != NULL)
+   {
       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);
    }
-
-   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;
@@ -786,19 +794,18 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
       if (WriteDatabase(Database) == false)
         return false;
       
-      if(log) {
+      if(log != NULL)
         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
+   if(log != NULL)
       log->Update(_("Source list entries for this disc are:\n"));
 
-   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+   for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
    {
       string::size_type Space = (*I).find(' ');
       if (Space == string::npos)
@@ -808,7 +815,8 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
         return _error->Error("Internal error");
       }
 
-      if(log) {
+      if(log != NULL)
+      {
         msg.str("");
         msg << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
            " " << string(*I,Space+1) << endl;
@@ -816,7 +824,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
       }
    }
 
-   for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
+   for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); ++I)
    {
       string::size_type Space = (*I).find(' ');
       if (Space == string::npos)
@@ -826,7 +834,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
         return _error->Error("Internal error");
       }
 
-      if(log) {
+      if(log != NULL) {
         msg.str("");
         msg << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) << 
            " " << string(*I,Space+1) << endl;
@@ -834,29 +842,28 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
       }
    }
 
-   
-
    // Unmount and finish
    if (_config->FindB("APT::CDROM::NoMount",false) == false) {
-      log->Update(_("Unmounting CD-ROM...\n"), STEP_LAST);
+      if (log != NULL)
+        log->Update(_("Unmounting CD-ROM...\n"), STEP_LAST);
       UnmountCdrom(CDROM);
    }
 
    return true;
 }
-
-
-pkgUdevCdromDevices::pkgUdevCdromDevices() 
-   : libudev_handle(NULL), Dlopened(false)
+                                                                       /*}}}*/
+pkgUdevCdromDevices::pkgUdevCdromDevices()                                     /*{{{*/
+   : libudev_handle(NULL)
 {
 
 }
+                                                                       /*}}}*/
 
 bool
-pkgUdevCdromDevices::Dlopen()
+pkgUdevCdromDevices::Dlopen()                                          /*{{{*/
 {
    // alread open
-   if(Dlopened)
+   if(libudev_handle != NULL)
       return true;
 
    // see if we can get libudev
@@ -868,6 +875,7 @@ pkgUdevCdromDevices::Dlopen()
    libudev_handle = h;
    udev_new = (udev* (*)(void)) dlsym(h, "udev_new");
    udev_enumerate_add_match_property = (int (*)(udev_enumerate*, const char*, const char*))dlsym(h, "udev_enumerate_add_match_property");
+   udev_enumerate_add_match_sysattr = (int (*)(udev_enumerate*, const char*, const char*))dlsym(h, "udev_enumerate_add_match_sysattr");
    udev_enumerate_scan_devices = (int (*)(udev_enumerate*))dlsym(h, "udev_enumerate_scan_devices");
    udev_enumerate_get_list_entry = (udev_list_entry* (*)(udev_enumerate*))dlsym(h, "udev_enumerate_get_list_entry");
    udev_device_new_from_syspath = (udev_device* (*)(udev*, const char*))dlsym(h, "udev_device_new_from_syspath");
@@ -878,12 +886,21 @@ pkgUdevCdromDevices::Dlopen()
    udev_list_entry_get_next = (udev_list_entry* (*)(udev_list_entry*))dlsym(h, "udev_list_entry_get_next");
    udev_device_get_property_value = (const char* (*)(udev_device *, const char *))dlsym(h, "udev_device_get_property_value");
 
-   Dlopened = true;
    return true;
 }
-
+                                                                       /*}}}*/
+                                                                        /*{{{*/
+// convenience interface, this will just call ScanForRemovable
 vector<CdromDevice>
 pkgUdevCdromDevices::Scan()
+{ 
+   bool CdromOnly = _config->FindB("APT::cdrom::CdromOnly", true);
+   return ScanForRemovable(CdromOnly); 
+};
+                                                                       /*}}}*/
+                                                                        /*{{{*/
+vector<CdromDevice>
+pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly)
 {
    vector<CdromDevice> cdrom_devices;
    struct udev_enumerate *enumerate;
@@ -895,7 +912,11 @@ pkgUdevCdromDevices::Scan()
 
    udev_ctx = udev_new();
    enumerate = udev_enumerate_new (udev_ctx);
-   udev_enumerate_add_match_property(enumerate, "ID_CDROM", "1");
+   if (CdromOnly)
+      udev_enumerate_add_match_property(enumerate, "ID_CDROM", "1");
+   else {
+      udev_enumerate_add_match_sysattr(enumerate, "removable", "1");
+   }
 
    udev_enumerate_scan_devices (enumerate);
    devices = udev_enumerate_get_list_entry (enumerate);
@@ -907,11 +928,18 @@ pkgUdevCdromDevices::Scan()
       if (udevice == NULL)
         continue;
       const char* devnode = udev_device_get_devnode(udevice);
-      const char* mountpath = udev_device_get_property_value(udevice, "FSTAB_DIR");
+
+      // try fstab_dir first
+      string mountpath;
+      const char* mp = udev_device_get_property_value(udevice, "FSTAB_DIR");
+      if (mp)
+         mountpath = string(mp);
+      else
+         mountpath = FindMountPointForDevice(devnode);
 
       // fill in the struct
       cdrom.DeviceName = string(devnode);
-      if (mountpath) {
+      if (mountpath != "") {
         cdrom.MountPath = mountpath;
         string s = string(mountpath);
         cdrom.Mounted = IsMounted(s);
@@ -923,9 +951,11 @@ pkgUdevCdromDevices::Scan()
    } 
    return cdrom_devices;
 }
+                                                                       /*}}}*/
 
-
-pkgUdevCdromDevices::~pkgUdevCdromDevices()
+pkgUdevCdromDevices::~pkgUdevCdromDevices()                             /*{{{*/
 { 
-   dlclose(libudev_handle);
+   if (libudev_handle != NULL)
+      dlclose(libudev_handle);
 }
+                                                                       /*}}}*/