From: Jiri Srain Date: Mon, 12 Dec 2005 09:48:02 +0000 (+0000) Subject: Added mount routines, including exception handling X-Git-Tag: BASE-SuSE-SLE-10-SP2-Branch~3594 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=00827cdf6e57111eb3d7bb1985c384d762365ef3;p=platform%2Fupstream%2Flibzypp.git Added mount routines, including exception handling --- diff --git a/zypp/media/Makefile.am b/zypp/media/Makefile.am index 03728af..d380a94 100644 --- a/zypp/media/Makefile.am +++ b/zypp/media/Makefile.am @@ -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 diff --git a/zypp/media/MediaException.h b/zypp/media/MediaException.h index ad08dcd..6b19ee4 100644 --- a/zypp/media/MediaException.h +++ b/zypp/media/MediaException.h @@ -14,6 +14,8 @@ #include +#include + #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 index 0000000..97c9ba9 --- /dev/null +++ b/zypp/media/Mount.cc @@ -0,0 +1,253 @@ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) 2002 SuSE AG | +\----------------------------------------------------------------------/ + + File: Mount.cc + Purpose: Implement interface to mount program + Author: Ludwig Nussel + Maintainer: Ludwig Nussel + +/-*/ + + +#include +#include +#include +#include +#include +#include + +#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 index 0000000..4aa76b3 --- /dev/null +++ b/zypp/media/Mount.h @@ -0,0 +1,136 @@ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) 2002 SuSE AG | +\----------------------------------------------------------------------/ + + File: Wget.h + Purpose: Declare interface to mount program + Author: Ludwig Nussel + Maintainer: Ludwig Nussel + +/-*/ + + +// -*- C++ -*- + +#ifndef ZYPP_MEDIA_MOUNT_H +#define ZYPP_MEDIA_MOUNT_H +#include +#include +#include + +#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