]> git.saurik.com Git - apt.git/commitdiff
[ABI] merged the libudev-dlopen branch, this allows to pass
authorMichael Vogt <michael.vogt@ubuntu.com>
Thu, 23 Jul 2009 08:41:38 +0000 (10:41 +0200)
committerMichael Vogt <michael.vogt@ubuntu.com>
Thu, 23 Jul 2009 08:41:38 +0000 (10:41 +0200)
"apt-udev-auto" to Acquire::Cdrom::mount and the cdrom method will
dynamically find/mount the cdrom device (if libhal is available)

apt-pkg/cdrom.cc
apt-pkg/cdrom.h
apt-pkg/contrib/cdromutl.cc
apt-pkg/contrib/cdromutl.h
apt-pkg/makefile
debian/changelog
methods/cdrom.cc
methods/makefile
test/makefile
test/test_udevcdrom.cc [new file with mode: 0644]

index 8796805bbab301af77679a7c31aeaf5c7b021c04..72d8e4d4174af464d9c9c8ddc6f9361f20eb0441 100644 (file)
@@ -16,7 +16,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <algorithm>
-
+#include <dlfcn.h>
 
 #include "indexcopy.h"
 
@@ -840,3 +840,87 @@ bool pkgCdrom::Add(pkgCdromStatus *log)                                    /*{{{*/
    return true;
 }
                                                                        /*}}}*/
+pkgUdevCdromDevices::pkgUdevCdromDevices()                                     /*{{{*/
+   : libudev_handle(NULL)
+{
+
+}
+                                                                       /*}}}*/
+
+bool
+pkgUdevCdromDevices::Dlopen()                                          /*{{{*/
+{
+   // alread open
+   if(libudev_handle != NULL)
+      return true;
+
+   // see if we can get libudev
+   void *h = ::dlopen("libudev.so.0", RTLD_LAZY);
+   if(h == NULL)
+      return false;
+
+   // get the pointers to the udev structs
+   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_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");
+   udev_enumerate_get_udev = (udev* (*)(udev_enumerate*))dlsym(h, "udev_enumerate_get_udev");
+   udev_list_entry_get_name = (const char* (*)(udev_list_entry*))dlsym(h, "udev_list_entry_get_name");
+   udev_device_get_devnode = (const char* (*)(udev_device*))dlsym(h, "udev_device_get_devnode");
+   udev_enumerate_new = (udev_enumerate* (*)(udev*))dlsym(h, "udev_enumerate_new");
+   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");
+
+   return true;
+}
+                                                                       /*}}}*/
+vector<CdromDevice>
+pkgUdevCdromDevices::Scan()                                             /*{{{*/
+{
+   vector<CdromDevice> cdrom_devices;
+   struct udev_enumerate *enumerate;
+   struct udev_list_entry *l, *devices;
+   struct udev *udev_ctx;
+
+   if(libudev_handle == NULL)
+      return cdrom_devices;
+
+   udev_ctx = udev_new();
+   enumerate = udev_enumerate_new (udev_ctx);
+   udev_enumerate_add_match_property(enumerate, "ID_CDROM", "1");
+
+   udev_enumerate_scan_devices (enumerate);
+   devices = udev_enumerate_get_list_entry (enumerate);
+   for (l = devices; l != NULL; l = udev_list_entry_get_next (l))
+   {
+      CdromDevice cdrom;
+      struct udev_device *udevice;
+      udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), udev_list_entry_get_name (l));
+      if (udevice == NULL)
+        continue;
+      const char* devnode = udev_device_get_devnode(udevice);
+      const char* mountpath = udev_device_get_property_value(udevice, "FSTAB_DIR");
+
+      // fill in the struct
+      cdrom.DeviceName = string(devnode);
+      if (mountpath) {
+        cdrom.MountPath = mountpath;
+        string s = string(mountpath);
+        cdrom.Mounted = IsMounted(s);
+      } else {
+        cdrom.Mounted = false;
+        cdrom.MountPath = "";
+      }
+      cdrom_devices.push_back(cdrom);
+   } 
+   return cdrom_devices;
+}
+                                                                       /*}}}*/
+
+pkgUdevCdromDevices::~pkgUdevCdromDevices()                             /*{{{*/
+{ 
+   dlclose(libudev_handle);
+}
+                                                                       /*}}}*/
index 608cb0e2fa5fa993785f909691c1c9fdbb413ef9..14ca1d8104dc163136e02a68426fca9a0283fdc6 100644 (file)
@@ -67,4 +67,41 @@ class pkgCdrom                                                               /*{{{*/
 };
                                                                        /*}}}*/
 
+
+// class that uses libudev to find cdrom devices dynamically
+struct CdromDevice                                                     /*{{{*/
+{
+   string DeviceName;
+   bool Mounted;
+   string MountPath;
+};
+                                                                       /*}}}*/
+class pkgUdevCdromDevices                                              /*{{{*/
+{
+ protected:
+   // libudev dlopen stucture
+   void *libudev_handle;
+   struct udev* (*udev_new)(void);
+   int (*udev_enumerate_add_match_property)(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
+   int (*udev_enumerate_scan_devices)(struct udev_enumerate *udev_enumerate);
+   struct udev_list_entry* (*udev_enumerate_get_list_entry)(struct udev_enumerate *udev_enumerate);
+   struct udev_device* (*udev_device_new_from_syspath)(struct udev *udev, const char *syspath);
+   struct udev* (*udev_enumerate_get_udev)(struct udev_enumerate *udev_enumerate);
+   const char* (*udev_list_entry_get_name)(struct udev_list_entry *list_entry);
+   const char* (*udev_device_get_devnode)(struct udev_device *udev_device);
+   struct udev_enumerate *(*udev_enumerate_new) (struct udev *udev);
+   struct udev_list_entry *(*udev_list_entry_get_next)(struct udev_list_entry *list_entry);
+   const char* (*udev_device_get_property_value)(struct udev_device *udev_device, const char *key);
+   // end libudev dlopen
+   
+ public:
+   pkgUdevCdromDevices();
+   virtual ~pkgUdevCdromDevices();
+
+   // try to open 
+   bool Dlopen();
+   vector<CdromDevice> Scan();
+};
+                                                                       /*}}}*/
+
 #endif
index b6524a1785f48e0f258aaf2630460d617377dc55..0cf9697acd48aedfcf1584bc6ba228c22f1ed288 100644 (file)
@@ -98,7 +98,7 @@ bool UnmountCdrom(string Path)
 // MountCdrom - Mount a cdrom                                          /*{{{*/
 // ---------------------------------------------------------------------
 /* We fork mount and drop all messages */
-bool MountCdrom(string Path)
+bool MountCdrom(string Path, string DeviceName)
 {
    if (IsMounted(Path) == true)
       return true;
@@ -122,8 +122,15 @@ bool MountCdrom(string Path)
       {
         const char *Args[10];
         Args[0] = "mount";
-        Args[1] = Path.c_str();
-        Args[2] = 0;
+        if (DeviceName == "") 
+        {
+           Args[1] = Path.c_str();
+           Args[2] = 0;
+        } else {
+           Args[1] = DeviceName.c_str();
+           Args[2] = Path.c_str();
+           Args[3] = 0;
+        }
         execvp(Args[0],(char **)Args);      
         _exit(100);
       }      
index f24bb8c704fdb85ee1d2447b74a0b3b8998a3fdd..9d14249c53b71fbcfa9d0051dfe60ab308c1ba03 100644 (file)
@@ -14,7 +14,8 @@
 
 using std::string;
 
-bool MountCdrom(string Path);
+// mount cdrom, DeviceName (e.g. /dev/sr0) is optional
+bool MountCdrom(string Path, string DeviceName="");
 bool UnmountCdrom(string Path);
 bool IdentCdrom(string CD,string &Res,unsigned int Version = 2);
 bool IsMounted(string &Path);
index 059f8532bcca95fc38cf8689a5508556d4288f67..92ef58967a98f1183384b5b02746710530ee220f 100644 (file)
@@ -15,7 +15,7 @@ LIBRARY=apt-pkg
 LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
 MAJOR=4.8
 MINOR=0
-SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil
+SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil -ldl
 APT_DOMAIN:=libapt-pkg$(MAJOR)
 
 # Source code for the contributed non-core things
index ff1483dfc491b824c05c2ada045f44dd44c2dbcc..30edf07577cdac9047e57607397389912299e7ba 100644 (file)
@@ -96,6 +96,9 @@ apt (0.7.22) UNRELEASED; urgency=low
   * doc/apt.conf.5.xml:
     - merged patch from AurĂ©lien Couderc to improve the text
       (thanks!)
+  * [ABI] merged the libudev-dlopen branch, this allows to pass
+    "apt-udev-auto" to Acquire::Cdrom::mount and the cdrom method will  
+    dynamically find/mount the cdrom device (if libhal is available)
 
   [ Julian Andres Klode ]
   * apt-pkg/contrib/configuration.cc: Fix a small memory leak in
index 601bc11c9039037fe94b3c78fb54d67d94d2c63d..9802eb46ceb4ffd0ca7b9c33229216fde56e499b 100644 (file)
@@ -9,6 +9,7 @@
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
 #include <apt-pkg/acquire-method.h>
+#include <apt-pkg/cdrom.h>
 #include <apt-pkg/cdromutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
@@ -17,6 +18,7 @@
 
 #include <sys/stat.h>
 #include <unistd.h>
+#include <dlfcn.h>
 
 #include <iostream>
 #include <apti18n.h>
@@ -27,15 +29,20 @@ using namespace std;
 class CDROMMethod : public pkgAcqMethod
 {
    bool DatabaseLoaded;
+   bool Debug;
+
    ::Configuration Database;
    string CurrentID;
    string CDROM;
    bool MountedByApt;
-   
+   pkgUdevCdromDevices UdevCdroms;
+   bool IsCorrectCD(URI want, string MountPath);
+   bool AutoDetectAndMount(URI);
    virtual bool Fetch(FetchItem *Itm);
    string GetID(string Name);
    virtual void Exit();
-   
+      
    public:
    
    CDROMMethod();
@@ -50,14 +57,15 @@ CDROMMethod::CDROMMethod() : pkgAcqMethod("1.0",SingleInstance | LocalOnly |
                                           DatabaseLoaded(false), 
                                           MountedByApt(false)
 {
+   UdevCdroms.Dlopen();
 };
                                                                        /*}}}*/
 // CDROMMethod::Exit - Unmount the disc if necessary                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 void CDROMMethod::Exit()
-{
-   if (MountedByApt == true)
+{ 
+  if (MountedByApt == true)
       UnmountCdrom(CDROM);
 }
                                                                        /*}}}*/
@@ -81,16 +89,94 @@ string CDROMMethod::GetID(string Name)
    return string();
 }
                                                                        /*}}}*/
+// CDROMMethod::AutoDetectAndMount                                      /*{{{*/
+// ---------------------------------------------------------------------
+/* Modifies class varaiable CDROM to the mountpoint */
+bool CDROMMethod::AutoDetectAndMount(URI Get)
+{
+   vector<struct CdromDevice> v = UdevCdroms.Scan();
+
+   // first check if its mounted somewhere already
+   for (unsigned int i=0; i < v.size(); i++)
+   {
+      if (v[i].Mounted)
+      {
+        if (Debug)
+           clog << "Checking mounted cdrom device " << v[i].DeviceName << endl;
+        if (IsCorrectCD(Get, v[i].MountPath))
+        {
+           CDROM = v[i].MountPath;
+           return true;
+        }
+      }
+   }
+
+   // we are not supposed to mount, exit
+   if (_config->FindB("APT::CDROM::NoMount",false) == true)
+      return false;
+
+   // check if we have the mount point
+   if (!FileExists("/media/apt"))
+      mkdir("/media/apt", 0755);
+
+   // now try mounting
+   for (unsigned int i=0; i < v.size(); i++)
+   {
+      if (!v[i].Mounted)
+      {
+        if(MountCdrom("/media/apt", v[i].DeviceName)) 
+        {
+           if (IsCorrectCD(Get, "/media/apt"))
+           {
+              MountedByApt = true;
+              CDROM = "/media/apt";
+              return true;
+           } else {
+              UnmountCdrom("/media/apt");
+           }
+        }
+      }
+   }
+
+   return false;
+}
+                                                                       /*}}}*/
+// CDROMMethod::IsCorrectCD                                             /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool CDROMMethod::IsCorrectCD(URI want, string MountPath)
+{
+   string NewID;
+
+   for (unsigned int Version = 2; Version != 0; Version--)
+   {
+      if (IdentCdrom(MountPath,NewID,Version) == false)
+        return false;
+      
+      if (Debug)
+        clog << "ID " << Version << " " << NewID << endl;
+      
+      // A hit
+      if (Database.Find("CD::" + NewID) == want.Host)
+        return true;
+   }
+   
+   return false;
+}
+                                                                       /*}}}*/
 // CDROMMethod::Fetch - Fetch a file                                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 bool CDROMMethod::Fetch(FetchItem *Itm)
 {
+   FetchResult Res;
+
    URI Get = Itm->Uri;
    string File = Get.Path;
-   FetchResult Res;
+   Debug = _config->FindB("Debug::Acquire::cdrom", false);
 
-   bool Debug = _config->FindB("Debug::Acquire::cdrom",false);
+   if (Debug)
+      clog << "CDROMMethod::Fetch " << Itm->Uri << endl;
 
    /* All IMS queries are returned as a hit, CDROMs are readonly so 
       time stamps never change */
@@ -126,38 +212,31 @@ bool CDROMMethod::Fetch(FetchItem *Itm)
    }
 
    // We already have a CD inserted, but it is the wrong one
-   if (CurrentID.empty() == false && Database.Find("CD::" + CurrentID) != Get.Host)
+   if (CurrentID.empty() == false && 
+       CurrentID != "FAIL" &&
+       Database.Find("CD::" + CurrentID) != Get.Host)
    {
       Fail(_("Wrong CD-ROM"),true);
       return true;
    }
-   
+
    CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
+   if (Debug)
+      clog << "Looking for CDROM at " << CDROM << endl;
+
    if (CDROM[0] == '.')
       CDROM= SafeGetCWD() + '/' + CDROM;
    string NewID;
+
    while (CurrentID.empty() == true)
    {
-      bool Hit = false;
+      if (CDROM == "apt-udev-auto/") 
+        AutoDetectAndMount(Get);
+
       if(!IsMounted(CDROM))
         MountedByApt = MountCdrom(CDROM);
-      for (unsigned int Version = 2; Version != 0; Version--)
-      {
-        if (IdentCdrom(CDROM,NewID,Version) == false)
-           return false;
-        
-        if (Debug == true)
-           clog << "ID " << Version << " " << NewID << endl;
       
-        // A hit
-        if (Database.Find("CD::" + NewID) == Get.Host)
-        {
-           Hit = true;
-           break;
-        }       
-      }
-
-      if (Hit == true)
+      if (IsCorrectCD(Get, CDROM))
         break;
         
       // I suppose this should prompt somehow?
index 589f9fa1c649284d237b1eb052550a0b699c7513..134166ba32f12a39c992d1a8d1fa730e378b2df1 100644 (file)
@@ -40,7 +40,7 @@ include $(PROGRAM_H)
 
 # The cdrom method
 PROGRAM=cdrom
-SLIBS = -lapt-pkg $(INTLLIBS)
+SLIBS = -lapt-pkg -ldl $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 SOURCE = cdrom.cc
 include $(PROGRAM_H)
index a9dbdc34dfb9935ef92a20f96373b23a3cff3c14..fb9123d0a1382207148c1053e5a4246e4077c8a8 100644 (file)
@@ -68,6 +68,12 @@ SLIBS = -lapt-pkg
 SOURCE = hash.cc
 include $(PROGRAM_H)
 
+# Program for testing udevcdrom
+PROGRAM=test_udevcdrom
+SLIBS = -lapt-pkg 
+SOURCE = test_udevcdrom.cc
+include $(PROGRAM_H)
+
 # Program for checking rpm versions
 PROGRAM=rpmver
 SLIBS = -lapt-pkg -lrpm
diff --git a/test/test_udevcdrom.cc b/test/test_udevcdrom.cc
new file mode 100644 (file)
index 0000000..e65c7a2
--- /dev/null
@@ -0,0 +1,19 @@
+#include <apt-pkg/cdrom.h>
+#include <stdio.h>
+#include <assert.h>
+
+int main()
+{
+   int i;
+   pkgUdevCdromDevices c;
+   assert(c.Dlopen());
+
+   vector<CdromDevice> l;
+   l = c.Scan();
+   assert(l.size() > 0);
+   for (i=0;i<l.size();i++)
+      std::cerr << l[i].DeviceName << " " 
+               << l[i].Mounted << " " 
+               << l[i].MountPath << std::endl;
+   
+}