#include "zypp/media/MediaISO.h"
+
+#define LOSETUP_TOOL_PATH "/sbin/losetup"
+
+using std::string;
using std::endl;
//////////////////////////////////////////////////////////////////////
}
// ---------------------------------------------------------------
+ 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)
- 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())
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,
}
// ---------------------------------------------------------------
- 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);
}
// ---------------------------------------------------------------