1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaDISK.cc
13 #include "zypp/base/Logger.h"
14 #include "zypp/base/String.h"
15 #include "zypp/media/Mount.h"
16 #include "zypp/media/MediaDISK.h"
17 #include "zypp/media/MediaManager.h"
23 #include <sys/types.h>
24 #include <sys/mount.h>
29 ** verify devices names as late as possible (while attach)
31 #define DELAYED_VERIFY 1
38 ///////////////////////////////////////////////////////////////////
40 // CLASS NAME : MediaDISK
42 ///////////////////////////////////////////////////////////////////
44 ///////////////////////////////////////////////////////////////////
47 // METHOD NAME : MediaDISK::MediaDISK
48 // METHOD TYPE : Constructor
52 MediaDISK::MediaDISK( const Url & url_r,
53 const Pathname & attach_point_hint_r )
54 : MediaHandler( url_r, attach_point_hint_r,
55 url_r.getPathName(), // urlpath below attachpoint
56 false ) // does_download
58 MIL << "MediaDISK::MediaDISK(" << url_r << ", " << attach_point_hint_r << ")" << endl;
60 _device = Pathname(_url.getQueryParam("device")).asString();
63 ERR << "Media url does not contain a device specification" << std::endl;
64 ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
67 DBG << "Verify of " << _device << " delayed" << std::endl;
69 if( !verifyIfDiskVolume( _device))
71 ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
75 _filesystem = _url.getQueryParam("filesystem");
76 if(_filesystem.empty())
81 ///////////////////////////////////////////////////////////////////
83 // METHOD NAME : MediaDISK::verifyIfDiskVolume
86 // DESCRIPTION : Check if specified device file name is
87 // a disk volume device or throw an error.
89 bool MediaDISK::verifyIfDiskVolume(const Pathname &dev_name)
91 if( dev_name.empty() ||
92 dev_name.asString().compare(0, sizeof("/dev/")-1, "/dev/"))
94 ERR << "Specified device name " << dev_name
95 << " is not allowed" << std::endl;
99 PathInfo dev_info(dev_name);
100 if( !dev_info.isBlk())
102 ERR << "Specified device name " << dev_name
103 << " is not a block device" << std::endl;
107 // check if a volume using /dev/disk/by-uuid links first
109 Pathname dpath("/dev/disk/by-uuid");
110 std::list<Pathname> dlist;
111 if( zypp::filesystem::readdir(dlist, dpath) == 0)
113 std::list<Pathname>::const_iterator it;
114 for(it = dlist.begin(); it != dlist.end(); ++it)
116 PathInfo vol_info(*it);
117 if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
118 vol_info.devMinor() == dev_info.devMinor())
120 DBG << "Specified device name " << dev_name
121 << " is a volume (disk/by-uuid link "
122 << vol_info.path() << ")"
130 // check if a volume using /dev/disk/by-label links
131 // (e.g. vbd mapped volumes in a XEN vm)
133 Pathname dpath("/dev/disk/by-label");
134 std::list<Pathname> dlist;
135 if( zypp::filesystem::readdir(dlist, dpath) == 0)
137 std::list<Pathname>::const_iterator it;
138 for(it = dlist.begin(); it != dlist.end(); ++it)
140 PathInfo vol_info(*it);
141 if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
142 vol_info.devMinor() == dev_info.devMinor())
144 DBG << "Specified device name " << dev_name
145 << " is a volume (disk/by-label link "
146 << vol_info.path() << ")"
154 // check if a filesystem volume using the 'blkid' tool
155 // (there is no /dev/disk link for some of them)
156 ExternalProgram::Arguments args;
157 args.push_back( "blkid" );
158 args.push_back( "-p" );
159 args.push_back( dev_name.asString() );
161 ExternalProgram cmd( args, ExternalProgram::Stderr_To_Stdout );
163 if ( cmd.close() != 0 )
165 ERR << cmd.execError() << endl
166 << "Specified device name " << dev_name
167 << " is not a usable disk volume"
174 ///////////////////////////////////////////////////////////////////
177 // METHOD NAME : MediaDISK::attachTo
178 // METHOD TYPE : PMError
180 // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory.
182 void MediaDISK::attachTo(bool next)
185 ZYPP_THROW(MediaNotSupportedException(url()));
187 // do mount --bind <partition>/<dir> to <to>
188 // mount /dev/<partition> /tmp_mount
189 // mount /tmp_mount/<dir> <to> --bind -o ro
190 // FIXME: try all filesystems
193 ZYPP_THROW(MediaBadUrlEmptyDestinationException(url()));
195 PathInfo dev_info(_device);
196 if(!dev_info.isBlk())
197 ZYPP_THROW(MediaBadUrlEmptyDestinationException(url()));
199 DBG << "Verifying " << _device << " ..." << std::endl;
200 if( !verifyIfDiskVolume( _device))
202 ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url));
206 if(_filesystem.empty())
207 ZYPP_THROW(MediaBadUrlEmptyFilesystemException(url()));
209 MediaSourceRef media( new MediaSource(
210 "disk", _device, dev_info.devMajor(), dev_info.devMinor()
212 AttachedMedia ret( findAttachedMedia( media));
214 if( ret.mediaSource &&
216 !ret.attachPoint->empty())
218 DBG << "Using a shared media "
219 << ret.mediaSource->name
221 << ret.attachPoint->path
225 setAttachPoint(ret.attachPoint);
226 setMediaSource(ret.mediaSource);
230 MediaManager manager;
231 MountEntries entries( manager.getMountEntries());
232 MountEntries::const_iterator e;
233 for( e = entries.begin(); e != entries.end(); ++e)
235 bool is_device = false;
236 std::string dev_path(Pathname(e->src).asString());
239 if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
240 dev_info(e->src) && dev_info.isBlk())
245 if( is_device && media->maj_nr == dev_info.devMajor() &&
246 media->min_nr == dev_info.devMinor())
248 AttachPointRef ap( new AttachPoint(e->dir, false));
249 AttachedMedia am( media, ap);
251 DBG << "Using a system mounted media "
257 media->iown = false; // mark attachment as foreign
259 setMediaSource(media);
266 if( !isUseableAttachPoint( attachPoint() ) )
268 setAttachPoint( createAttachPoint(), true );
270 std::string mountpoint( attachPoint().asString() );
273 string options = _url.getQueryParam("mountoptions");
279 if( !media->bdir.empty())
282 mount.mount(media->bdir, mountpoint, "none", options);
286 mount.mount(_device, mountpoint, _filesystem, options);
289 setMediaSource(media);
291 // wait for /etc/mtab update ...
292 // (shouldn't be needed)
295 while( !(mountsucceeded=isAttached()) && --limit)
302 setMediaSource(MediaSourceRef());
305 mount.umount(attachPoint().asString());
307 catch (const MediaException & excpt_r)
309 ZYPP_CAUGHT(excpt_r);
311 ZYPP_THROW(MediaMountException(
312 "Unable to verify that the media was mounted",
318 ///////////////////////////////////////////////////////////////////
320 // METHOD NAME : MediaDISK::isAttached
321 // METHOD TYPE : bool
323 // DESCRIPTION : Override check if media is attached.
326 MediaDISK::isAttached() const
328 return checkAttached(false);
331 ///////////////////////////////////////////////////////////////////
334 // METHOD NAME : MediaDISK::releaseFrom
335 // METHOD TYPE : PMError
337 // DESCRIPTION : Asserted that media is attached.
339 void MediaDISK::releaseFrom( const std::string & ejectDev )
341 AttachedMedia am( attachedMedia());
342 if(am.mediaSource && am.mediaSource->iown)
345 mount.umount(attachPoint().asString());
349 ///////////////////////////////////////////////////////////////////
351 // METHOD NAME : MediaDISK::getFile
352 // METHOD TYPE : PMError
354 // DESCRIPTION : Asserted that media is attached.
356 void MediaDISK::getFile (const Pathname & filename) const
358 MediaHandler::getFile( filename );
361 ///////////////////////////////////////////////////////////////////
363 // METHOD NAME : MediaDISK::getDir
364 // METHOD TYPE : PMError
366 // DESCRIPTION : Asserted that media is attached.
368 void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const
370 MediaHandler::getDir( dirname, recurse_r );
373 ///////////////////////////////////////////////////////////////////
376 // METHOD NAME : MediaDISK::getDirInfo
377 // METHOD TYPE : PMError
379 // DESCRIPTION : Asserted that media is attached and retlist is empty.
381 void MediaDISK::getDirInfo( std::list<std::string> & retlist,
382 const Pathname & dirname, bool dots ) const
384 MediaHandler::getDirInfo( retlist, dirname, dots );
387 ///////////////////////////////////////////////////////////////////
390 // METHOD NAME : MediaDISK::getDirInfo
391 // METHOD TYPE : PMError
393 // DESCRIPTION : Asserted that media is attached and retlist is empty.
395 void MediaDISK::getDirInfo( filesystem::DirContent & retlist,
396 const Pathname & dirname, bool dots ) const
398 MediaHandler::getDirInfo( retlist, dirname, dots );
401 bool MediaDISK::getDoesFileExist( const Pathname & filename ) const
403 return MediaHandler::getDoesFileExist( filename );
408 // vim: set ts=8 sts=2 sw=2 ai noet: