libzypp  17.28.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 using std::endl;
29 
30 /*
31 ** verify devices names as late as possible (while attach)
32 */
33 #define DELAYED_VERIFY 1
34 
35 
36 namespace zypp {
37  namespace media {
38 
40  //
41  // CLASS NAME : MediaDISK
42  //
44 
46  //
47  //
48  // METHOD NAME : MediaDISK::MediaDISK
49  // METHOD TYPE : Constructor
50  //
51  // DESCRIPTION :
52  //
53  MediaDISK::MediaDISK( const Url & url_r,
54  const Pathname & attach_point_hint_r )
55  : MediaHandler( url_r, attach_point_hint_r,
56  url_r.getPathName(), // urlpath below attachpoint
57  false ) // does_download
58  {
59  MIL << "MediaDISK::MediaDISK(" << url_r << ", " << attach_point_hint_r << ")" << endl;
60 
62  if( _device.empty())
63  {
64  ERR << "Media url does not contain a device specification" << std::endl;
66  }
67 #if DELAYED_VERIFY
68  DBG << "Verify of " << _device << " delayed" << std::endl;
69 #else
71  {
73  }
74 #endif
75 
76  _filesystem = _url.getQueryParam("filesystem");
77  if(_filesystem.empty())
78  _filesystem="auto";
79 
80  }
81 
83  //
84  // METHOD NAME : MediaDISK::verifyIfDiskVolume
85  // METHOD TYPE : void
86  //
87  // DESCRIPTION : Check if specified device file name is
88  // a disk volume device or throw an error.
89  //
91  {
92  if( dev_name.empty() ||
93  dev_name.asString().compare(0, sizeof("/dev/")-1, "/dev/"))
94  {
95  ERR << "Specified device name " << dev_name
96  << " is not allowed" << std::endl;
97  return false;
98  }
99 
100  PathInfo dev_info(dev_name);
101  if( !dev_info.isBlk())
102  {
103  ERR << "Specified device name " << dev_name
104  << " is not a block device" << std::endl;
105  return false;
106  }
107 
108  // check if a volume using /dev/disk/by-uuid links first
109  {
110  Pathname dpath("/dev/disk/by-uuid");
111  std::list<Pathname> dlist;
112  if( zypp::filesystem::readdir(dlist, dpath) == 0)
113  {
114  std::list<Pathname>::const_iterator it;
115  for(it = dlist.begin(); it != dlist.end(); ++it)
116  {
117  PathInfo vol_info(*it);
118  if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
119  vol_info.devMinor() == dev_info.devMinor())
120  {
121  DBG << "Specified device name " << dev_name
122  << " is a volume (disk/by-uuid link "
123  << vol_info.path() << ")"
124  << std::endl;
125  return true;
126  }
127  }
128  }
129  }
130 
131  // check if a volume using /dev/disk/by-label links
132  // (e.g. vbd mapped volumes in a XEN vm)
133  {
134  Pathname dpath("/dev/disk/by-label");
135  std::list<Pathname> dlist;
136  if( zypp::filesystem::readdir(dlist, dpath) == 0)
137  {
138  std::list<Pathname>::const_iterator it;
139  for(it = dlist.begin(); it != dlist.end(); ++it)
140  {
141  PathInfo vol_info(*it);
142  if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() &&
143  vol_info.devMinor() == dev_info.devMinor())
144  {
145  DBG << "Specified device name " << dev_name
146  << " is a volume (disk/by-label link "
147  << vol_info.path() << ")"
148  << std::endl;
149  return true;
150  }
151  }
152  }
153  }
154 
155  // check if a filesystem volume using the 'blkid' tool
156  // (there is no /dev/disk link for some of them)
158  args.push_back( "blkid" );
159  args.push_back( "-p" );
160  args.push_back( dev_name.asString() );
161 
163  cmd >> DBG;
164  if ( cmd.close() != 0 )
165  {
166  ERR << cmd.execError() << endl
167  << "Specified device name " << dev_name
168  << " is not a usable disk volume"
169  << std::endl;
170  return false;
171  }
172  return true;
173  }
174 
176  //
177  //
178  // METHOD NAME : MediaDISK::attachTo
179  // METHOD TYPE : PMError
180  //
181  // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory.
182  //
183  void MediaDISK::attachTo(bool next)
184  {
185  if(next)
187  // FIXME
188  // do mount --bind <partition>/<dir> to <to>
189  // mount /dev/<partition> /tmp_mount
190  // mount /tmp_mount/<dir> <to> --bind -o ro
191  // FIXME: try all filesystems
192 
193  if(_device.empty())
195 
196  PathInfo dev_info(_device);
197  if(!dev_info.isBlk())
199 #if DELAYED_VERIFY
200  DBG << "Verifying " << _device << " ..." << std::endl;
202  {
204  }
205 #endif
206 
207  if(_filesystem.empty())
209 
210  MediaSourceRef media( new MediaSource(
211  "disk", _device, dev_info.devMajor(), dev_info.devMinor()
212  ));
213  AttachedMedia ret( findAttachedMedia( media));
214 
215  if( ret.mediaSource &&
216  ret.attachPoint &&
217  !ret.attachPoint->empty())
218  {
219  DBG << "Using a shared media "
220  << ret.mediaSource->name
221  << " attached on "
222  << ret.attachPoint->path
223  << endl;
224 
228  return;
229  }
230 
231  MediaManager manager;
232  MountEntries entries( manager.getMountEntries());
233  MountEntries::const_iterator e;
234  for( e = entries.begin(); e != entries.end(); ++e)
235  {
236  bool is_device = false;
237  std::string dev_path(Pathname(e->src).asString());
238  PathInfo dev_info;
239 
240  if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
241  dev_info(e->src) && dev_info.isBlk())
242  {
243  is_device = true;
244  }
245 
246  if( is_device && media->maj_nr == dev_info.devMajor() &&
247  media->min_nr == dev_info.devMinor())
248  {
249  AttachPointRef ap( new AttachPoint(e->dir, false));
250  AttachedMedia am( media, ap);
251  {
252  DBG << "Using a system mounted media "
253  << media->name
254  << " attached on "
255  << ap->path
256  << endl;
257 
258  media->iown = false; // mark attachment as foreign
259 
260  setMediaSource(media);
261  setAttachPoint(ap);
262  return;
263  }
264  }
265  }
266 
268  {
270  }
271  std::string mountpoint( attachPoint().asString() );
272 
273  Mount mount;
274  std::string options = _url.getQueryParam("mountoptions");
275  if(options.empty())
276  {
277  options = "ro";
278  }
279 
280  if( !media->bdir.empty())
281  {
282  options += ",bind";
283  mount.mount(media->bdir, mountpoint, "none", options);
284  }
285  else
286  {
287  mount.mount(_device, mountpoint, _filesystem, options);
288  }
289 
290  setMediaSource(media);
291 
292  // wait for /etc/mtab update ...
293  // (shouldn't be needed)
294  int limit = 3;
295  bool mountsucceeded;
296  while( !(mountsucceeded=isAttached()) && --limit)
297  {
298  sleep(1);
299  }
300 
301  if( !mountsucceeded)
302  {
304  try
305  {
306  mount.umount(attachPoint().asString());
307  }
308  catch (const MediaException & excpt_r)
309  {
310  ZYPP_CAUGHT(excpt_r);
311  }
313  "Unable to verify that the media was mounted",
314  _device, mountpoint
315  ));
316  }
317  }
318 
320  //
321  // METHOD NAME : MediaDISK::isAttached
322  // METHOD TYPE : bool
323  //
324  // DESCRIPTION : Override check if media is attached.
325  //
326  bool
328  {
329  return checkAttached(false);
330  }
331 
333  //
334  //
335  // METHOD NAME : MediaDISK::releaseFrom
336  // METHOD TYPE : PMError
337  //
338  // DESCRIPTION : Asserted that media is attached.
339  //
340  void MediaDISK::releaseFrom( const std::string & ejectDev )
341  {
343  if(am.mediaSource && am.mediaSource->iown)
344  {
345  Mount mount;
346  mount.umount(attachPoint().asString());
347  }
348  }
349 
351  //
352  // METHOD NAME : MediaDISK::getFile
353  // METHOD TYPE : PMError
354  //
355  // DESCRIPTION : Asserted that media is attached.
356  //
357  void MediaDISK::getFile ( const OnMediaLocation &file ) const
358  {
359  MediaHandler::getFile( file );
360  }
361 
363  //
364  // METHOD NAME : MediaDISK::getDir
365  // METHOD TYPE : PMError
366  //
367  // DESCRIPTION : Asserted that media is attached.
368  //
369  void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const
370  {
371  MediaHandler::getDir( dirname, recurse_r );
372  }
373 
375  //
376  //
377  // METHOD NAME : MediaDISK::getDirInfo
378  // METHOD TYPE : PMError
379  //
380  // DESCRIPTION : Asserted that media is attached and retlist is empty.
381  //
382  void MediaDISK::getDirInfo( std::list<std::string> & retlist,
383  const Pathname & dirname, bool dots ) const
384  {
385  MediaHandler::getDirInfo( retlist, dirname, dots );
386  }
387 
389  //
390  //
391  // METHOD NAME : MediaDISK::getDirInfo
392  // METHOD TYPE : PMError
393  //
394  // DESCRIPTION : Asserted that media is attached and retlist is empty.
395  //
397  const Pathname & dirname, bool dots ) const
398  {
399  MediaHandler::getDirInfo( retlist, dirname, dots );
400  }
401 
402  bool MediaDISK::getDoesFileExist( const Pathname & filename ) const
403  {
404  return MediaHandler::getDoesFileExist( filename );
405  }
406 
407  } // namespace media
408 } // namespace zypp
409 // 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:96
Interface to the mount program.
Definition: Mount.h:69
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:244
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
MediaDISK(const Url &url_r, const Pathname &attach_point_hint_r)
Definition: MediaDISK.cc:53
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Describes a resource file located on a medium.
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.
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition: MediaSource.h:124
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
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:327
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:340
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:369
unsigned int devMinor() const
Definition: PathInfo.cc:251
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
#define ERR
Definition: Logger.h:98
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:67
virtual bool getDoesFileExist(const Pathname &filename) const override
check if a file exists
Definition: MediaDISK.cc:402
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:382
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
AttachPointRef attachPoint
Definition: MediaSource.h:145
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:51
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:113
void setMediaSource(const MediaSourceRef &ref)
Set new media source reference.
const std::string & asString() const
String representation.
Definition: Pathname.h:91
Just inherits Exception to separate media exceptions.
virtual void getFile(const OnMediaLocation &file) const override
Call concrete handler to provide file below attach point.
Definition: MediaDISK.cc:357
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:514
virtual void attachTo(bool next=false) override
Call concrete handler to attach the media.
Definition: MediaDISK.cc:183
bool verifyIfDiskVolume(const Pathname &name)
Definition: MediaDISK.cc:90
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:576
Manages access to the &#39;physical&#39; media, e.g CDROM drives, Disk volumes, directory trees...
Definition: MediaManager.h:453
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:503
unsigned int devMajor() const
Definition: PathInfo.cc:241
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:218
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
virtual void getFile(const OnMediaLocation &file) const
Call concrete handler to provide file below attach point.
Url manipulation class.
Definition: Url.h:91
void umount(const std::string &path)
umount device
Definition: Mount.cc:163
#define DBG
Definition: Logger.h:95
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.