00001
00002
00003
00004
00005
00006
00007
00008
00013 #include <sys/stat.h>
00014 #include <stdio.h>
00015 #include <mntent.h>
00016 #include <limits.h>
00017 #include <unistd.h>
00018 #include <errno.h>
00019 #include <iostream>
00020 #include <fstream>
00021 #include <string>
00022
00023 #include "zypp/base/ExternalDataSource.h"
00024 #include "zypp/base/Logger.h"
00025 #include "zypp/media/Mount.h"
00026 #include "zypp/media/MediaException.h"
00027
00028 #ifndef N_
00029 #define N_(STR) STR
00030 #endif
00031
00032 using namespace std;
00033
00034 namespace zypp {
00035 namespace media {
00036
00037 Mount::Mount()
00038 {
00039 process = 0;
00040 exit_code = -1;
00041 }
00042
00043 Mount::~Mount()
00044 {
00045 MIL << "~Mount()" << endl;
00046
00047 if ( process )
00048 delete process;
00049
00050 process = NULL;
00051
00052 MIL << "~Mount() end" << endl;
00053 }
00054
00055 void Mount::mount ( const string& source,
00056 const string& target,
00057 const string& filesystem,
00058 const string& options,
00059 const Environment& environment )
00060 {
00061 const char *const argv[] = {
00062 "/bin/mount",
00063 "-t", filesystem.c_str(),
00064 "-o", options.c_str(),
00065 source.c_str(),
00066 target.c_str(),
00067 NULL
00068 };
00069
00070 std::string err;
00071
00072 this->run(argv, environment, ExternalProgram::Stderr_To_Stdout);
00073
00074 if ( process == NULL )
00075 {
00076 ZYPP_THROW(MediaMountException(source, target, "Mounting media failed"));
00077 }
00078
00079 string value;
00080 string output = process->receiveLine();
00081
00082
00083 while ( output.length() > 0)
00084 {
00085 string::size_type ret;
00086
00087
00088 ret = output.find_first_of ( "\n" );
00089 if ( ret != string::npos )
00090 {
00091 value.assign ( output, 0, ret );
00092 }
00093 else
00094 {
00095 value = output;
00096 }
00097
00098 DBG << "stdout: " << value << endl;
00099
00100 if ( value.find ( "is already mounted on" ) != string::npos )
00101 {
00102 err = "Media already mounted";
00103 }
00104 else if ( value.find ( "ermission denied" ) != string::npos )
00105 {
00106 err = "Permission denied";
00107 }
00108 else if ( value.find ( "wrong fs type" ) != string::npos )
00109 {
00110 err = "Invalid filesystem on media";
00111 }
00112 else if ( value.find ( "No medium found" ) != string::npos )
00113 {
00114 err = "No medium found";
00115 }
00116 else if ( value.find ( "Not a directory" ) != string::npos )
00117 {
00118 if( filesystem == "nfs")
00119 {
00120 err = "Nfs path is not a directory";
00121 }
00122 }
00123
00124 output = process->receiveLine();
00125 }
00126
00127 int status = Status();
00128
00129 if ( status == 0 )
00130 {
00131
00132 err = "";
00133 }
00134 else if ( status != 0 && err == "" )
00135 {
00136 err = "Mounting media failed";
00137 }
00138
00139 if ( err != "" ) {
00140 WAR << "mount " << source << " " << target << ": " << err << endl;
00141 ZYPP_THROW(MediaMountException(source, target, err));
00142 } else {
00143 MIL << "mounted " << source << " " << target << endl;
00144 }
00145 }
00146
00147 void Mount::umount (const string& path)
00148 {
00149 const char *const argv[] = {
00150 "/bin/umount",
00151 path.c_str(),
00152 NULL
00153 };
00154
00155 std::string err;
00156
00157 this->run(argv, ExternalProgram::Stderr_To_Stdout);
00158
00159 if ( process == NULL )
00160 {
00161 ZYPP_THROW(MediaUnmountException("E_mount_failed", path));
00162 }
00163
00164 string value;
00165 string output = process->receiveLine();
00166
00167
00168 while ( output.length() > 0)
00169 {
00170 string::size_type ret;
00171
00172
00173 ret = output.find_first_of ( "\n" );
00174 if ( ret != string::npos )
00175 {
00176 value.assign ( output, 0, ret );
00177 }
00178 else
00179 {
00180 value = output;
00181 }
00182
00183 DBG << "stdout: " << value << endl;
00184
00185
00186
00187
00188
00189
00190 if ( value.find ( "device is busy" ) != string::npos )
00191 {
00192 err = "Device is busy";
00193 }
00194
00195 output = process->receiveLine();
00196 }
00197
00198 int status = Status();
00199
00200 if ( status == 0 )
00201 {
00202
00203 err = "";
00204 }
00205 else if ( status != 0 && err == "" )
00206 {
00207 err = "Unmounting media failed";
00208 }
00209
00210 if ( err != "") {
00211 WAR << "umount " << path << ": " << err << endl;
00212 ZYPP_THROW(MediaUnmountException(err, path));
00213 } else {
00214 MIL << "unmounted " << path << endl;
00215 }
00216 }
00217
00218 void Mount::run( const char *const *argv, const Environment& environment,
00219 ExternalProgram::Stderr_Disposition disp )
00220 {
00221 exit_code = -1;
00222
00223 if ( process != NULL )
00224 {
00225 delete process;
00226 process = NULL;
00227 }
00228
00229
00230 process = new ExternalProgram(argv, environment, disp, false, -1, true);
00231 }
00232
00233
00234
00235
00236
00237 int Mount::Status()
00238 {
00239 if ( process == NULL )
00240 return -1;
00241
00242 exit_code = process->close();
00243 process->kill();
00244 delete process;
00245 process = 0;
00246
00247 DBG << "exit code: " << exit_code << endl;
00248
00249 return exit_code;
00250 }
00251
00252
00253 void Mount::Kill()
00254 {
00255 if (process) process->kill();
00256 }
00257
00258
00259 MountEntries
00260 Mount::getEntries(const std::string &mtab)
00261 {
00262 MountEntries entries;
00263 std::vector<std::string> mtabs;
00264 bool verbose = false;
00265
00266 if( mtab.empty())
00267 {
00268 mtabs.push_back("/etc/mtab");
00269 mtabs.push_back("/proc/mounts");
00270 }
00271 else
00272 {
00273 mtabs.push_back(mtab);
00274 }
00275
00276 std::vector<std::string>::const_iterator t;
00277 for( t=mtabs.begin(); t != mtabs.end(); ++t)
00278 {
00279 if( verbose)
00280 {
00281 DBG << "Reading mount table from '" << *t << "'" << std::endl;
00282 }
00283 FILE *fp = setmntent(t->c_str(), "r");
00284 if( fp)
00285 {
00286 char buf[PATH_MAX * 4];
00287 struct mntent ent;
00288
00289 memset(buf, 0, sizeof(buf));
00290 memset(&ent, 0, sizeof(ent));
00291
00292 while( getmntent_r(fp, &ent, buf, sizeof(buf)) != NULL)
00293 {
00294 if( ent.mnt_fsname && *ent.mnt_fsname &&
00295 ent.mnt_dir && *ent.mnt_dir &&
00296 ent.mnt_type && *ent.mnt_type &&
00297 ent.mnt_opts && *ent.mnt_opts)
00298 {
00299 MountEntry entry(
00300 ent.mnt_fsname, ent.mnt_dir,
00301 ent.mnt_type, ent.mnt_opts,
00302 ent.mnt_freq, ent.mnt_passno
00303 );
00304
00305 entries.push_back(entry);
00306
00307 memset(buf, 0, sizeof(buf));
00308 memset(&ent, 0, sizeof(ent));
00309 }
00310 }
00311 endmntent(fp);
00312
00313 if( entries.empty())
00314 {
00315 WAR << "Unable to read any entry from the mount table '" << *t << "'"
00316 << std::endl;
00317 }
00318 else
00319 {
00320
00321 t = mtabs.end();
00322 break;
00323 }
00324 }
00325 else
00326 {
00327 int err = errno;
00328 verbose = true;
00329 WAR << "Failed to read the mount table '" << *t << "': "
00330 << ::strerror(err)
00331 << std::endl;
00332 errno = err;
00333 }
00334 }
00335 return entries;
00336 }
00337
00338 }
00339 }