Added mount routines, including exception handling
authorJiri Srain <jsrain@suse.cz>
Mon, 12 Dec 2005 09:48:02 +0000 (09:48 +0000)
committerJiri Srain <jsrain@suse.cz>
Mon, 12 Dec 2005 09:48:02 +0000 (09:48 +0000)
zypp/media/Makefile.am
zypp/media/MediaException.h
zypp/media/Mount.cc [new file with mode: 0644]
zypp/media/Mount.h [new file with mode: 0644]

index 03728af..d380a94 100644 (file)
@@ -10,7 +10,8 @@ INCLUDES = -I$(oldincludedir)/libxml2
 include_HEADERS =              \
        MediaException.h        \
        MediaAccess.h           \
-       MediaHandler.h          
+       MediaHandler.h          \
+       Mount.h
 
 #      MediaCurl.h
 
@@ -21,7 +22,8 @@ noinst_LTLIBRARIES =  lib@PACKAGE@_media.la
 
 lib@PACKAGE@_media_la_SOURCES = \
        MediaAccess.cc          \
-       MediaHandler.cc         
+       MediaHandler.cc         \
+       Mount.cc
 
 #      MediaCurl.cc
 
index ad08dcd..6b19ee4 100644 (file)
@@ -14,6 +14,8 @@
 
 #include <iosfwd>
 
+#include <string>
+
 #include "zypp/base/Exception.h"
 
 ///////////////////////////////////////////////////////////////////
@@ -29,10 +31,60 @@ namespace zypp
     class MediaException : public Exception
     {
     public:
-      /** Ctor taking message. */
+      /** Ctor taking message.
+       * Use \ref ZYPP_THROW to throw exceptions.
+      */
+      MediaException()
+      : Exception( "Media Exception" )
+      {}
+      /** Ctor taking message.
+       * Use \ref ZYPP_THROW to throw exceptions.
+      */
       MediaException( const std::string & msg_r )
       : Exception( msg_r )
       {}
+      /** Dtor. */
+      virtual ~MediaException() throw() {};
+    };
+
+    class MediaMountException : public MediaException
+    {
+    public:
+      /** Ctor taking message.
+       * Use \ref ZYPP_DOTHROW to throw exceptions.
+      */
+      MediaMountException( const std::string & msg_r,
+                          const std::string & source_r,
+                          const std::string & target_r )
+      : MediaException( msg_r )
+      , _source(source_r)
+      , _target(target_r)
+      {}
+      /** Dtor. */
+      virtual ~MediaMountException() throw() {};
+      std::string source() const { return _source; }
+      std::string target() const { return _target; }
+    private:
+      std::string _source;
+      std::string _target;
+    };
+
+    class MediaUnmountException : public MediaException
+    {
+    public:
+      /** Ctor taking message.
+       * Use \ref ZYPP_DOTHROW to throw exceptions.
+      */
+      MediaUnmountException( const std::string & msg_r,
+                            const std::string & path_r )
+      : MediaException( msg_r )
+      , _path(path_r)
+      {}
+      /** Dtor. */
+      virtual ~MediaUnmountException() throw() {};
+      std::string path() const { return _path; }
+    private:
+      std::string _path;
     };
 
   /////////////////////////////////////////////////////////////////
diff --git a/zypp/media/Mount.cc b/zypp/media/Mount.cc
new file mode 100644 (file)
index 0000000..97c9ba9
--- /dev/null
@@ -0,0 +1,253 @@
+/*---------------------------------------------------------------------\
+|                                                                      |
+|                      __   __    ____ _____ ____                      |
+|                      \ \ / /_ _/ ___|_   _|___ \                     |
+|                       \ V / _` \___ \ | |   __) |                    |
+|                        | | (_| |___) || |  / __/                     |
+|                        |_|\__,_|____/ |_| |_____|                    |
+|                                                                      |
+|                               core system                            |
+|                                                     (C) 2002 SuSE AG |
+\----------------------------------------------------------------------/
+
+   File:       Mount.cc
+   Purpose:    Implement interface to mount program
+   Author:     Ludwig Nussel <lnussel@suse.de>
+   Maintainer: Ludwig Nussel <lnussel@suse.de>
+
+/-*/
+
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "zypp/base/ExternalDataSource.h"
+#include "zypp/base/Logger.h"
+#include "zypp/media/Mount.h"
+#include "zypp/media/MediaException.h"
+
+#ifndef N_
+#define N_(STR) STR
+#endif
+
+using namespace std;
+
+namespace zypp {
+  namespace media {
+
+Mount::Mount()
+{
+    process = 0;
+    exit_code = -1;
+}
+
+Mount::~Mount()
+{
+   MIL <<  "~Mount()" << endl;
+
+   if ( process )
+      delete process;
+
+   process = NULL;
+
+   MIL << "~Mount() end" << endl;
+}
+
+void Mount::mount ( const string& source,
+                      const string& target,
+                      const string& filesystem,
+                      const string& options,
+                      const Environment& environment )
+{
+    const char *const argv[] = {
+       "/bin/mount",
+       "-t", filesystem.c_str(),
+       "-o", options.c_str(),
+       source.c_str(),
+       target.c_str(),
+       NULL
+     };
+
+    std::string err;
+
+    this->run(argv, environment, ExternalProgram::Stderr_To_Stdout);
+
+    if ( process == NULL )
+    {
+      ZYPP_DOTHROW(MediaMountException(source, target, "Error::E_mount_failed"));
+    }
+
+    string value;
+    string output = process->receiveLine();
+
+    // parse error messages
+    while ( output.length() > 0)
+    {
+       string::size_type       ret;
+
+       // extract \n
+       ret = output.find_first_of ( "\n" );
+       if ( ret != string::npos )
+       {
+           value.assign ( output, 0, ret );
+       }
+       else
+       {
+           value = output;
+       }
+
+       DBG << "stdout: " << value << endl;
+
+       if  ( value.find ( "is already mounted on" ) != string::npos )
+       {
+           err = "Error::E_already_mounted";
+       }
+       else if  ( value.find ( "ermission denied" ) != string::npos )
+       {
+           err = "Error::E_no_permission";
+       }
+       else if  ( value.find ( "wrong fs type" ) != string::npos )
+       {
+           err = "Error::E_invalid_filesystem";
+       }
+
+       output = process->receiveLine();
+    }
+
+    int status = Status();
+
+    if ( status == 0 )
+    {
+       // return codes overwites parsed error message
+       err = "";
+    }
+    else if ( status != 0 && err == "" )
+    {
+        err = "Error::E_mount_failed";
+    }
+
+    if ( err != "" ) {
+      WAR << "mount " << source << " " << target << ": " << err << endl;
+      ZYPP_DOTHROW(MediaMountException(source, target, err));
+    } else {
+      MIL << "mounted " << source << " " << target << endl;
+    }
+}
+
+void Mount::umount (const string& path)
+{
+    const char *const argv[] = {
+       "/bin/umount",
+       path.c_str(),
+       NULL
+     };
+
+    std::string err;
+
+    this->run(argv, ExternalProgram::Stderr_To_Stdout);
+
+    if ( process == NULL )
+    {
+        ZYPP_DOTHROW(MediaUnmountException("E_mount_failed", path));
+    }
+
+    string value;
+    string output = process->receiveLine();
+
+    // parse error messages
+    while ( output.length() > 0)
+    {
+       string::size_type       ret;
+
+       // extract \n
+       ret = output.find_first_of ( "\n" );
+       if ( ret != string::npos )
+       {
+           value.assign ( output, 0, ret );
+       }
+       else
+       {
+           value = output;
+       }
+
+       DBG << "stdout: " << value << endl;
+
+       // if  ( value.find ( "not mounted" ) != string::npos )
+       // {
+       //    err = Error::E_already_mounted;
+       // }
+
+       if  ( value.find ( "device is busy" ) != string::npos )
+       {
+           err = "Error::E_busy";
+       }
+
+       output = process->receiveLine();
+    }
+
+    int status = Status();
+
+    if ( status == 0 )
+    {
+       // return codes overwites parsed error message
+       err = "";
+    }
+    else if ( status != 0 && err == "" )
+    {
+       err = "Error::E_umount_failed";
+    }
+
+    if ( err != "") {
+      WAR << "umount " << path << ": " << err << endl;
+      ZYPP_DOTHROW(MediaUnmountException(err, path));
+    } else {
+      MIL << "unmounted " << path << endl;
+    }
+}
+
+void Mount::run( const char *const *argv, const Environment& environment,
+                ExternalProgram::Stderr_Disposition disp )
+{
+  exit_code = -1;
+
+  if ( process != NULL )
+  {
+     delete process;
+     process = NULL;
+  }
+  // Launch the program
+
+  process = new ExternalProgram(argv, environment, disp, false, -1, true);
+}
+
+/*--------------------------------------------------------------*/
+/* Return the exit status of the Mount process, closing the    */
+/* connection if not already done                              */
+/*--------------------------------------------------------------*/
+int Mount::Status()
+{
+   if ( process == NULL )
+      return -1;
+
+   exit_code = process->close();
+   process->kill();
+   delete process;
+   process = 0;
+
+   DBG << "exit code: " << exit_code << endl;
+
+   return exit_code;
+}
+
+/* Forcably kill the process */
+void Mount::Kill()
+{
+  if (process) process->kill();
+}
+
+  } // namespace media
+} // namespace zypp
diff --git a/zypp/media/Mount.h b/zypp/media/Mount.h
new file mode 100644 (file)
index 0000000..4aa76b3
--- /dev/null
@@ -0,0 +1,136 @@
+/*---------------------------------------------------------------------\
+|                                                                      |
+|                      __   __    ____ _____ ____                      |
+|                      \ \ / /_ _/ ___|_   _|___ \                     |
+|                       \ V / _` \___ \ | |   __) |                    |
+|                        | | (_| |___) || |  / __/                     |
+|                        |_|\__,_|____/ |_| |_____|                    |
+|                                                                      |
+|                               core system                            |
+|                                                     (C) 2002 SuSE AG |
+\----------------------------------------------------------------------/
+
+   File:       Wget.h
+   Purpose:    Declare interface to mount program
+   Author:     Ludwig Nussel <lnussel@suse.de>
+   Maintainer: Ludwig Nussel <lnussel@suse.de>
+
+/-*/
+
+
+// -*- C++ -*-
+
+#ifndef ZYPP_MEDIA_MOUNT_H
+#define ZYPP_MEDIA_MOUNT_H
+#include <set>
+#include <map>
+#include <string>
+
+#include "zypp/ExternalProgram.h"
+
+namespace zypp {
+  namespace media {
+
+    /**
+     * @short Interface to the mount program
+     */
+    class Mount
+    {
+    public:
+
+       /**
+        * For passing additional environment variables
+        * to mount
+        **/
+       typedef ExternalProgram::Environment Environment;
+
+       /**
+        * Mount options. 'key' or 'key=value' pairs, separated by ','
+        **/
+#warning Uncomment Options type if it is needed
+#if 0
+       typedef KVMap<_KVMap::CharSep<'=',','> > Options;
+#endif
+
+    public:
+
+       /**
+       * Create an new instance.
+       */
+       Mount();
+
+       /**
+       * Clean up.
+       */
+       ~Mount();
+
+       /**
+       * mount device
+       *
+       * @param source what to mount (e.g. /dev/hda3)
+       * @param target where to mount (e.g. /mnt)
+       * @param filesystem which filesystem to use (e.g. reiserfs) (-t parameter)
+       * @param options mount options (e.g. ro) (-o parameter)
+       * @param environment optinal environment to pass (e.g. PASSWD="sennah")
+        *
+        * \throws MediaException
+        *
+       */
+
+       void mount ( const std::string& source,
+                       const std::string& target,
+                       const std::string& filesystem,
+                       const std::string& options,
+                       const Environment& environment = Environment() );
+
+       /** umount device
+        *
+        * @param path device or mountpoint to umount
+        *
+        * \throws MediaException
+        *
+        * */
+       void umount (const std::string& path);
+
+    private:
+
+       /** The connection to the mount process.
+        * */
+       ExternalProgram *process;
+
+       /**
+        * Run mount with the specified arguments and handle stderr.
+        * @param argv Mount arguments
+        * @param environment Addittional environment to set
+        * @param stderr_disp How to handle stderr, merged with stdout by default
+        * */
+       void run( const char *const *argv, const Environment& environment,
+                 ExternalProgram::Stderr_Disposition stderr_disp =
+                 ExternalProgram::Stderr_To_Stdout);
+
+       void run( const char *const *argv,
+                 ExternalProgram::Stderr_Disposition stderr_disp =
+                 ExternalProgram::Stderr_To_Stdout) {
+         Environment notused;
+         run( argv, notused, stderr_disp );
+       }
+
+       /** Return the exit status of the process, closing the connection if
+        * not already done.
+        * */
+       int Status();
+
+       /** Forcably kill the process
+        * */
+       void Kill();
+
+
+       /** The exit code of the process, or -1 if not yet known.
+        * */
+       int exit_code;
+    };
+
+  } // namespace media
+} // namespace zypp
+
+#endif