libzypp  16.22.5
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 
60  _device = Pathname(_url.getQueryParam("device")).asString();
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  //
89  bool MediaDISK::verifyIfDiskVolume(const Pathname &dev_name)
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:64
Interface to the mount program.
Definition: Mount.h:69
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:350
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
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
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
virtual bool getDoesFileExist(const Pathname &filename) const
check if a file exists
Definition: MediaDISK.cc:401
virtual void getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const
Call concrete handler to provide file below attach point.
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
virtual bool isAttached() const
True if media is attached.
Definition: MediaDISK.cc:326
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
std::string _device
Definition: MediaDISK.h:33
virtual void attachTo(bool next=false)
Call concrete handler to attach the media.
Definition: MediaDISK.cc:182
virtual void getDirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Call concrete handler to provide a content list of directory on media via retlist.
Definition: MediaDISK.cc:381
#define ERR
Definition: Logger.h:66
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
AttachPointRef attachPoint
Definition: MediaSource.h:145
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
Ask the media manager if specified media source is already attached.
MediaSourceRef mediaSource
Definition: MediaSource.h:144
AttachedMedia attachedMedia() const
Returns the attached media.
Abstract base class for 'physical' 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.
Just inherits Exception to separate media exceptions.
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
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:654
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...
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:354
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:598
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees...
Definition: MediaManager.h:473
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
Pathname attachPoint() const
Return the currently used attach point.
virtual void getDir(const Pathname &dirname, bool recurse_r) const
Call concrete handler to provide directory content (not recursive!) below attach point.
Definition: MediaDISK.cc:368
virtual void releaseFrom(const std::string &ejectDev)
Call concrete handler to release the media.
Definition: MediaDISK.cc:339
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
std::string _filesystem
Definition: MediaDISK.h:34
Url url() const
Url used.
Definition: MediaHandler.h:507
Url manipulation class.
Definition: Url.h:87
void umount(const std::string &path)
umount device
Definition: Mount.cc:162
#define DBG
Definition: Logger.h:63
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.