libzypp  17.14.1
MediaDISK.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include "zypp/base/Logger.h"
14 #include "zypp/base/String.h"
15 #include "zypp/media/Mount.h"
16 #include "zypp/media/MediaDISK.h"
18 
19 #include <iostream>
20 #include <fstream>
21 #include <sstream>
22 
23 #include <sys/types.h>
24 #include <sys/mount.h>
25 #include <errno.h>
26 #include <dirent.h>
27 
28 /*
29 ** verify devices names as late as possible (while attach)
30 */
31 #define DELAYED_VERIFY 1
32 
33 using namespace std;
34 
35 namespace zypp {
36  namespace media {
37 
39  //
40  // CLASS NAME : MediaDISK
41  //
43 
45  //
46  //
47  // METHOD NAME : MediaDISK::MediaDISK
48  // METHOD TYPE : Constructor
49  //
50  // DESCRIPTION :
51  //
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
57  {
58  MIL << "MediaDISK::MediaDISK(" << url_r << ", " << attach_point_hint_r << ")" << endl;
59 
61  if( _device.empty())
62  {
63  ERR << "Media url does not contain a device specification" << std::endl;
65  }
66 #if DELAYED_VERIFY
67  DBG << "Verify of " << _device << " delayed" << std::endl;
68 #else
70  {
72  }
73 #endif
74 
75  _filesystem = _url.getQueryParam("filesystem");
76  if(_filesystem.empty())
77  _filesystem="auto";
78 
79  }
80 
82  //
83  // METHOD NAME : MediaDISK::verifyIfDiskVolume
84  // METHOD TYPE : void
85  //
86  // DESCRIPTION : Check if specified device file name is
87  // a disk volume device or throw an error.
88  //
90  {
91  if( dev_name.empty() ||
92  dev_name.asString().compare(0, sizeof("/dev/")-1, "/dev/"))
93  {
94  ERR << "Specified device name " << dev_name
95  << " is not allowed" << std::endl;
96  return false;
97  }
98 
99  PathInfo dev_info(dev_name);
100  if( !dev_info.isBlk())
101  {
102  ERR << "Specified device name " << dev_name
103  << " is not a block device" << std::endl;
104  return false;
105  }
106 
107  // check if a volume using /dev/disk/by-uuid links first
108  {
109  Pathname dpath("/dev/disk/by-uuid");
110  std::list<Pathname> dlist;
111  if( zypp::filesystem::readdir(dlist, dpath) == 0)
112  {
113  std::list<Pathname>::const_iterator it;
114  for(it = dlist.begin(); it != dlist.end(); ++it)
115  {
116  PathInfo vol_info(*it);
117  if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
118  vol_info.devMinor() == dev_info.devMinor())
119  {
120  DBG << "Specified device name " << dev_name
121  << " is a volume (disk/by-uuid link "
122  << vol_info.path() << ")"
123  << std::endl;
124  return true;
125  }
126  }
127  }
128  }
129 
130  // check if a volume using /dev/disk/by-label links
131  // (e.g. vbd mapped volumes in a XEN vm)
132  {
133  Pathname dpath("/dev/disk/by-label");
134  std::list<Pathname> dlist;
135  if( zypp::filesystem::readdir(dlist, dpath) == 0)
136  {
137  std::list<Pathname>::const_iterator it;
138  for(it = dlist.begin(); it != dlist.end(); ++it)
139  {
140  PathInfo vol_info(*it);
141  if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
142  vol_info.devMinor() == dev_info.devMinor())
143  {
144  DBG << "Specified device name " << dev_name
145  << " is a volume (disk/by-label link "
146  << vol_info.path() << ")"
147  << std::endl;
148  return true;
149  }
150  }
151  }
152  }
153 
154  // check if a filesystem volume using the 'blkid' tool
155  // (there is no /dev/disk link for some of them)
157  args.push_back( "blkid" );
158  args.push_back( "-p" );
159  args.push_back( dev_name.asString() );
160 
162  cmd >> DBG;
163  if ( cmd.close() != 0 )
164  {
165  ERR << cmd.execError() << endl
166  << "Specified device name " << dev_name
167  << " is not a usable disk volume"
168  << std::endl;
169  return false;
170  }
171  return true;
172  }
173 
175  //
176  //
177  // METHOD NAME : MediaDISK::attachTo
178  // METHOD TYPE : PMError
179  //
180  // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory.
181  //
182  void MediaDISK::attachTo(bool next)
183  {
184  if(next)
186  // FIXME
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
191 
192  if(_device.empty())
194 
195  PathInfo dev_info(_device);
196  if(!dev_info.isBlk())
198 #if DELAYED_VERIFY
199  DBG << "Verifying " << _device << " ..." << std::endl;
201  {
203  }
204 #endif
205 
206  if(_filesystem.empty())
208 
209  MediaSourceRef media( new MediaSource(
210  "disk", _device, dev_info.devMajor(), dev_info.devMinor()
211  ));
212  AttachedMedia ret( findAttachedMedia( media));
213 
214  if( ret.mediaSource &&
215  ret.attachPoint &&
216  !ret.attachPoint->empty())
217  {
218  DBG << "Using a shared media "
219  << ret.mediaSource->name
220  << " attached on "
221  << ret.attachPoint->path
222  << endl;
223 
227  return;
228  }
229 
230  MediaManager manager;
231  MountEntries entries( manager.getMountEntries());
232  MountEntries::const_iterator e;
233  for( e = entries.begin(); e != entries.end(); ++e)
234  {
235  bool is_device = false;
236  std::string dev_path(Pathname(e->src).asString());
237  PathInfo dev_info;
238 
239  if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
240  dev_info(e->src) && dev_info.isBlk())
241  {
242  is_device = true;
243  }
244 
245  if( is_device && media->maj_nr == dev_info.devMajor() &&
246  media->min_nr == dev_info.devMinor())
247  {
248  AttachPointRef ap( new AttachPoint(e->dir, false));
249  AttachedMedia am( media, ap);
250  {
251  DBG << "Using a system mounted media "
252  << media->name
253  << " attached on "
254  << ap->path
255  << endl;
256 
257  media->iown = false; // mark attachment as foreign
258 
259  setMediaSource(media);
260  setAttachPoint(ap);
261  return;
262  }
263  }
264  }
265 
267  {
269  }
270  std::string mountpoint( attachPoint().asString() );
271 
272  Mount mount;
273  string options = _url.getQueryParam("mountoptions");
274  if(options.empty())
275  {
276  options = "ro";
277  }
278 
279  if( !media->bdir.empty())
280  {
281  options += ",bind";
282  mount.mount(media->bdir, mountpoint, "none", options);
283  }
284  else
285  {
286  mount.mount(_device, mountpoint, _filesystem, options);
287  }
288 
289  setMediaSource(media);
290 
291  // wait for /etc/mtab update ...
292  // (shouldn't be needed)
293  int limit = 3;
294  bool mountsucceeded;
295  while( !(mountsucceeded=isAttached()) && --limit)
296  {
297  sleep(1);
298  }
299 
300  if( !mountsucceeded)
301  {
303  try
304  {
305  mount.umount(attachPoint().asString());
306  }
307  catch (const MediaException & excpt_r)
308  {
309  ZYPP_CAUGHT(excpt_r);
310  }
312  "Unable to verify that the media was mounted",
313  _device, mountpoint
314  ));
315  }
316  }
317 
319  //
320  // METHOD NAME : MediaDISK::isAttached
321  // METHOD TYPE : bool
322  //
323  // DESCRIPTION : Override check if media is attached.
324  //
325  bool
327  {
328  return checkAttached(false);
329  }
330 
332  //
333  //
334  // METHOD NAME : MediaDISK::releaseFrom
335  // METHOD TYPE : PMError
336  //
337  // DESCRIPTION : Asserted that media is attached.
338  //
339  void MediaDISK::releaseFrom( const std::string & ejectDev )
340  {
342  if(am.mediaSource && am.mediaSource->iown)
343  {
344  Mount mount;
345  mount.umount(attachPoint().asString());
346  }
347  }
348 
350  //
351  // METHOD NAME : MediaDISK::getFile
352  // METHOD TYPE : PMError
353  //
354  // DESCRIPTION : Asserted that media is attached.
355  //
356  void MediaDISK::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
357  {
358  MediaHandler::getFile( filename, expectedFileSize_r );
359  }
360 
362  //
363  // METHOD NAME : MediaDISK::getDir
364  // METHOD TYPE : PMError
365  //
366  // DESCRIPTION : Asserted that media is attached.
367  //
368  void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const
369  {
370  MediaHandler::getDir( dirname, recurse_r );
371  }
372 
374  //
375  //
376  // METHOD NAME : MediaDISK::getDirInfo
377  // METHOD TYPE : PMError
378  //
379  // DESCRIPTION : Asserted that media is attached and retlist is empty.
380  //
381  void MediaDISK::getDirInfo( std::list<std::string> & retlist,
382  const Pathname & dirname, bool dots ) const
383  {
384  MediaHandler::getDirInfo( retlist, dirname, dots );
385  }
386 
388  //
389  //
390  // METHOD NAME : MediaDISK::getDirInfo
391  // METHOD TYPE : PMError
392  //
393  // DESCRIPTION : Asserted that media is attached and retlist is empty.
394  //
396  const Pathname & dirname, bool dots ) const
397  {
398  MediaHandler::getDirInfo( retlist, dirname, dots );
399  }
400 
401  bool MediaDISK::getDoesFileExist( const Pathname & filename ) const
402  {
403  return MediaHandler::getDoesFileExist( filename );
404  }
405 
406  } // namespace media
407 } // namespace zypp
408 // vim: set ts=8 sts=2 sw=2 ai noet:
Attach point of a media source.
Definition: MediaSource.h:105
#define MIL
Definition: Logger.h:79
Interface to the mount program.
Definition: Mount.h:69
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
AttachedMedia attachedMedia() const
Returns the attached media.
Store and operate with byte count.
Definition: ByteCount.h:30
virtual void getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const override
Call concrete handler to provide file below attach point.
Definition: MediaDISK.cc:356
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition: MediaSource.h:124
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Ask media manager, if the specified path is already used as attach point or if there are another atta...
virtual bool isAttached() const override
True if media is attached.
Definition: MediaDISK.cc:326
Definition: Arch.h:344
std::string _device
Definition: MediaDISK.h:30
virtual void releaseFrom(const std::string &ejectDev) override
Call concrete handler to release the media.
Definition: MediaDISK.cc:339
virtual void getDir(const Pathname &dirname, bool recurse_r) const override
Call concrete handler to provide directory content (not recursive!) below attach point.
Definition: MediaDISK.cc:368
unsigned int devMinor() const
Definition: PathInfo.cc:252
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
#define ERR
Definition: Logger.h:81
std::vector< std::string > Arguments
void mount(const std::string &source, const std::string &target, const std::string &filesystem, const std::string &options, const Environment &environment=Environment())
mount device
Definition: Mount.cc:66
virtual bool getDoesFileExist(const Pathname &filename) const override
check if a file exists
Definition: MediaDISK.cc:401
virtual void getDirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const override
Call concrete handler to provide a content list of directory on media via retlist.
Definition: MediaDISK.cc:381
bool empty() const
Test for an empty path.
Definition: Pathname.h:113
AttachPointRef attachPoint
Definition: MediaSource.h:145
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
std::string getQueryParam(const std::string &param, EEncoding eflag=zypp::url::E_DECODED) const
Return the value for the specified query parameter.
Definition: Url.cc:655
MediaSourceRef mediaSource
Definition: MediaSource.h:144
Abstract base class for &#39;physical&#39; MediaHandler like MediaCD, etc.
Definition: MediaHandler.h:45
A simple structure containing references to a media source and its attach point.
Definition: MediaSource.h:133
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
const Url _url
Url to handle.
Definition: MediaHandler.h:110
void setMediaSource(const MediaSourceRef &ref)
Set new media source reference.
const std::string & asString() const
String representation.
Definition: Pathname.h:90
Just inherits Exception to separate media exceptions.
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
virtual void attachTo(bool next=false) override
Call concrete handler to attach the media.
Definition: MediaDISK.cc:182
bool verifyIfDiskVolume(const Pathname &name)
Definition: MediaDISK.cc:89
void removeAttachPoint()
Remove unused attach point.
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:36
int close()
Wait for the progamm to complete.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:589
Manages access to the &#39;physical&#39; media, e.g CDROM drives, Disk volumes, directory trees...
Definition: MediaManager.h:470
virtual void getDirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const =0
Call concrete handler to provide a content list of directory on media via retlist.
virtual bool getDoesFileExist(const Pathname &filename) const =0
check if a file exists
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
Ask the media manager if specified media source is already attached.
Pathname attachPoint() const
Return the currently used attach point.
Url url() const
Url used.
Definition: MediaHandler.h:507
unsigned int devMajor() const
Definition: PathInfo.cc:242
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
virtual void getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const
Call concrete handler to provide file below attach point.
std::string _filesystem
Definition: MediaDISK.h:31
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
Url manipulation class.
Definition: Url.h:87
void umount(const std::string &path)
umount device
Definition: Mount.cc:162
#define DBG
Definition: Logger.h:78
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.