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::string _mtab( mtab.empty() ? "/etc/mtab" : mtab);
00264
00265 if(_mtab == "/etc/mtab" ||
00266 _mtab == "/etc/fstab" ||
00267 _mtab == "/proc/mounts")
00268 {
00269 FILE *fp = setmntent(_mtab.c_str(), "r");
00270 if( fp)
00271 {
00272 char buf[PATH_MAX * 4];
00273 struct mntent ent;
00274
00275 memset(buf, 0, sizeof(buf));
00276 memset(&ent, 0, sizeof(ent));
00277
00278 while( getmntent_r(fp, &ent, buf, sizeof(buf)) != NULL)
00279 {
00280 if( ent.mnt_fsname && *ent.mnt_fsname &&
00281 ent.mnt_dir && *ent.mnt_dir &&
00282 ent.mnt_type && *ent.mnt_type &&
00283 ent.mnt_opts && *ent.mnt_opts)
00284 {
00285 MountEntry entry(
00286 ent.mnt_fsname, ent.mnt_dir,
00287 ent.mnt_type, ent.mnt_opts,
00288 ent.mnt_freq, ent.mnt_passno
00289 );
00290
00291 entries.push_back(entry);
00292
00293 memset(buf, 0, sizeof(buf));
00294 memset(&ent, 0, sizeof(ent));
00295 }
00296 }
00297 endmntent(fp);
00298 }
00299 }
00300 return entries;
00301 }
00302
00303 }
00304 }