libzypp  17.25.2
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 Pathname & filename, const ByteCount &expectedFileSize_r) const
358  {
359  MediaHandler::getFile( filename, expectedFileSize_r );
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:
zypp::filesystem::readdir
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
zypp::ExternalProgram::Stderr_To_Stdout
@ Stderr_To_Stdout
Definition: ExternalProgram.h:73
zypp::media::MediaSource
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:37
zypp::filesystem::PathInfo::path
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
zypp::media::Mount
Interface to the mount program.
Definition: Mount.h:70
zypp::media::MediaException
Just inherits Exception to separate media exceptions.
Definition: MediaException.h:36
zypp::media::AttachedMedia::mediaSource
MediaSourceRef mediaSource
Definition: MediaSource.h:144
zypp::media::MediaDISK::attachTo
virtual void attachTo(bool next=false) override
Call concrete handler to attach the media.
Definition: MediaDISK.cc:183
zypp::media::MediaSourceRef
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition: MediaSource.h:124
zypp::media::MediaDISK::_filesystem
std::string _filesystem
Definition: MediaDISK.h:31
zypp::media::MediaHandler::getFile
virtual void getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const
Call concrete handler to provide file below attach point.
Definition: MediaHandler.cc:1234
MIL
#define MIL
Definition: Logger.h:79
zypp::filesystem::PathInfo::devMinor
unsigned int devMinor() const
Definition: PathInfo.cc:252
zypp::media::MediaHandler
Abstract base class for 'physical' MediaHandler like MediaCD, etc.
Definition: MediaHandler.h:45
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
zypp::media::MediaDISK::isAttached
virtual bool isAttached() const override
True if media is attached.
Definition: MediaDISK.cc:327
zypp::media::MediaHandler::isUseableAttachPoint
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...
Definition: MediaHandler.cc:446
zypp::media::MediaNotSupportedException
Definition: MediaException.h:330
zypp::media::MediaBadUrlEmptyDestinationException
Definition: MediaException.h:308
zypp::media::MediaBadUrlEmptyFilesystemException
Definition: MediaException.h:297
zypp::ExternalProgram
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
Definition: ExternalProgram.h:60
zypp::media::MediaHandler::attachedMedia
AttachedMedia attachedMedia() const
Returns the attached media.
Definition: MediaHandler.cc:478
MediaManager.h
zypp::media::MediaHandler::setMediaSource
void setMediaSource(const MediaSourceRef &ref)
Set new media source reference.
Definition: MediaHandler.cc:462
zypp::media::MediaHandler::findAttachedMedia
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
Ask the media manager if specified media source is already attached.
Definition: MediaHandler.cc:299
zypp::ExternalProgram::execError
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
Definition: ExternalProgram.h:186
zypp::filesystem::PathInfo::isBlk
bool isBlk() const
Definition: PathInfo.h:293
zypp::ByteCount
Store and operate with byte count.
Definition: ByteCount.h:31
zypp::media::Mount::mount
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
zypp::Url::getQueryParam
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
zypp::ExternalProgram::Arguments
std::vector< std::string > Arguments
Definition: ExternalProgram.h:64
zypp::filesystem::PathInfo::devMajor
unsigned int devMajor() const
Definition: PathInfo.cc:242
zypp::RW_pointer< MediaSource >
zypp::filesystem::PathInfo
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
zypp::media::MediaHandler::setAttachPoint
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
Definition: MediaHandler.cc:230
zypp::media::MediaDISK::verifyIfDiskVolume
bool verifyIfDiskVolume(const Pathname &name)
Definition: MediaDISK.cc:90
Logger.h
zypp::media::MediaManager
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees,...
Definition: MediaManager.h:471
zypp::media::AttachedMedia
A simple structure containing references to a media source and its attach point.
Definition: MediaSource.h:134
zypp::media::MediaDISK::getDir
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
MediaDISK.h
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
zypp::filesystem::DirContent
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
zypp::media::MediaHandler::checkAttached
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
Definition: MediaHandler.cc:509
zypp::media::MediaHandler::url
Url url() const
Url used.
Definition: MediaHandler.h:507
zypp::media::AttachPoint
Attach point of a media source.
Definition: MediaSource.h:106
zypp::ExternalProgram::close
int close()
Wait for the progamm to complete.
Definition: ExternalProgram.cc:456
zypp::media::MediaDISK::getDoesFileExist
virtual bool getDoesFileExist(const Pathname &filename) const override
check if a file exists
Definition: MediaDISK.cc:402
zypp::media::AttachedMedia::attachPoint
AttachPointRef attachPoint
Definition: MediaSource.h:145
zypp::media::MediaHandler::removeAttachPoint
void removeAttachPoint()
Remove unused attach point.
Definition: MediaHandler.cc:173
zypp::asString
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
Definition: DefaultIntegral.h:98
zypp::media::MediaDISK::_device
std::string _device
Definition: MediaDISK.h:30
zypp::media::MediaDISK::releaseFrom
virtual void releaseFrom(const std::string &ejectDev) override
Call concrete handler to release the media.
Definition: MediaDISK.cc:340
zypp::media::MediaManager::getMountEntries
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.
Definition: MediaManager.cc:783
zypp::media::MediaHandler::attachPoint
Pathname attachPoint() const
Return the currently used attach point.
Definition: MediaHandler.cc:215
zypp::media::MediaDISK::MediaDISK
MediaDISK(const Url &url_r, const Pathname &attach_point_hint_r)
Definition: MediaDISK.cc:53
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
String.h
zypp::filesystem::Pathname
Pathname.
Definition: Pathname.h:45
zypp::media::Mount::umount
void umount(const std::string &path)
umount device
Definition: Mount.cc:163
Mount.h
ERR
#define ERR
Definition: Logger.h:81
zypp::media::MediaHandler::_url
const Url _url
Url to handle.
Definition: MediaHandler.h:110
zypp::media::MediaHandler::createAttachPoint
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
Definition: MediaHandler.cc:342
DBG
#define DBG
Definition: Logger.h:78
zypp::media::MediaMountException
Definition: MediaException.h:55
zypp::media::MediaDISK::getDirInfo
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
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
zypp::filesystem::Pathname::asString
const std::string & asString() const
String representation.
Definition: Pathname.h:91
zypp::Url
Url manipulation class.
Definition: Url.h:88
zypp::media::MediaHandler::getDir
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
Definition: MediaHandler.cc:1268
zypp::media::MediaHandler::getDoesFileExist
virtual bool getDoesFileExist(const Pathname &filename) const =0
check if a file exists
Definition: MediaHandler.cc:1375
zypp::media::MediaHandler::getDirInfo
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.
Definition: MediaHandler.cc:1290
zypp::media::MediaDISK::getFile
virtual void getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const override
Call concrete handler to provide file below attach point.
Definition: MediaDISK.cc:357