libzypp  17.23.5
Mount.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <mntent.h>
14 
15 #include <cstdio>
16 #include <climits>
17 #include <cerrno>
18 
19 #include <iostream>
20 #include <fstream>
21 #include <string>
22 
24 #include <zypp/base/Logger.h>
25 #include <zypp/media/Mount.h>
27 
28 #include <zypp/PathInfo.h>
29 
30 using std::endl;
31 
32 #ifndef N_
33 #define N_(STR) STR
34 #endif
35 
36 
37 namespace zypp {
38  namespace media {
39 
40  std::ostream & operator<<( std::ostream & str, const MountEntry & obj )
41  {
42  str << obj.src << " on " << obj.dir << " type " << obj.type;
43  if ( ! obj.opts.empty() )
44  str << " (" << obj.opts << ")";
45  return str;
46  }
47 
48 
50 {
51  process = 0;
52  exit_code = -1;
53 }
54 
56 {
57  MIL << "~Mount()" << endl;
58 
59  if ( process )
60  delete process;
61 
62  process = NULL;
63 
64  MIL << "~Mount() end" << endl;
65 }
66 
67 void Mount::mount( const std::string & source,
68  const std::string & target,
69  const std::string & filesystem,
70  const std::string & options,
71  const Environment & environment )
72 {
73  const char *const argv[] = {
74  "/bin/mount",
75  "-t", filesystem.c_str(),
76  "-o", options.c_str(),
77  source.c_str(),
78  target.c_str(),
79  NULL
80  };
81 
82  std::string err;
83 
84  this->run(argv, environment, ExternalProgram::Stderr_To_Stdout);
85 
86  if ( process == NULL )
87  {
88  ZYPP_THROW(MediaMountException("Mounting media failed", source, target));
89  }
90 
91  std::string value;
92  std::string output = process->receiveLine();
93 
94  // parse error messages
95  while ( output.length() > 0)
96  {
98 
99  // extract \n
100  ret = output.find_first_of ( "\n" );
101  if ( ret != std::string::npos )
102  {
103  value.assign ( output, 0, ret );
104  }
105  else
106  {
107  value = output;
108  }
109 
110  DBG << "stdout: " << value << endl;
111 
112  if ( value.find ( "is already mounted on" ) != std::string::npos )
113  {
114  err = "Media already mounted";
115  }
116  else if ( value.find ( "ermission denied" ) != std::string::npos )
117  {
118  err = "Permission denied";
119  }
120  else if ( value.find ( "wrong fs type" ) != std::string::npos )
121  {
122  err = "Invalid filesystem on media";
123  }
124  else if ( value.find ( "No medium found" ) != std::string::npos )
125  {
126  err = "No medium found";
127  }
128  else if ( value.find ( "Not a directory" ) != std::string::npos )
129  {
130  if( filesystem == "nfs" || filesystem == "nfs4" )
131  {
132  err = "Nfs path is not a directory";
133  }
134  else
135  {
136  err = "Unable to find directory on the media";
137  }
138  }
139 
140  output = process->receiveLine();
141  }
142 
143  int status = Status();
144 
145  if ( status == 0 )
146  {
147  // return codes overwites parsed error message
148  err = "";
149  }
150  else if ( status != 0 && err == "" )
151  {
152  err = "Mounting media failed";
153  }
154 
155  if ( err != "" ) {
156  WAR << "mount " << source << " " << target << ": " << err << endl;
157  ZYPP_THROW(MediaMountException(err, source, target, value));
158  } else {
159  MIL << "mounted " << source << " " << target << endl;
160  }
161 }
162 
163 void Mount::umount( const std::string & path )
164 {
165  const char *const argv[] = {
166  "/bin/umount",
167  path.c_str(),
168  NULL
169  };
170 
171  std::string err;
172 
174 
175  if ( process == NULL )
176  {
177  ZYPP_THROW(MediaUnmountException("E_mount_failed", path));
178  }
179 
180  std::string value;
181  std::string output = process->receiveLine();
182 
183  // parse error messages
184  while ( output.length() > 0)
185  {
187 
188  // extract \n
189  ret = output.find_first_of ( "\n" );
190  if ( ret != std::string::npos )
191  {
192  value.assign ( output, 0, ret );
193  }
194  else
195  {
196  value = output;
197  }
198 
199  DBG << "stdout: " << value << endl;
200 
201  // if ( value.find ( "not mounted" ) != std::string::npos )
202  // {
203  // err = Error::E_already_mounted;
204  // }
205 
206  if ( value.find ( "device is busy" ) != std::string::npos )
207  {
208  err = "Device is busy";
209  }
210 
211  output = process->receiveLine();
212  }
213 
214  int status = Status();
215 
216  if ( status == 0 )
217  {
218  // return codes overwites parsed error message
219  err = "";
220  }
221  else if ( status != 0 && err == "" )
222  {
223  err = "Unmounting media failed";
224  }
225 
226  if ( err != "") {
227  WAR << "umount " << path << ": " << err << endl;
228  ZYPP_THROW(MediaUnmountException(err, path));
229  } else {
230  MIL << "unmounted " << path << endl;
231  }
232 }
233 
234 void Mount::run( const char *const *argv, const Environment& environment,
236 {
237  exit_code = -1;
238 
239  if ( process != NULL )
240  {
241  delete process;
242  process = NULL;
243  }
244  // Launch the program
245 
246  process = new ExternalProgram(argv, environment, disp, false, -1, true);
247 }
248 
249 /*--------------------------------------------------------------*/
250 /* Return the exit status of the Mount process, closing the */
251 /* connection if not already done */
252 /*--------------------------------------------------------------*/
254 {
255  if ( process == NULL )
256  return -1;
257 
258  exit_code = process->close();
259  process->kill();
260  delete process;
261  process = 0;
262 
263  DBG << "exit code: " << exit_code << endl;
264 
265  return exit_code;
266 }
267 
268 /* Forcably kill the process */
270 {
271  if (process) process->kill();
272 }
273 
274 // STATIC
275 MountEntries
276 Mount::getEntries(const std::string &mtab)
277 {
278  MountEntries entries;
279  std::vector<std::string> mtabs;
280  bool verbose = false;
281 
282  if( mtab.empty())
283  {
284  mtabs.push_back("/proc/mounts");
285  // Also read /etc/mtab if it is a file (on newer sytems
286  // mtab is a symlink to /proc/mounts).
287  // Reason for this is the different representation of
288  // mounted loop devices:
289  // /etc/mtab: /tmp/SLES-11-SP2-MINI-ISO-x86_64-Beta2-DVD.iso on /mnt type iso9660 (ro,loop=/dev/loop0)
290  // /proc/mounts: /dev/loop0 /mnt iso9660 ro,relatime 0 0
291  if ( PathInfo( "/etc/mtab", PathInfo::LSTAT ).isFile() )
292  mtabs.push_back("/etc/mtab");
293  }
294  else
295  {
296  mtabs.push_back(mtab);
297  }
298 
299  std::vector<std::string>::const_iterator t;
300  for( t=mtabs.begin(); t != mtabs.end(); ++t)
301  {
302  if( verbose)
303  {
304  DBG << "Reading mount table from '" << *t << "'" << std::endl;
305  }
306  FILE *fp = setmntent(t->c_str(), "re");
307  if( fp)
308  {
309  char buf[PATH_MAX * 4];
310  struct mntent ent;
311 
312  memset(buf, 0, sizeof(buf));
313  memset(&ent, 0, sizeof(ent));
314 
315  while( getmntent_r(fp, &ent, buf, sizeof(buf)) != NULL)
316  {
317  if( ent.mnt_fsname && *ent.mnt_fsname &&
318  ent.mnt_dir && *ent.mnt_dir &&
319  ent.mnt_type && *ent.mnt_type &&
320  ent.mnt_opts && *ent.mnt_opts)
321  {
322  MountEntry entry(
323  ent.mnt_fsname, ent.mnt_dir,
324  ent.mnt_type, ent.mnt_opts,
325  ent.mnt_freq, ent.mnt_passno
326  );
327 
328  // Attempt quick fix for bnc#710269:
329  // MountEntry is "//dist/install/ on /var/adm/mount/AP_0x00000001 type cifs (ro,relatime,unc=\dist\install,username=,domain=suse.de"
330  // but looking for "Looking for media(cifs<//dist/install>)attached(*/var/adm/mount/AP_0x00000001)"
331  // Kick the trailing '/' in "//dist/install/"
332  // TODO: Check and fix comparison in MediaHandler::checkAttached instead.
333  if ( entry.src.size() > 1 // not for "/"
334  && entry.src[entry.src.size()-1] == '/' )
335  {
336  entry.src.erase( entry.src.size()-1 );
337  }
338  entries.push_back(entry);
339 
340  memset(buf, 0, sizeof(buf));
341  memset(&ent, 0, sizeof(ent));
342  }
343  }
344  endmntent(fp);
345 
346  if( entries.empty())
347  {
348  WAR << "Unable to read any entry from the mount table '" << *t << "'"
349  << std::endl;
350  }
351  else
352  {
353  // OK, have a non-empty mount table.
354  t = mtabs.end();
355  break;
356  }
357  }
358  else
359  {
360  int err = errno;
361  verbose = true;
362  WAR << "Failed to read the mount table '" << *t << "': "
363  << ::strerror(err)
364  << std::endl;
365  errno = err;
366  }
367  }
368  return entries;
369 }
370 
371  } // namespace media
372 } // namespace zypp
zypp::ExternalProgram::Stderr_To_Stdout
Definition: ExternalProgram.h:73
zypp::media::Mount::~Mount
~Mount()
Clean up.
Definition: Mount.cc:55
PathInfo.h
zypp::ResolverNamespace::filesystem
filesystems
zypp::media::MountEntry::opts
std::string opts
mount options
Definition: Mount.h:53
zypp::ExternalProgram::kill
bool kill()
Kill the program.
Definition: ExternalProgram.cc:574
MIL
#define MIL
Definition: Logger.h:79
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
zypp::filesystem::PathInfo::LSTAT
Definition: PathInfo.h:226
zypp::ExternalProgram
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
Definition: ExternalProgram.h:59
zypp::str::strerror
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:51
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::media::Mount::Status
int Status()
Return the exit status of the process, closing the connection if not already done.
Definition: Mount.cc:253
zypp::media::operator<<
std::ostream & operator<<(std::ostream &str, const MediaAccess &obj)
Definition: MediaAccess.cc:481
zypp::filesystem::PathInfo
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
zypp::media::MountEntry::type
std::string type
filesystem / mount type
Definition: Mount.h:52
zypp::media::Mount::Environment
ExternalProgram::Environment Environment
For passing additional environment variables to mount.
Definition: Mount.h:77
zypp::media::MountEntry::src
std::string src
name of mounted file system
Definition: Mount.h:50
zypp::media::Mount::run
void run(const char *const *argv, const Environment &environment, ExternalProgram::Stderr_Disposition stderr_disp=ExternalProgram::Stderr_To_Stdout)
Run mount with the specified arguments and handle stderr.
Definition: Mount.cc:234
Logger.h
WAR
#define WAR
Definition: Logger.h:80
MediaException.h
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
zypp::media::Mount::Mount
Mount()
Create an new instance.
Definition: Mount.cc:49
zypp::ExternalProgram::Stderr_Disposition
Stderr_Disposition
Define symbols for different policies on the handling of stderr.
Definition: ExternalProgram.h:70
zypp::ExternalProgram::close
int close()
Wait for the progamm to complete.
Definition: ExternalProgram.cc:456
zypp::media::Mount::exit_code
int exit_code
The exit code of the process, or -1 if not yet known.
Definition: Mount.h:175
ExternalDataSource.h
zypp::media::Mount::getEntries
static MountEntries getEntries(const std::string &mtab="")
Return mount entries from /etc/mtab or /etc/fstab file.
Definition: Mount.cc:276
zypp::media::Mount::process
ExternalProgram * process
The connection to the mount process.
Definition: Mount.h:144
zypp::media::MountEntry
A "struct mntent" like mount entry structure, but using std::strings.
Definition: Mount.h:34
zypp::externalprogram::ExternalDataSource::receiveLine
std::string receiveLine()
Read one line from the input stream.
Definition: ExternalDataSource.cc:126
zypp::media::Mount::umount
void umount(const std::string &path)
umount device
Definition: Mount.cc:163
Mount.h
zypp::sat::detail::size_type
SolvableIdType size_type
Definition: PoolMember.h:126
DBG
#define DBG
Definition: Logger.h:78
zypp::media::Mount::Kill
void Kill()
Forcably kill the process.
Definition: Mount.cc:269
zypp::media::MediaMountException
Definition: MediaException.h:54
str
String related utilities and Regular expression matching.
zypp::media::MountEntry::dir
std::string dir
file system path prefix
Definition: Mount.h:51
zypp::media::MediaUnmountException
Definition: MediaException.h:95