Mount.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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     // parse error messages
00083     while ( output.length() > 0)
00084     {
00085         string::size_type       ret;
00086 
00087         // extract \n
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         // return codes overwites parsed error message
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     // parse error messages
00168     while ( output.length() > 0)
00169     {
00170         string::size_type       ret;
00171 
00172         // extract \n
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         // if  ( value.find ( "not mounted" ) != string::npos )
00186         // {
00187         //    err = Error::E_already_mounted;
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         // return codes overwites parsed error message
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   // Launch the program
00229 
00230   process = new ExternalProgram(argv, environment, disp, false, -1, true);
00231 }
00232 
00233 /*--------------------------------------------------------------*/
00234 /* Return the exit status of the Mount process, closing the     */
00235 /* connection if not already done                               */
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 /* Forcably kill the process */
00253 void Mount::Kill()
00254 {
00255   if (process) process->kill();
00256 }
00257 
00258 // STATIC
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   } // namespace media
00304 } // namespace zypp

Generated on Mon Jun 5 19:10:33 2006 for zypp by  doxygen 1.4.6