| /_____||_| |_| |_| |
| |
\---------------------------------------------------------------------*/
-/** \file zypp/media/MediaDISK.h
+/** \file zypp/media/MediaDISK.cc
*
*/
-#include <iostream>
-
#include "zypp/base/Logger.h"
+#include "zypp/base/String.h"
#include "zypp/media/Mount.h"
#include "zypp/media/MediaDISK.h"
+#include "zypp/media/MediaManager.h"
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
#include <sys/types.h>
#include <sys/mount.h>
#include <errno.h>
#include <dirent.h>
+/*
+** verify devices names as late as possible (while attach)
+*/
+#define DELAYED_VERIFY 1
+
using namespace std;
namespace zypp {
url_r.getPathName(), // urlpath below attachpoint
false ) // does_download
{
+ MIL << "MediaDISK::MediaDISK(" << url_r << ", " << attach_point_hint_r << ")" << endl;
+
_device = Pathname(_url.getQueryParam("device")).asString();
+ if( _device.empty())
+ {
+ ERR << "Media url does not contain a device specification" << std::endl;
+ ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
+ }
+#if DELAYED_VERIFY
+ DBG << "Verify of " << _device << " delayed" << std::endl;
+#else
+ if( !verifyIfDiskVolume( _device))
+ {
+ ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
+ }
+#endif
+
_filesystem = _url.getQueryParam("filesystem");
if(_filesystem.empty())
_filesystem="auto";
- MIL << "MediaDISK::MediaDISK(" << url_r << ", " << attach_point_hint_r << ")" << endl;
+
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : MediaDISK::verifyIfDiskVolume
+ // METHOD TYPE : void
+ //
+ // DESCRIPTION : Check if specified device file name is
+ // a disk volume device or throw an error.
+ //
+ bool MediaDISK::verifyIfDiskVolume(const Pathname &dev_name)
+ {
+ if( dev_name.empty() ||
+ dev_name.asString().compare(0, sizeof("/dev/")-1, "/dev/"))
+ {
+ ERR << "Specified device name " << dev_name
+ << " is not allowed" << std::endl;
+ return false;
+ }
+
+ PathInfo dev_info(dev_name);
+ if( !dev_info.isBlk())
+ {
+ ERR << "Specified device name " << dev_name
+ << " is not a block device" << std::endl;
+ return false;
+ }
+
+ // check if a volume using /dev/disk/by-uuid links first
+ {
+ Pathname dpath("/dev/disk/by-uuid");
+ std::list<Pathname> dlist;
+ if( zypp::filesystem::readdir(dlist, dpath) == 0)
+ {
+ std::list<Pathname>::const_iterator it;
+ for(it = dlist.begin(); it != dlist.end(); ++it)
+ {
+ PathInfo vol_info(*it);
+ if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
+ vol_info.devMinor() == dev_info.devMinor())
+ {
+ DBG << "Specified device name " << dev_name
+ << " is a volume (disk/by-uuid link "
+ << vol_info.path() << ")"
+ << std::endl;
+ return true;
+ }
+ }
+ }
+ }
+
+ // check if a volume using /dev/disk/by-label links
+ // (e.g. vbd mapped volumes in a XEN vm)
+ {
+ Pathname dpath("/dev/disk/by-label");
+ std::list<Pathname> dlist;
+ if( zypp::filesystem::readdir(dlist, dpath) == 0)
+ {
+ std::list<Pathname>::const_iterator it;
+ for(it = dlist.begin(); it != dlist.end(); ++it)
+ {
+ PathInfo vol_info(*it);
+ if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
+ vol_info.devMinor() == dev_info.devMinor())
+ {
+ DBG << "Specified device name " << dev_name
+ << " is a volume (disk/by-label link "
+ << vol_info.path() << ")"
+ << std::endl;
+ return true;
+ }
+ }
+ }
+ }
+
+ // check if a filesystem volume using the 'blkid' tool
+ // (there is no /dev/disk link for some of them)
+ ExternalProgram::Arguments args;
+ args.push_back( "blkid" );
+ args.push_back( "-p" );
+ args.push_back( dev_name.asString() );
+
+ ExternalProgram cmd( args, ExternalProgram::Stderr_To_Stdout );
+ cmd >> DBG;
+ if ( cmd.close() != 0 )
+ {
+ ERR << cmd.execError() << endl
+ << "Specified device name " << dev_name
+ << " is not a usable disk volume"
+ << std::endl;
+ return false;
+ }
+ return true;
}
///////////////////////////////////////////////////////////////////
// mount /dev/<partition> /tmp_mount
// mount /tmp_mount/<dir> <to> --bind -o ro
// FIXME: try all filesystems
-
+
if(_device.empty())
ZYPP_THROW(MediaBadUrlEmptyDestinationException(url()));
-
+
PathInfo dev_info(_device);
if(!dev_info.isBlk())
ZYPP_THROW(MediaBadUrlEmptyDestinationException(url()));
+#if DELAYED_VERIFY
+ DBG << "Verifying " << _device << " ..." << std::endl;
+ if( !verifyIfDiskVolume( _device))
+ {
+ ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
+ }
+#endif
if(_filesystem.empty())
ZYPP_THROW(MediaBadUrlEmptyFilesystemException(url()));
MediaSourceRef media( new MediaSource(
- "disk", _device, dev_info.major(), dev_info.minor()
+ "disk", _device, dev_info.devMajor(), dev_info.devMinor()
));
AttachedMedia ret( findAttachedMedia( media));
return;
}
-
- Mount mount;
- std::string mountpoint = attachPoint().asString();
- if( !isUseableAttachPoint(attachPoint()))
+ MediaManager manager;
+ MountEntries entries( manager.getMountEntries());
+ MountEntries::const_iterator e;
+ for( e = entries.begin(); e != entries.end(); ++e)
+ {
+ bool is_device = false;
+ std::string dev_path(Pathname(e->src).asString());
+ PathInfo dev_info;
+
+ if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
+ dev_info(e->src) && dev_info.isBlk())
+ {
+ is_device = true;
+ }
+
+ if( is_device && media->maj_nr == dev_info.devMajor() &&
+ media->min_nr == dev_info.devMinor())
+ {
+ AttachPointRef ap( new AttachPoint(e->dir, false));
+ AttachedMedia am( media, ap);
+ {
+ DBG << "Using a system mounted media "
+ << media->name
+ << " attached on "
+ << ap->path
+ << endl;
+
+ media->iown = false; // mark attachment as foreign
+
+ setMediaSource(media);
+ setAttachPoint(ap);
+ return;
+ }
+ }
+ }
+
+ if( !isUseableAttachPoint( attachPoint() ) )
{
- mountpoint = createAttachPoint().asString();
- if( mountpoint.empty())
- ZYPP_THROW( MediaBadAttachPointException(url()));
- setAttachPoint( mountpoint, true);
+ setAttachPoint( createAttachPoint(), true );
}
+ std::string mountpoint( attachPoint().asString() );
+ Mount mount;
string options = _url.getQueryParam("mountoptions");
if(options.empty())
{
- options="ro";
+ options = "ro";
}
- mount.mount(_device,mountpoint,_filesystem,options);
+ if( !media->bdir.empty())
+ {
+ options += ",bind";
+ mount.mount(media->bdir, mountpoint, "none", options);
+ }
+ else
+ {
+ mount.mount(_device, mountpoint, _filesystem, options);
+ }
setMediaSource(media);
// wait for /etc/mtab update ...
// (shouldn't be needed)
- int limit = 10;
+ int limit = 3;
bool mountsucceeded;
- while( !(mountsucceeded=isAttached()) && limit--)
+ while( !(mountsucceeded=isAttached()) && --limit)
{
sleep(1);
}
bool
MediaDISK::isAttached() const
{
- return checkAttached(true);
+ return checkAttached(false);
}
///////////////////////////////////////////////////////////////////
//
// DESCRIPTION : Asserted that media is attached.
//
- void MediaDISK::releaseFrom( bool eject )
+ void MediaDISK::releaseFrom( const std::string & ejectDev )
{
- Mount mount;
- mount.umount(attachPoint().asString());
+ AttachedMedia am( attachedMedia());
+ if(am.mediaSource && am.mediaSource->iown)
+ {
+ Mount mount;
+ mount.umount(attachPoint().asString());
+ }
}
-
///////////////////////////////////////////////////////////////////
//
// METHOD NAME : MediaDISK::getFile
{
MediaHandler::getFile( filename );
}
-
+
///////////////////////////////////////////////////////////////////
//
// METHOD NAME : MediaDISK::getDir
{
MediaHandler::getDir( dirname, recurse_r );
}
-
+
///////////////////////////////////////////////////////////////////
//
//
{
MediaHandler::getDirInfo( retlist, dirname, dots );
}
-
+
///////////////////////////////////////////////////////////////////
//
//
MediaHandler::getDirInfo( retlist, dirname, dots );
}
+ bool MediaDISK::getDoesFileExist( const Pathname & filename ) const
+ {
+ return MediaHandler::getDoesFileExist( filename );
+ }
+
} // namespace media
} // namespace zypp
+// vim: set ts=8 sts=2 sw=2 ai noet: