Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / media / MediaISO.cc
index e7f71fc..9c07c1d 100644 (file)
 
 #include "zypp/media/MediaISO.h"
 
+
+#define LOSETUP_TOOL_PATH "/sbin/losetup"
+
+using std::string;
 using std::endl;
 
 //////////////////////////////////////////////////////////////////////
@@ -145,6 +149,32 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
+    string MediaISO::findUnusedLoopDevice()
+    {
+      const char* argv[] =
+      {
+        LOSETUP_TOOL_PATH,
+        "-f",
+        NULL
+      };
+      ExternalProgram losetup(argv, ExternalProgram::Stderr_To_Stdout);
+
+      string out = losetup.receiveLine();
+      string device = out.substr(0, out.size() - 1); // remove the trailing endl
+      for(; out.length(); out = losetup.receiveLine())
+        DBG << "losetup: " << out;
+
+      if (losetup.close() != 0)
+      {
+        ERR << LOSETUP_TOOL_PATH " failed to find an unused loop device." << std::endl;
+        ZYPP_THROW(MediaNoLoopDeviceException(_url));
+      }
+
+      DBG << "found " << device << endl;
+      return device;
+    }
+
+    // ---------------------------------------------------------------
     void MediaISO::attachTo(bool next)
     {
       if(next)
@@ -185,9 +215,20 @@ namespace zypp
         ZYPP_THROW(MediaNotSupportedException(_url));
       }
 
-      MediaSourceRef media( new MediaSource("iso", isofile.asString() ) );
+      //! \todo make this thread-safe - another thread might pick up the same device
+      string loopdev = findUnusedLoopDevice(); // (bnc #428009)
 
-      AttachedMedia  ret( findAttachedMedia(media));
+      MediaSourceRef media( new MediaSource("iso",  loopdev));
+      PathInfo dinfo(loopdev);
+      if( dinfo.isBlk())
+      {
+        media->maj_nr = dinfo.devMajor();
+        media->min_nr = dinfo.devMinor();
+      }
+      else
+        ERR << loopdev << " is not a block device" << endl;
+
+      AttachedMedia  ret( findAttachedMedia( media));
       if( ret.mediaSource &&
           ret.attachPoint &&
           !ret.attachPoint->empty())
@@ -203,16 +244,12 @@ namespace zypp
         return;
       }
 
-      std::string mountpoint = attachPoint().asString();
-      if( !isUseableAttachPoint(attachPoint()))
+      if( !isUseableAttachPoint( attachPoint() ) )
       {
-        mountpoint = createAttachPoint().asString();
-        if( mountpoint.empty())
-          ZYPP_THROW( MediaBadAttachPointException(url()));
-        setAttachPoint( mountpoint, true);
+       setAttachPoint( createAttachPoint(), true );
       }
-
-      std::string mountopts("ro,loop");
+      std::string mountpoint( attachPoint().asString() );
+      std::string mountopts("ro,loop=" + loopdev);
 
       Mount mount;
       mount.mount(isofile.asString(), mountpoint,
@@ -276,9 +313,9 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
-    void MediaISO::getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const
+    void MediaISO::getFile(const Pathname &filename) const
     {
-      MediaHandler::getFile(filename, expectedFileSize_r);
+      MediaHandler::getFile(filename);
     }
 
     // ---------------------------------------------------------------