return str << form(_(" SSL certificate problem, verify that the CA cert is OK for '%s'."), _url.c_str()) << endl;
return str << _msg << endl;
}
+
+ std::ostream & MediaNoLoopDeviceException::dumpOn( std::ostream & str ) const
+ {
+ if (msg().empty())
+ return str << form(_("Cannot find available loop device to mount the image file from '%s'"), _url.c_str()) << endl;
+ return str << msg() << endl;
+ }
+
/////////////////////////////////////////////////////////////////
} // namespace media
} // namespace zypp
std::string _url;
std::string _msg;
};
+
+ /**
+ * Thrown if /sbin/losetup fails to find an unused loop device for mounting
+ * an .iso image.
+ *
+ * UI hint: tell user to check permissions to read /dev/loop# or enablement
+ * of support for loop devices.
+ *
+ * \see MediaISO
+ */
+ class MediaNoLoopDeviceException : public MediaException
+ {
+ public:
+ MediaNoLoopDeviceException(const Url & url_r, const std::string & msg = "")
+ : MediaException(msg)
+ , _url(url_r.asString())
+ {}
+ virtual ~MediaNoLoopDeviceException() throw() {};
+ protected:
+ virtual std::ostream & dumpOn( std::ostream & str ) const;
+ std::string _url;
+ };
/////////////////////////////////////////////////////////////////
} // namespace media
} // namespace zypp
}
// differs
}
- else // mixed cases:
- {
- // Type ISO: Since 11.1 mtab might contain the name of
- // the loop device instead of the iso file:
- if ( ref.mediaSource->type == "iso"
- && str::hasPrefix( Pathname(e->src).asString(), "/dev/loop" )
- && ref.attachPoint->path == Pathname(e->dir) )
- {
- DBG << "Found bound media "
- << ref.mediaSource->asString()
- << " in the mount table as " << e->src << std::endl;
- _isAttached = true;
- break;
- }
- }
}
if( !_isAttached)
/** \file zypp/media/MediaISO.cc
*
*/
-#include "zypp/media/MediaISO.h"
+#include <iostream>
+
#include "zypp/base/Logger.h"
#include "zypp/media/Mount.h"
-#include <iostream>
+#include "zypp/media/MediaISO.h"
+
+
+#define LOSETUP_TOOL_PATH "/sbin/losetup"
+
+using std::string;
+using std::endl;
//////////////////////////////////////////////////////////////////////
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)
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)
+
+ MediaSourceRef media( new MediaSource("iso", loopdev));
+ PathInfo dinfo(loopdev);
+ if( dinfo.isBlk())
+ {
+ media->maj_nr = dinfo.major();
+ media->min_nr = dinfo.minor();
+ }
+ else
+ ERR << loopdev << " is not a block device" << endl;
AttachedMedia ret( findAttachedMedia( media));
if( ret.mediaSource &&
setAttachPoint( mountpoint, true);
}
- std::string mountopts("ro,loop");
+ std::string mountopts("ro,loop=" + loopdev);
Mount mount;
mount.mount(isofile.asString(), mountpoint,