libzypp  13.10.6
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.major() == dev_info.major() &&
118  vol_info.minor() == dev_info.minor())
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.major() == dev_info.major() &&
142  vol_info.minor() == dev_info.minor())
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.major(), dev_info.minor()
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.major() &&
246  media->min_nr == dev_info.minor())
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 
266  Mount mount;
267  std::string mountpoint = attachPoint().asString();
269  {
270  mountpoint = createAttachPoint().asString();
271  if( mountpoint.empty())
273  setAttachPoint( mountpoint, true);
274  }
275 
276  string options = _url.getQueryParam("mountoptions");
277  if(options.empty())
278  {
279  options = "ro";
280  }
281 
282  if( !media->bdir.empty())
283  {
284  options += ",bind";
285  mount.mount(media->bdir, mountpoint, "none", options);
286  }
287  else
288  {
289  mount.mount(_device, mountpoint, _filesystem, options);
290  }
291 
292  setMediaSource(media);
293 
294  // wait for /etc/mtab update ...
295  // (shouldn't be needed)
296  int limit = 3;
297  bool mountsucceeded;
298  while( !(mountsucceeded=isAttached()) && --limit)
299  {
300  sleep(1);
301  }
302 
303  if( !mountsucceeded)
304  {
306  try
307  {
308  mount.umount(attachPoint().asString());
309  }
310  catch (const MediaException & excpt_r)
311  {
312  ZYPP_CAUGHT(excpt_r);
313  }
315  "Unable to verify that the media was mounted",
316  _device, mountpoint
317  ));
318  }
319  }
320 
322  //
323  // METHOD NAME : MediaDISK::isAttached
324  // METHOD TYPE : bool
325  //
326  // DESCRIPTION : Override check if media is attached.
327  //
328  bool
330  {
331  return checkAttached(false);
332  }
333 
335  //
336  //
337  // METHOD NAME : MediaDISK::releaseFrom
338  // METHOD TYPE : PMError
339  //
340  // DESCRIPTION : Asserted that media is attached.
341  //
342  void MediaDISK::releaseFrom( const std::string & ejectDev )
343  {
345  if(am.mediaSource && am.mediaSource->iown)
346  {
347  Mount mount;
348  mount.umount(attachPoint().asString());
349  }
350  }
351 
353  //
354  // METHOD NAME : MediaDISK::getFile
355  // METHOD TYPE : PMError
356  //
357  // DESCRIPTION : Asserted that media is attached.
358  //
359  void MediaDISK::getFile (const Pathname & filename) const
360  {
361  MediaHandler::getFile( filename );
362  }
363 
365  //
366  // METHOD NAME : MediaDISK::getDir
367  // METHOD TYPE : PMError
368  //
369  // DESCRIPTION : Asserted that media is attached.
370  //
371  void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const
372  {
373  MediaHandler::getDir( dirname, recurse_r );
374  }
375 
377  //
378  //
379  // METHOD NAME : MediaDISK::getDirInfo
380  // METHOD TYPE : PMError
381  //
382  // DESCRIPTION : Asserted that media is attached and retlist is empty.
383  //
384  void MediaDISK::getDirInfo( std::list<std::string> & retlist,
385  const Pathname & dirname, bool dots ) const
386  {
387  MediaHandler::getDirInfo( retlist, dirname, dots );
388  }
389 
391  //
392  //
393  // METHOD NAME : MediaDISK::getDirInfo
394  // METHOD TYPE : PMError
395  //
396  // DESCRIPTION : Asserted that media is attached and retlist is empty.
397  //
399  const Pathname & dirname, bool dots ) const
400  {
401  MediaHandler::getDirInfo( retlist, dirname, dots );
402  }
403 
404  bool MediaDISK::getDoesFileExist( const Pathname & filename ) const
405  {
406  return MediaHandler::getDoesFileExist( filename );
407  }
408 
409  } // namespace media
410 } // namespace zypp
411 // 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:47
Interface to the mount program.
Definition: Mount.h:69
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:320
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
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:404
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
virtual bool isAttached() const
True if media is attached.
Definition: MediaDISK.cc:329
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:384
#define ERR
Definition: Logger.h:49
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 &#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.
Just inherits Exception to separate media exceptions.
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:544
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
virtual void getFile(const Pathname &filename) const
Call concrete handler to provide file below attach point.
Definition: MediaDISK.cc:359
void removeAttachPoint()
Remove unused attach point.
std::string asString(const Patch::SeverityFlag &obj)
Definition: Patch.cc:149
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:324
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:599
Manages access to the &#39;physical&#39; 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:371
virtual void releaseFrom(const std::string &ejectDev)
Call concrete handler to release the media.
Definition: MediaDISK.cc:342
virtual void getFile(const Pathname &filename) const =0
Call concrete handler to provide file below attach point.
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:506
Url manipulation class.
Definition: Url.h:87
void umount(const std::string &path)
umount device
Definition: Mount.cc:162
#define DBG
Definition: Logger.h:46
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.