libzypp 17.28.8
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
23#include <zypp/base/ExternalDataSource.h>
24#include <zypp/base/Logger.h>
25#include <zypp/media/Mount.h>
27
28#include <zypp/PathInfo.h>
29
30using std::endl;
31
32#ifndef N_
33#define N_(STR) STR
34#endif
35
36
37namespace 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
67void 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
163void 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;
229 } else {
230 MIL << "unmounted " << path << endl;
231 }
232}
233
234void 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
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
275MountEntries
276Mount::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
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
bool kill()
Kill the program.
int close()
Wait for the progamm to complete.
Stderr_Disposition
Define symbols for different policies on the handling of stderr.
std::string receiveLine()
Read one line from the input stream.
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
void umount(const std::string &path)
umount device
Definition: Mount.cc:163
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
static MountEntries getEntries(const std::string &mtab="")
Return mount entries from /etc/mtab or /etc/fstab file.
Definition: Mount.cc:276
void Kill()
Forcably kill the process.
Definition: Mount.cc:269
int Status()
Return the exit status of the process, closing the connection if not already done.
Definition: Mount.cc:253
ExternalProgram * process
The connection to the mount process.
Definition: Mount.h:144
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
int exit_code
The exit code of the process, or -1 if not yet known.
Definition: Mount.h:175
~Mount()
Clean up.
Definition: Mount.cc:55
ExternalProgram::Environment Environment
For passing additional environment variables to mount.
Definition: Mount.h:77
Mount()
Create an new instance.
Definition: Mount.cc:49
String related utilities and Regular expression matching.
std::ostream & operator<<(std::ostream &str, const MediaBlockList &bl)
SolvableIdType size_type
Definition: PoolMember.h:126
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:53
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
A "struct mntent" like mount entry structure, but using std::strings.
Definition: Mount.h:35
std::string dir
file system path prefix
Definition: Mount.h:51
std::string src
name of mounted file system
Definition: Mount.h:50
std::string type
filesystem / mount type
Definition: Mount.h:52
std::string opts
mount options
Definition: Mount.h:53
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
#define DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96
#define WAR
Definition: Logger.h:97