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);
267 std::string mountpoint = attachPoint().asString();
268 if( !isUseableAttachPoint(attachPoint()))
270 mountpoint = createAttachPoint().asString();
271 if( mountpoint.empty())
272 ZYPP_THROW( MediaBadAttachPointException(url()));
273 setAttachPoint( mountpoint, true);
276 string options = _url.getQueryParam("mountoptions");
282 if( !media->bdir.empty())
285 mount.mount(media->bdir, mountpoint, "none", options);
289 mount.mount(_device, mountpoint, _filesystem, options);
292 setMediaSource(media);
294 // wait for /etc/mtab update ...
295 // (shouldn't be needed)
298 while( !(mountsucceeded=isAttached()) && --limit)
305 setMediaSource(MediaSourceRef());
308 mount.umount(attachPoint().asString());
310 catch (const MediaException & excpt_r)
312 ZYPP_CAUGHT(excpt_r);
314 ZYPP_THROW(MediaMountException(
315 "Unable to verify that the media was mounted",
321 ///////////////////////////////////////////////////////////////////
323 // METHOD NAME : MediaDISK::isAttached
324 // METHOD TYPE : bool
326 // DESCRIPTION : Override check if media is attached.
329 MediaDISK::isAttached() const
331 return checkAttached(false);
334 ///////////////////////////////////////////////////////////////////
337 // METHOD NAME : MediaDISK::releaseFrom
338 // METHOD TYPE : PMError
340 // DESCRIPTION : Asserted that media is attached.
342 void MediaDISK::releaseFrom( const std::string & ejectDev )
344 AttachedMedia am( attachedMedia());
345 if(am.mediaSource && am.mediaSource->iown)
348 mount.umount(attachPoint().asString());
352 ///////////////////////////////////////////////////////////////////
354 // METHOD NAME : MediaDISK::getFile
355 // METHOD TYPE : PMError
357 // DESCRIPTION : Asserted that media is attached.
359 void MediaDISK::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
361 MediaHandler::getFile( filename, expectedFileSize_r );
364 ///////////////////////////////////////////////////////////////////
366 // METHOD NAME : MediaDISK::getDir
367 // METHOD TYPE : PMError
369 // DESCRIPTION : Asserted that media is attached.
371 void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const
373 MediaHandler::getDir( dirname, recurse_r );
376 ///////////////////////////////////////////////////////////////////
379 // METHOD NAME : MediaDISK::getDirInfo
380 // METHOD TYPE : PMError
382 // DESCRIPTION : Asserted that media is attached and retlist is empty.
384 void MediaDISK::getDirInfo( std::list<std::string> & retlist,
385 const Pathname & dirname, bool dots ) const
387 MediaHandler::getDirInfo( retlist, dirname, dots );
390 ///////////////////////////////////////////////////////////////////
393 // METHOD NAME : MediaDISK::getDirInfo
394 // METHOD TYPE : PMError
396 // DESCRIPTION : Asserted that media is attached and retlist is empty.
398 void MediaDISK::getDirInfo( filesystem::DirContent & retlist,
399 const Pathname & dirname, bool dots ) const
401 MediaHandler::getDirInfo( retlist, dirname, dots );
404 bool MediaDISK::getDoesFileExist( const Pathname & filename ) const
406 return MediaHandler::getDoesFileExist( filename );
411 // vim: set ts=8 sts=2 sw=2 ai noet: