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::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         // OK, have a non-empty mount table.
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   } // namespace media
00339 } // namespace zypp

Generated on Thu Jul 6 00:07:21 2006 for zypp by  doxygen 1.4.6