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 std::string & source,
00056                    const std::string & target,
00057                    const std::string & filesystem,
00058                    const std::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("Mounting media failed", source, target));
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             else
00123             {
00124                err = "Unable to find directory on the media";
00125             }
00126         }
00127 
00128         output = process->receiveLine();
00129     }
00130 
00131     int status = Status();
00132 
00133     if ( status == 0 )
00134     {
00135         // return codes overwites parsed error message
00136         err = "";
00137     }
00138     else if ( status != 0 && err == "" )
00139     {
00140         err = "Mounting media failed";
00141     }
00142 
00143     if ( err != "" ) {
00144       WAR << "mount " << source << " " << target << ": " << err << endl;
00145       ZYPP_THROW(MediaMountException(err, source, target, value));
00146     } else {
00147       MIL << "mounted " << source << " " << target << endl;
00148     }
00149 }
00150 
00151 void Mount::umount( const std::string & path )
00152 {
00153     const char *const argv[] = {
00154         "/bin/umount",
00155         path.c_str(),
00156         NULL
00157      };
00158 
00159     std::string err;
00160 
00161     this->run(argv, ExternalProgram::Stderr_To_Stdout);
00162 
00163     if ( process == NULL )
00164     {
00165         ZYPP_THROW(MediaUnmountException("E_mount_failed", path));
00166     }
00167 
00168     string value;
00169     string output = process->receiveLine();
00170 
00171     // parse error messages
00172     while ( output.length() > 0)
00173     {
00174         string::size_type       ret;
00175 
00176         // extract \n
00177         ret = output.find_first_of ( "\n" );
00178         if ( ret != string::npos )
00179         {
00180             value.assign ( output, 0, ret );
00181         }
00182         else
00183         {
00184             value = output;
00185         }
00186 
00187         DBG << "stdout: " << value << endl;
00188 
00189         // if  ( value.find ( "not mounted" ) != string::npos )
00190         // {
00191         //    err = Error::E_already_mounted;
00192         // }
00193 
00194         if  ( value.find ( "device is busy" ) != string::npos )
00195         {
00196             err = "Device is busy";
00197         }
00198 
00199         output = process->receiveLine();
00200     }
00201 
00202     int status = Status();
00203 
00204     if ( status == 0 )
00205     {
00206         // return codes overwites parsed error message
00207         err = "";
00208     }
00209     else if ( status != 0 && err == "" )
00210     {
00211         err = "Unmounting media failed";
00212     }
00213 
00214     if ( err != "") {
00215       WAR << "umount " << path << ": " << err << endl;
00216       ZYPP_THROW(MediaUnmountException(err, path));
00217     } else {
00218       MIL << "unmounted " << path << endl;
00219     }
00220 }
00221 
00222 void Mount::run( const char *const *argv, const Environment& environment,
00223                  ExternalProgram::Stderr_Disposition disp )
00224 {
00225   exit_code = -1;
00226 
00227   if ( process != NULL )
00228   {
00229      delete process;
00230      process = NULL;
00231   }
00232   // Launch the program
00233 
00234   process = new ExternalProgram(argv, environment, disp, false, -1, true);
00235 }
00236 
00237 /*--------------------------------------------------------------*/
00238 /* Return the exit status of the Mount process, closing the     */
00239 /* connection if not already done                               */
00240 /*--------------------------------------------------------------*/
00241 int Mount::Status()
00242 {
00243    if ( process == NULL )
00244       return -1;
00245 
00246    exit_code = process->close();
00247    process->kill();
00248    delete process;
00249    process = 0;
00250 
00251    DBG << "exit code: " << exit_code << endl;
00252 
00253    return exit_code;
00254 }
00255 
00256 /* Forcably kill the process */
00257 void Mount::Kill()
00258 {
00259   if (process) process->kill();
00260 }
00261 
00262 // STATIC
00263 MountEntries
00264 Mount::getEntries(const std::string &mtab)
00265 {
00266   MountEntries             entries;
00267   std::vector<std::string> mtabs;
00268   bool                     verbose = false;
00269 
00270   if( mtab.empty())
00271   {
00272     mtabs.push_back("/etc/mtab");
00273     mtabs.push_back("/proc/mounts");
00274   }
00275   else
00276   {
00277     mtabs.push_back(mtab);
00278   }
00279 
00280   std::vector<std::string>::const_iterator t;
00281   for( t=mtabs.begin(); t != mtabs.end(); ++t)
00282   {
00283     if( verbose)
00284     {
00285       DBG << "Reading mount table from '" << *t << "'" << std::endl;
00286     }
00287     FILE *fp = setmntent(t->c_str(), "r");
00288     if( fp)
00289     {
00290       char          buf[PATH_MAX * 4];
00291       struct mntent ent;
00292 
00293       memset(buf,  0, sizeof(buf));
00294       memset(&ent, 0, sizeof(ent));
00295 
00296       while( getmntent_r(fp, &ent, buf, sizeof(buf)) != NULL)
00297       {
00298         if( ent.mnt_fsname && *ent.mnt_fsname &&
00299             ent.mnt_dir    && *ent.mnt_dir    &&
00300             ent.mnt_type   && *ent.mnt_type   &&
00301             ent.mnt_opts   && *ent.mnt_opts)
00302         {
00303           MountEntry entry(
00304             ent.mnt_fsname, ent.mnt_dir,
00305             ent.mnt_type,   ent.mnt_opts,
00306             ent.mnt_freq,   ent.mnt_passno
00307           );
00308 
00309           entries.push_back(entry);
00310 
00311           memset(buf,  0, sizeof(buf));
00312           memset(&ent, 0, sizeof(ent));
00313         }
00314       }
00315       endmntent(fp);
00316 
00317       if( entries.empty())
00318       {
00319         WAR << "Unable to read any entry from the mount table '" << *t << "'"
00320             << std::endl;
00321       }
00322       else
00323       {
00324         // OK, have a non-empty mount table.
00325         t = mtabs.end();
00326         break;
00327       }
00328     }
00329     else
00330     {
00331       int err = errno;
00332       verbose = true;
00333       WAR << "Failed to read the mount table '" << *t << "': "
00334           << ::strerror(err)
00335           << std::endl;
00336       errno = err;
00337     }
00338   }
00339   return entries;
00340 }
00341 
00342   } // namespace media
00343 } // namespace zypp

Generated on Tue Sep 25 19:23:02 2007 for libzypp by  doxygen 1.5.3