From: Jiri Srain Date: Tue, 13 Dec 2005 16:20:01 +0000 (+0000) Subject: added media-specific backends, some of them still need some updates... X-Git-Tag: BASE-SuSE-SLE-10-SP2-Branch~3573 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3f9795568d045bbfc457c63430aa7b64ba1fafc7;p=platform%2Fupstream%2Flibzypp.git added media-specific backends, some of them still need some updates... --- diff --git a/zypp/KVMap.h b/zypp/KVMap.h new file mode 100644 index 0000000..f464228 --- /dev/null +++ b/zypp/KVMap.h @@ -0,0 +1,209 @@ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) SuSE Linux AG | +\----------------------------------------------------------------------/ + + File: KVMap.h + + Author: Michael Andres + Maintainer: Michael Andres + + Purpose: Convenience stuff for handling (key,value) pairs + +/-*/ +#ifndef KVMap_h +#define KVMap_h + +#include +#include + +#include "zypp/base/String.h" + +namespace zypp { + namespace kvmap { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : KVMapBase::KVMapPolicy + /** + * @short KVMapPolicy for conversion of KVMaps to/from string. + * + * _kvsplit: The string separating key from value + * + * _fsplit: (key,value) pairs are separated by any nonempty + * sequence of characers occurring in _fsplit + * + * _kvjoin: The string used to join key and value. + * + * _fjoin: The string used to separate (key,value) pairs. + * + * TODO: Maybe options for exact _fsplit handling and timming of values. + * + **/ + struct KVMapPolicy { + std::string _kvsplit; + std::string _fsplit; + std::string _kvjoin; + std::string _fjoin; + KVMapPolicy( const std::string & kvsplit_r, const std::string & fsplit_r ) + : _kvsplit( kvsplit_r ) + , _fsplit ( fsplit_r ) + , _kvjoin ( _kvsplit ) + , _fjoin ( _fsplit ) + {} + KVMapPolicy( const std::string & kvsplit_r, const std::string & fsplit_r, + const std::string & kvjoin_r ) + : _kvsplit( kvsplit_r ) + , _fsplit ( fsplit_r ) + , _kvjoin ( kvjoin_r ) + , _fjoin ( _fsplit ) + {} + KVMapPolicy( const std::string & kvsplit_r, const std::string & fsplit_r, + const std::string & kvjoin_r, const std::string & fjoin_r ) + : _kvsplit( kvsplit_r ) + , _fsplit ( fsplit_r ) + , _kvjoin ( kvjoin_r ) + , _fjoin ( fjoin_r ) + {} + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : KVMapBase + /** + * @short Base class for KVMaps, (key,value) pairs + **/ + struct KVMapBase : public std::map { + + /** + * (key,value) map type + **/ + typedef std::map map_type; + + KVMapBase() + {} + KVMapBase( const map_type & kvmap_r ) + : std::map( kvmap_r ) + {} + + /** + * Test whether key is set. + **/ + bool has( const std::string & key_r ) const { + return( find( key_r ) != end() ); + } + + /** + * @short KVMapPolicy for KVMaps using a single char as separator (e.g. mount options). + **/ + template + struct CharSep : public KVMapPolicy { CharSep() : KVMapPolicy( std::string(1,kv), std::string(1,f) ) {} }; + + /////////////////////////////////////////////////////////////////// + + /** + * Split str_r into (key,value) map, using the separators defined + * by opts_r. + **/ + static map_type split( const std::string & str_r, + const KVMapPolicy & opts_r ) { + map_type ret; + std::vector fields; +#warning uncomment when split is ported +#if 0 + str::split( str_r, fields, opts_r._fsplit ); +#endif + + for ( unsigned i = 0; i < fields.size(); ++i ) { + std::string::size_type pos = fields[i].find( opts_r._kvsplit ); + if ( pos == std::string::npos ) { + ret[fields[i]] = ""; + } else { + ret[fields[i].substr( 0, pos )] = fields[i].substr( pos+1 ); + } + } + + return ret; + } + + /** + * Join (key,value) map into string, using the separators defined + * by opts_r. + **/ + static std::string join( const map_type & kvmap_r, + const KVMapPolicy & opts_r ) { + std::string ret; + + for ( map_type::const_iterator it = kvmap_r.begin(); it != kvmap_r.end(); ++it ) { + if ( ! ret.empty() ) { + ret += opts_r._fjoin; + } + ret += it->first; + if ( !it->second.empty() ) { + ret += opts_r._kvjoin + it->second; + } + } + + return ret; + } + + }; + + + + } // namespace kvmap + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : KVMap + /** + * @short A map of (key,value) strings. + * + * The template argument defines the @ref kvmap::Options for + * split and join. + * + * E.g. mount options (a comma separated list of key[=value] pairs) + * could be handled by KVMap. + **/ + template + struct KVMap : public kvmap::KVMapBase { + + KVMap() + {} + KVMap( const char * str_r ) + : kvmap::KVMapBase( split( (str_r?str_r:""), KVMapOpts() ) ) + {} + KVMap( const std::string & str_r ) + : kvmap::KVMapBase( split( str_r, KVMapOpts() ) ) + {} + KVMap( const map_type & map_r ) + : kvmap::KVMapBase( map_r ) + {} + + ~KVMap() {} + + std::string asString() const { + return join( *this, KVMapOpts() ); + } + + }; + + /////////////////////////////////////////////////////////////////// + + template + std::ostream & operator<<( std::ostream & str, const KVMap & obj ) + { return str << obj.asString(); } + +/////////////////////////////////////////////////////////////////// +} // namespace zypp + +#endif // KVMap_h diff --git a/zypp/Makefile.am b/zypp/Makefile.am index b4a937b..30c7ee1 100644 --- a/zypp/Makefile.am +++ b/zypp/Makefile.am @@ -28,7 +28,10 @@ include_HEADERS = NeedAType.h \ Pathname.h \ PathInfo.h \ Digest.h \ - Url.h + Url.h \ + TmpPath.h \ + KVMap.h \ + Callback.h ## ################################################## @@ -58,7 +61,8 @@ lib@PACKAGE@_la_SOURCES = \ ExternalProgram.cc\ PathInfo.cc \ Digest.cc \ - Url.cc + Url.cc \ + TmpPath.cc lib@PACKAGE@_la_LDFLAGS = @LIB_VERSION_INFO@ diff --git a/zypp/media/Makefile.am b/zypp/media/Makefile.am index a4e02bd..ea1575a 100644 --- a/zypp/media/Makefile.am +++ b/zypp/media/Makefile.am @@ -12,9 +12,14 @@ include_HEADERS = \ MediaAccess.h \ MediaHandler.h \ Mount.h \ + MediaNFS.h \ + MediaCD.h \ + MediaDIR.h \ + MediaDISK.h \ + MediaSMB.h \ + MediaCIFS.h \ MediaCurl.h -# MediaNFS.h noinst_LTLIBRARIES = lib@PACKAGE@_media.la @@ -25,9 +30,14 @@ lib@PACKAGE@_media_la_SOURCES = \ MediaAccess.cc \ MediaHandler.cc \ Mount.cc \ + MediaNFS.cc \ + MediaCD.cc \ + MediaDIR.cc \ + MediaDISK.cc \ + MediaSMB.cc \ + MediaCIFS.cc \ MediaCurl.cc -# MediaNFS.cc lib@PACKAGE@_media_la_LIBADD = -lcurl diff --git a/zypp/media/MediaAccess.cc b/zypp/media/MediaAccess.cc index 2957c40..1b386fd 100644 --- a/zypp/media/MediaAccess.cc +++ b/zypp/media/MediaAccess.cc @@ -20,14 +20,12 @@ #include "zypp/media/MediaAccess.h" #include "zypp/media/MediaHandler.h" -/* +#include "zypp/media/MediaNFS.h" #include "zypp/media/MediaCD.h" #include "zypp/media/MediaDIR.h" #include "zypp/media/MediaDISK.h" #include "zypp/media/MediaSMB.h" #include "zypp/media/MediaCIFS.h" -#include "zypp/media/MediaNFS.h" -*/ #include "zypp/media/MediaCurl.h" using namespace std; @@ -67,47 +65,36 @@ MediaAccess::open (const Url& url, const Pathname & preferred_attach_point) close(); -#warning FIXME uncomment once media backends get ready -#if 0 - switch ( url.protocol() ) { - case Url::cd: - case Url::dvd: + std::string scheme = url.getScheme(); + if (scheme == "cd" || scheme == "dvd") _handler = new MediaCD (url,preferred_attach_point); - break; - case Url::nfs: + else if (scheme == "nfs") _handler = new MediaNFS (url,preferred_attach_point); - break; - case Url::file: - case Url::dir: +// else if (scheme == "iso") +// _handler = new MediaISO (url,preferred_attach_point); + else if (scheme == "file" || scheme == "dir") _handler = new MediaDIR (url,preferred_attach_point); - break; - case Url::hd: + else if (scheme == "hd") _handler = new MediaDISK (url,preferred_attach_point); - break; - case Url::smb: - case Url::cifs: + else if (scheme == "smb") + _handler = new MediaSMB (url,preferred_attach_point); + else if (scheme == "cifs") _handler = new MediaCIFS (url,preferred_attach_point); - break; - case Url::ftp: - case Url::http: - case Url::https: + else if (scheme == "ftp" || scheme == "http" || scheme == "https") _handler = new MediaCurl (url,preferred_attach_point); - break; - case Url::unknown: - ERR << Error::E_bad_media_type << " opening " << url << endl; - return Error::E_bad_media_type; - break; + else + { + ERR << "Error::E_bad_media_type opening " << url << endl; + ZYPP_THROW(MediaUnsupportedUrlSchemeException(url)); } // check created handler if ( !_handler ){ ERR << "Failed to create media handler" << endl; - return Error::E_system; + ZYPP_THROW(MediaSystemException(url, "Failed to create media handler")); } MIL << "Opened: " << *this << endl; - return Error::E_ok; -#endif } // Type of media if open, otherwise NONE. diff --git a/zypp/media/MediaCD.cc b/zypp/media/MediaCD.cc new file mode 100644 index 0000000..9490eb5 --- /dev/null +++ b/zypp/media/MediaCD.cc @@ -0,0 +1,326 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCD.cc + * +*/ + +#include + +#include "zypp/base/Logger.h" +#include "zypp/ExternalProgram.h" +#include "zypp/media/Mount.h" +#include "zypp/media/MediaCD.h" + +#include // strerror + +#include +#include + +#include +#include +#include + +#include + + +using namespace std; + +namespace zypp { + namespace media { + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : MediaCD +// +/////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::MediaCD + // METHOD TYPE : Constructor + // + // DESCRIPTION : + // + MediaCD::MediaCD( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, + url_r.getPathName(), // urlpath below attachpoint + false ), // does_download + _lastdev(-1) + { + string devices = _url.getQueryParam("devices"); + if (!devices.empty()) + { + string::size_type pos; + DBG << "parse " << devices << endl; + while(!devices.empty()) + { + pos = devices.find(','); + string device = devices.substr(0,pos); + if (!device.empty()) + { + _devices.push_back(device); + DBG << "use device " << device << endl; + } + if (pos!=string::npos) + devices=devices.substr(pos+1); + else + devices.erase(); + } + } + else + { + //default is /dev/cdrom; for dvd: /dev/dvd if it exists + //TODO: make configurable + string device( "/dev/cdrom" ); + if ( _url.getScheme() == "dvd" && PathInfo( "/dev/dvd" ).isBlk() ) { + device = "/dev/dvd"; + } + DBG << "use default device " << device << endl; + _devices.push_back(device); + } + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::openTray + // METHOD TYPE : bool + // + bool MediaCD::openTray( const string & device_r ) + { + int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK ); + if ( fd == -1 ) { + WAR << "Unable to open '" << device_r << "' (" << ::strerror( errno ) << ")" << endl; + return false; + } + int res = ::ioctl( fd, CDROMEJECT ); + ::close( fd ); + if ( res ) { + WAR << "Eject " << device_r << " failed (" << ::strerror( errno ) << ")" << endl; + return false; + } + MIL << "Eject " << device_r << endl; + return true; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::closeTray + // METHOD TYPE : bool + // + bool MediaCD::closeTray( const string & device_r ) + { + int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK ); + if ( fd == -1 ) { + WAR << "Unable to open '" << device_r << "' (" << ::strerror( errno ) << ")" << endl; + return false; + } + int res = ::ioctl( fd, CDROMCLOSETRAY ); + ::close( fd ); + if ( res ) { + WAR << "Close tray " << device_r << " failed (" << ::strerror( errno ) << ")" << endl; + return false; + } + DBG << "Close tray " << device_r << endl; + return true; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaCD::attachTo(bool next) + { + Mount mount; + const char *mountpoint = attachPoint().asString().c_str(); + bool mountsucceeded = false; + int count = 0; + + DBG << "next " << next << " last " << _lastdev << " lastdevice " << _mounteddevice << endl; + + if (next && _lastdev == -1) + ZYPP_THROW(MediaNotSupportedException(url())); + + string options = _url.getQueryParam("mountoptions"); + if (options.empty()) + { + options="ro"; + } + + //TODO: make configurable + list filesystems; + + // if DVD, try UDF filesystem before iso9660 + if ( _url.getScheme() == "dvd" ) + filesystems.push_back("udf"); + + filesystems.push_back("iso9660"); + + // try all devices in sequence + for (DeviceList::iterator it = _devices.begin() + ; !mountsucceeded && it != _devices.end() + ; ++it, count++ ) + { + DBG << "count " << count << endl; + if (next && count<=_lastdev ) + { + DBG << "skip" << endl; + continue; + } + + // close tray + closeTray( *it ); + + // try all filesystems in sequence + for(list::iterator fsit = filesystems.begin() + ; !mountsucceeded && fsit != filesystems.end() + ; ++fsit) + { + try { + mount.mount (*it, mountpoint, *fsit, options); + _mounteddevice = *it; + _lastdev = count; + mountsucceeded = true; + } + catch (const MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + } + } + + if (!mountsucceeded) + { + _mounteddevice.erase(); + _lastdev = -1; + // FIXME not suitable for MediaMountExeption, as device cannot be + // specified here + // errors might be different as well + ZYPP_THROW(MediaException("Error::E_mount_failed")); + } + DBG << _lastdev << " " << count << endl; + } + + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCD::releaseFrom( bool eject ) + { + if (_mounteddevice.empty()) // no device mounted + { + if (eject) // eject wanted -> eject all devices + { + for (DeviceList::iterator it = _devices.begin() + ; it != _devices.end() + ; ++it ) + { + openTray( *it ); + } + return; + } + ZYPP_THROW(MediaNotAttachedException(url())); + } + + Mount mount; + mount.umount(attachPoint().asString()); + + // eject device + if (eject) + { + openTray( _mounteddevice ); + } + + _mounteddevice.erase(); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::forceEject + // METHOD TYPE : void + // + // Asserted that media is not attached. + // + void MediaCD::forceEject() + { + if ( _mounteddevice.empty() ) { // no device mounted + for ( DeviceList::iterator it = _devices.begin(); it != _devices.end(); ++it ) { + if ( openTray( *it ) ) + break; // on 1st success + } + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCD::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCD::getFile( const Pathname & filename ) const + { + MediaHandler::getFile( filename ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCD::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCD::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaCD::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaCD::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaCD.h b/zypp/media/MediaCD.h new file mode 100644 index 0000000..87ff697 --- /dev/null +++ b/zypp/media/MediaCD.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCD.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIACD_H +#define ZYPP_MEDIA_MEDIACD_H + +#include "zypp/media/MediaHandler.h" + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaCD + /** + * @short Implementation class for CD/DVD MediaHandler + * @see MediaHandler + **/ + class MediaCD : public MediaHandler { + + private: + + unsigned long _mountflags; + + typedef std::list DeviceList; + /** list of devices to try to mount */ + DeviceList _devices; + + /** which device has been mounted */ + std::string _mounteddevice; + + /** number of last successful mounted device in list */ + int _lastdev; + + static bool openTray( const std::string & device_r ); + static bool closeTray( const std::string & device_r ); + + protected: + + MEDIA_HANDLER_API; + + virtual void forceEject(); + + public: + + MediaCD( const Url & url_r, + const Pathname & attach_point_hint_r ); + + virtual ~MediaCD() { release(); } + }; + +/////////////////////////////////////////////////////////////////// + } // namespace media +} // namespace zypp +#endif // ZYPP_MEDIA_MEDIACD_H diff --git a/zypp/media/MediaCIFS.cc b/zypp/media/MediaCIFS.cc new file mode 100644 index 0000000..f4f2133 --- /dev/null +++ b/zypp/media/MediaCIFS.cc @@ -0,0 +1,16 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCIFS.cc + * +*/ + +// +// NOTE: It's actually MediaSMB, but using "cifs" +// as vfstype for mount. +// diff --git a/zypp/media/MediaCIFS.h b/zypp/media/MediaCIFS.h new file mode 100644 index 0000000..f05b912 --- /dev/null +++ b/zypp/media/MediaCIFS.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCIFS.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIACIFS_H +#define ZYPP_MEDIA_MEDIACIFS_H + +#include "zypp/media/MediaSMB.h" + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaCIFS + /** + * @short Implementation class for CIFS MediaHandler + * + * NOTE: It's actually MediaSMB, but using "cifs" + * as vfstype for mount. + * @see MediaHandler + **/ + class MediaCIFS : public MediaSMB { + + public: + + MediaCIFS( const Url& url_r, + const Pathname & attach_point_hint_r ) + : MediaSMB( url_r, attach_point_hint_r ) + { + mountAsCIFS(); + } + }; + + } // namespace media +} // namespace zypp + +/////////////////////////////////////////////////////////////////// + +#endif // ZYPP_MEDIA_MEDIACIFS_H diff --git a/zypp/media/MediaCallbacks.cc b/zypp/media/MediaCallbacks.cc new file mode 100644 index 0000000..fe577ca --- /dev/null +++ b/zypp/media/MediaCallbacks.cc @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCallbacks.cc + * +*/ + +#include + +#include + +using namespace std; + +/////////////////////////////////////////////////////////////////// +namespace MediaCallbacks { +/////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // Reporting progress of download + /////////////////////////////////////////////////////////////////// + DownloadProgressReport downloadProgressReport; + + void DownloadProgressCallback::start( const Url & url_r, const Pathname & localpath_r ) { + } + bool DownloadProgressCallback::progress( const ProgressData & prg ) { + return true; // continue download + } + void DownloadProgressCallback::stop( PMError error ) { + } + +#if 0 + /////////////////////////////////////////////////////////////////// + // Reporting @ + /////////////////////////////////////////////////////////////////// + @Report @Report; + + void @Callback::start() { + } + void @Callback::progress( const ProgressData & prg ) { + } + void @Callback::stop( PMError error ) { + } +#endif + +/////////////////////////////////////////////////////////////////// +} // namespace MediaCallbacks +/////////////////////////////////////////////////////////////////// diff --git a/zypp/media/MediaCallbacks.h b/zypp/media/MediaCallbacks.h new file mode 100644 index 0000000..a5a7690 --- /dev/null +++ b/zypp/media/MediaCallbacks.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCallbacks.h + * +*/ + +#ifndef ZYPP_MEDIA_MEDIACALLBACKS_H +#define ZYPP_MEDIA_MEDIACALLBACKS_H + +#include + +#include "zypp/Url.h" +#include "zypp/Callback.h" + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // Reporting progress of download + /////////////////////////////////////////////////////////////////// + class DownloadProgressReport : public HACK::Callback { + virtual ~DownloadProgressReport() + {} + virtual void start( const Url & url_r, const Pathname & localpath_r ) + { } + virtual bool progress( /*const ProgressData & prg*/ ) + { return false; } + virtual void stop( Exception & excpt_r ) + { } + }; + + extern DownloadProgressReport downloadProgressReport; + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIACALLBACKS_H diff --git a/zypp/media/MediaCurl.cc b/zypp/media/MediaCurl.cc index ad1ec6f..cfe2472 100644 --- a/zypp/media/MediaCurl.cc +++ b/zypp/media/MediaCurl.cc @@ -18,7 +18,7 @@ //#include #include "zypp/media/MediaCurl.h" -//#include "zypp/media/MediaCallbacks.h" +#include "zypp/media/MediaCallbacks.h" #include #include @@ -29,7 +29,6 @@ using namespace std; using namespace zypp::base; -//using namespace MediaCallbacks; namespace zypp { namespace media { @@ -102,11 +101,8 @@ void MediaCurl::attachTo (bool next) if ( next ) ZYPP_THROW( MediaException("Error::E_not_supported_by_media") ); -#warning FIXME implement check for URL validity -#if 0 if ( !_url.isValid() ) - ZYPP_THROW( MediaException("Error::E_bad_url") ); -#endif + ZYPP_THROW(MediaBadUrlException(_url)); _curl = curl_easy_init(); if ( !_curl ) { @@ -368,11 +364,8 @@ void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target { DBG << filename.asString() << endl; -#warning FIXME implement check for URL validity -#if 0 if(!_url.isValid()) - ZYPP_THROW( MediaException(string("Error::E_bad_url") + " " + _url.toString()) ); -#endif + ZYPP_THROW(MediaBadUrlException(_url)); if(_url.getHost().empty()) ZYPP_THROW( MediaException("Error::E_no_host_specified") ); @@ -553,19 +546,9 @@ void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const { filesystem::DirContent content; - try { - getDirInfo( content, dirname, /*dots*/false ); - } - catch (const MediaException & excpt_r) - { -#warning FIXME rethrow -#if 0 - ZYPP_RETHROW(excpt_r); -#endif - } + getDirInfo( content, dirname, /*dots*/false ); for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) { - try { Pathname filename = dirname + it->name; int res = 0; @@ -588,14 +571,6 @@ void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const // don't provide devices, sockets, etc. break; } - } - catch (const MediaException & excpt_r) - { -#warning FIXME rethrow -#if 0 - ZYPP_RETHROW(excpt_r); -#endif - } } } @@ -610,13 +585,7 @@ void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const void MediaCurl::getDirInfo( std::list & retlist, const Pathname & dirname, bool dots ) const { - try { - getDirectoryYast( retlist, dirname, dots ); - } - catch (const MediaException & excpt_r) - { - ZYPP_THROW( MediaException("Error::E_not_supported_by_media") ); - } + getDirectoryYast( retlist, dirname, dots ); } /////////////////////////////////////////////////////////////////// @@ -630,13 +599,7 @@ void MediaCurl::getDirInfo( std::list & retlist, void MediaCurl::getDirInfo( filesystem::DirContent & retlist, const Pathname & dirname, bool dots ) const { - try { - getDirectoryYast( retlist, dirname, dots ); - } - catch (const MediaException & excpt_r) - { - ZYPP_THROW( MediaException("Error::E_not_supported_by_media") ); - } + getDirectoryYast( retlist, dirname, dots ); } /////////////////////////////////////////////////////////////////// diff --git a/zypp/media/MediaDIR.cc b/zypp/media/MediaDIR.cc new file mode 100644 index 0000000..447c2d8 --- /dev/null +++ b/zypp/media/MediaDIR.cc @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDIR.cc + * +*/ + +#include + +#include "zypp/base/Logger.h" +#include "zypp/media/MediaDIR.h" + +#include +#include + +using namespace std; + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDIR + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::MediaDIR + // METHOD TYPE : Constructor + // + // DESCRIPTION : Attach point is always '/', as files are not copied. + // Thus attach_point_hint_r is ignored. + // + MediaDIR::MediaDIR( const Url & url_r, + const Pathname & /*attach_point_hint_r*/ ) + : MediaHandler( url_r, url_r.getPathName(), + "/", // urlpath at attachpoint + false ) // does_download + { + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaDIR::attachTo(bool next) + { + if(next) + ZYPP_THROW(MediaNotSupportedException(url())); + } + + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDIR::releaseFrom( bool eject ) + { + return; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDIR::getFile( const Pathname & filename ) const + { + MediaHandler::getFile( filename ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDIR::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDIR::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDIR::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDIR::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaDIR.h b/zypp/media/MediaDIR.h new file mode 100644 index 0000000..0c6056d --- /dev/null +++ b/zypp/media/MediaDIR.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDIR.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIADIR_H +#define ZYPP_MEDIA_MEDIADIR_H + +#include "zypp/media/MediaHandler.h" + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDIR + + /** + * @short Implementation class for DIR MediaHandler + * @see MediaHandler + **/ + class MediaDIR : public MediaHandler { + + protected: + + MEDIA_HANDLER_API; + + public: + + MediaDIR( const Url & url_r, + const Pathname & attach_point_hint_r ); + + virtual ~MediaDIR() { release(); } + }; + + /////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIADIR_H diff --git a/zypp/media/MediaDISK.cc b/zypp/media/MediaDISK.cc new file mode 100644 index 0000000..7921a7f --- /dev/null +++ b/zypp/media/MediaDISK.cc @@ -0,0 +1,160 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDISK.h + * +*/ + +#include + +#include "zypp/base/Logger.h" +#include "zypp/media/Mount.h" +#include "zypp/media/MediaDISK.h" + +#include +#include +#include +#include + +using namespace std; + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDISK + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::MediaDISK + // METHOD TYPE : Constructor + // + // DESCRIPTION : + // + MediaDISK::MediaDISK( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, + url_r.getPathName(), // urlpath below attachpoint + false ) // does_download + { + _device = _url.getQueryParam("device"); + _filesystem = _url.getQueryParam("filesystem"); + if(_filesystem.empty()) + _filesystem="auto"; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaDISK::attachTo(bool next) + { + if(next) + ZYPP_THROW(MediaNotSupportedException(url())); + // FIXME + // do mount --bind / to + // mount /dev/ /tmp_mount + // mount /tmp_mount/ --bind -o ro + // FIXME: try all filesystems + + if(_device.empty()) + ZYPP_THROW(MediaBadUrlEmptyDestinationException(url())); + + if(_filesystem.empty()) + ZYPP_THROW(MediaBadUrlEmptyFilesystemException(url())); + + Mount mount; + const char *mountpoint = attachPoint().asString().c_str(); + string options = _url.getQueryParam("mountoptions"); + if(options.empty()) + { + options="ro"; + } + + mount.mount(_device,mountpoint,_filesystem,options); + } + + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDISK::releaseFrom( bool eject ) + { + Mount mount; + + mount.umount(attachPoint().asString()); + } + + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDISK::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDISK::getFile (const Pathname & filename) const + { + MediaHandler::getFile( filename ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDISK::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDISK::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDISK::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaDISK.h b/zypp/media/MediaDISK.h new file mode 100644 index 0000000..ea6d4b0 --- /dev/null +++ b/zypp/media/MediaDISK.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDISK.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIADISK_H +#define ZYPP_MEDIA_MEDIADISK_H + +#include "zypp/media/MediaHandler.h" + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDISK + /** + * @short Implementation class for DISK MediaHandler + * @see MediaHandler + **/ + class MediaDISK : public MediaHandler { + + private: + + unsigned long _mountflags; + + std::string _device; + std::string _filesystem; + + protected: + + MEDIA_HANDLER_API; + + public: + + MediaDISK( const Url & url_r, + const Pathname & attach_point_hint_r ); + + virtual ~MediaDISK() { release(); } + }; + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIADISK_H diff --git a/zypp/media/MediaException.cc b/zypp/media/MediaException.cc index 9be0079..a7ac548 100644 --- a/zypp/media/MediaException.cc +++ b/zypp/media/MediaException.cc @@ -86,6 +86,31 @@ namespace zypp return str << "Malformed URL: " << _url << endl; } + std::ostream & MediaBadUrlEmptyHostException::dumpOn( std::ostream & str) const + { + return str << "Empty host name in URL: " << _url << endl; + } + + std::ostream & MediaBadUrlEmptyFilesystemException::dumpOn( std::ostream & str) const + { + return str << "Empty filesystem in URL: " << _url << endl; + } + + std::ostream & MediaBadUrlEmptyDestinationException::dumpOn( std::ostream & str) const + { + return str << "Empty destination in URL: " << _url << endl; + } + + std::ostream & MediaUnsupportedUrlSchemeException::dumpOn( std::ostream & str) const + { + return str << "Unsupported URL scheme in URL: " << _url << endl; + } + + std::ostream & MediaNotSupportedException::dumpOn( std::ostream & str) const + { + return str << "Operation not supported by media: " << _url << endl; + } + ///////////////////////////////////////////////////////////////// } // namespace media diff --git a/zypp/media/MediaException.h b/zypp/media/MediaException.h index 798c1bf..8c285e8 100644 --- a/zypp/media/MediaException.h +++ b/zypp/media/MediaException.h @@ -227,11 +227,65 @@ namespace zypp virtual ~MediaBadUrlException() throw() {}; protected: virtual std::ostream & dumpOn( std::ostream & str ) const; - private: std::string _url; }; + class MediaBadUrlEmptyHostException : public MediaBadUrlException + { + public: + MediaBadUrlEmptyHostException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + virtual ~MediaBadUrlEmptyHostException() throw() {}; + protected: + virtual std::ostream & dumpOn( std::ostream & str ) const; + }; + class MediaBadUrlEmptyFilesystemException : public MediaBadUrlException + { + public: + MediaBadUrlEmptyFilesystemException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + virtual ~MediaBadUrlEmptyFilesystemException() throw() {}; + protected: + virtual std::ostream & dumpOn( std::ostream & str ) const; + }; + + class MediaBadUrlEmptyDestinationException : public MediaBadUrlException + { + public: + MediaBadUrlEmptyDestinationException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + virtual ~MediaBadUrlEmptyDestinationException() throw() {}; + protected: + virtual std::ostream & dumpOn( std::ostream & str ) const; + }; + + class MediaUnsupportedUrlSchemeException : public MediaBadUrlException + { + public: + MediaUnsupportedUrlSchemeException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + virtual ~MediaUnsupportedUrlSchemeException() throw() {}; + protected: + virtual std::ostream & dumpOn( std::ostream & str ) const; + }; + + class MediaNotSupportedException : public MediaException + { + public: + MediaNotSupportedException(const Url & url_r) + : MediaException() + , _url(url_r.toString()) + {} + virtual ~MediaNotSupportedException() throw() {}; + protected: + virtual std::ostream & dumpOn( std::ostream & str ) const; + std::string _url; + }; ///////////////////////////////////////////////////////////////// } // namespace media diff --git a/zypp/media/MediaNFS.cc b/zypp/media/MediaNFS.cc new file mode 100644 index 0000000..8fd3963 --- /dev/null +++ b/zypp/media/MediaNFS.cc @@ -0,0 +1,170 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaNFS.cc + * +*/ + +#include + +#include "zypp/base/Logger.h" +#include "zypp/base/String.h" +#include "zypp/media/MediaNFS.h" +#include "zypp/media/Mount.h" + +#include + +using namespace std; + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaNFS + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::MediaNFS + // METHOD TYPE : Constructor + // + // DESCRIPTION : + // + MediaNFS::MediaNFS( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, + "/", // urlpath at attachpoint + false ) // does_download + { + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaNFS::attachTo(bool next) + { + if(_url.getHost().empty()) + ZYPP_THROW(MediaBadUrlEmptyHostException(_url)); + if(next) + ZYPP_THROW(MediaNotSupportedException(_url)); + + const char* const filesystem = "nfs"; + const char *mountpoint = attachPoint().asString().c_str(); + Mount mount; + + string path = _url.getHost(); + path += ':'; + path += _url.getPathName(); + + string options = _url.getQueryParam("mountoptions"); + if(options.empty()) + { + options="ro"; + } + + // Add option "nolock", unless option "lock" or "unlock" is already set. + // This should prevent the mount command hanging when the portmapper isn't + // running. + vector optionList; +#warning FIXME once the function is in str namespace +#if 0 + str::split( options, optionList, "," ); +#endif + vector::const_iterator it; + for( it = optionList.begin(); it != optionList.end(); ++it ) { + if ( *it == "lock" || *it == "nolock" ) break; + } + if ( it == optionList.end() ) { + optionList.push_back( "nolock" ); +#warning FIXME once the function is in str namespace +#if 0 + options = str::join( optionList, "," ); +#endif + } + + mount.mount(path,mountpoint,filesystem,options); + } + + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaNFS::releaseFrom( bool eject ) + { + Mount mount; + mount.umount(attachPoint().asString()); + } + + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaNFS::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaNFS::getFile (const Pathname & filename) const + { + MediaHandler::getFile( filename );; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaNFS::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaNFS::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaNFS::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaNFS::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaNFS.h b/zypp/media/MediaNFS.h new file mode 100644 index 0000000..4962b7a --- /dev/null +++ b/zypp/media/MediaNFS.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaNFS.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIANFS_H +#define ZYPP_MEDIA_MEDIANFS_H + +#include "zypp/media/MediaHandler.h" + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaNFS + /** + * @short Implementation class for NFS MediaHandler + * @see MediaHandler + **/ + class MediaNFS : public MediaHandler { + + protected: + + MEDIA_HANDLER_API; + + public: + + MediaNFS( const Url& url_r, + const Pathname & attach_point_hint_r ); + + virtual ~MediaNFS() { release(); } + }; + + /////////////////////////////////////////////////////////////////// + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIANFS_H diff --git a/zypp/media/MediaSMB.cc b/zypp/media/MediaSMB.cc new file mode 100644 index 0000000..ea8e83c --- /dev/null +++ b/zypp/media/MediaSMB.cc @@ -0,0 +1,273 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaSMB.cc + * +*/ + +#include +#include + +#include "zypp/base/Logger.h" +#include "zypp/TmpPath.h" +#include "zypp/KVMap.h" +#include "zypp/media/Mount.h" +#include "zypp/media/MediaSMB.h" + +#include +#include +#include +#include + +using namespace std; + +namespace zypp { + namespace media { + + /****************************************************************** + ** + ** + ** FUNCTION NAME : getShare + ** FUNCTION TYPE : inline Pathname + ** + ** Get the 1st path component (CIFS share name). + */ + inline string getShare( Pathname spath_r ) + { + if ( spath_r.empty() ) + return string(); + + string share( spath_r.absolutename().asString() ); + string::size_type sep = share.find( "/", 1 ); + if ( sep == string::npos ) + share = share.erase( 0, 1 ); // nothing but the share name in spath_r + else + share = share.substr( 1, sep-1 ); + + // deescape %2f in sharename + while ( (sep = share.find( "%2f" )) != string::npos ) { + share.replace( sep, 3, "/" ); + } + + return share; + } + + /****************************************************************** + ** + ** + ** FUNCTION NAME : stripShare + ** FUNCTION TYPE : inline Pathname + ** + ** Strip off the 1st path component (CIFS share name). + */ + inline Pathname stripShare( Pathname spath_r ) + { + if ( spath_r.empty() ) + return Pathname(); + + string striped( spath_r.absolutename().asString() ); + string::size_type sep = striped.find( "/", 1 ); + if ( sep == string::npos ) + return "/"; // nothing but the share name in spath_r + + return striped.substr( sep ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaSMB + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaSMB::MediaSMB + // METHOD TYPE : Constructor + // + // DESCRIPTION : + // + MediaSMB::MediaSMB( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, + stripShare( url_r.getPathName() ), // urlpath WITHOUT share name at attachpoint + false ) // does_download + , _vfstype( "smbfs" ) + { + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaSMB::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint + // is a directory. + // + // NOTE: The implementation currently serves both, "smbfs" + // and "cifs". The only difference is the vfstype passed to + // the mount command. + // + void MediaSMB::attachTo(bool next) + { + if(_url.getHost().empty()) + ZYPP_THROW(MediaBadUrlEmptyHostException(_url)); + if(next) + ZYPP_THROW(MediaNotSupportedException(_url)); + + const char *mountpoint = attachPoint().asString().c_str(); + Mount mount; + + string path = "//"; + path += _url.getHost() + "/" + getShare( _url.getPathName() ); + + Mount::Options options( _url.getQueryParam("mountoptions") ); + string username = _url.getUsername(); + string password = _url.getPassword(); + + options["guest"]; // prevent smbmount from asking for password + + if ( ! options.has( "rw" ) ) { + options["ro"]; + } + + Mount::Options::iterator toEnv; + + // extract 'username', do not overwrite any _url.username + toEnv = options.find("username"); + if ( toEnv != options.end() ) { + if ( username.empty() ) + username = toEnv->second; + options.erase( toEnv ); + } + toEnv = options.find("user"); // actually cifs specific + if ( toEnv != options.end() ) { + if ( username.empty() ) + username = toEnv->second; + options.erase( toEnv ); + } + + // extract 'password', do not overwrite any _url.password + toEnv = options.find("password"); + if ( toEnv != options.end() ) { + if ( password.empty() ) + password = toEnv->second; + options.erase( toEnv ); + } + toEnv = options.find("pass"); // actually cifs specific + if ( toEnv != options.end() ) { + if ( password.empty() ) + password = toEnv->second; + options.erase( toEnv ); + } + + // look for a workgroup + string workgroup = _url.getQueryParam("workgroup"); + if ( workgroup.size() ) { + options["workgroup"] = workgroup; + } + + // pass 'username' and 'password' via environment + Mount::Environment environment; + if ( username.size() ) + environment["USER"] = username; + if ( password.size() ) + environment["PASSWD"] = password; + + ////////////////////////////////////////////////////// + // In case we need a tmpfile, credentials will remove + // it in it's destructor after the mout call below. + filesystem::TmpPath credentials; + if ( username.size() || password.size() ) + { + filesystem::TmpFile tmp; + ofstream outs( tmp.path().asString().c_str() ); + outs << "username=" << username << endl; + outs << "password=" << password << endl; + outs.close(); + + credentials = tmp; + options["credentials"] = credentials.path().asString(); + } + // + ////////////////////////////////////////////////////// + + mount.mount( path, mountpoint, _vfstype, + options.asString(), environment ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaSMB::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaSMB::releaseFrom( bool eject ) + { + Mount mount; + mount.umount(attachPoint().asString()); + } + + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaSMB::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaSMB::getFile (const Pathname & filename) const + { + MediaHandler::getFile( filename ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaSMB::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaSMB::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaSMB::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaSMB::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaSMB::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaSMB::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaSMB.h b/zypp/media/MediaSMB.h new file mode 100644 index 0000000..cb1495f --- /dev/null +++ b/zypp/media/MediaSMB.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaSMB.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIASMB_H +#define ZYPP_MEDIA_MEDIASMB_H + +#include "zypp/media/MediaHandler.h" + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaSMB + /** + * @short Implementation class for SMB MediaHandler + * + * NOTE: The implementation currently serves both, "smbfs" + * and "cifs". The only difference is the vfstype passed to + * the mount command. + * @see MediaHandler + **/ + class MediaSMB : public MediaHandler { + + private: + + /** + * vfstype for mount. This is either "smbfs" + * or "cifs" (rewritten by MediaCIFS). + **/ + const char* _vfstype; + + protected: + + MEDIA_HANDLER_API; + + /** + * MediaCIFS rewrites the vfstype to "cifs" + * within it's constructor. + **/ + void mountAsCIFS() { _vfstype = "cifs"; } + + public: + + MediaSMB( const Url& url_r, + const Pathname & attach_point_hint_r ); + + virtual ~MediaSMB() { release(); } + }; + +///////////////////////////////////////////////////////////////////A + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIASMB_H diff --git a/zypp/media/Mount.cc b/zypp/media/Mount.cc index 2d01dea..3dfd8d5 100644 --- a/zypp/media/Mount.cc +++ b/zypp/media/Mount.cc @@ -1,22 +1,14 @@ /*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | | | -| __ __ ____ _____ ____ | -| \ \ / /_ _/ ___|_ _|___ \ | -| \ V / _` \___ \ | | __) | | -| | | (_| |___) || | / __/ | -| |_|\__,_|____/ |_| |_____| | -| | -| core system | -| (C) 2002 SuSE AG | -\----------------------------------------------------------------------/ - - File: Mount.cc - Purpose: Implement interface to mount program - Author: Ludwig Nussel - Maintainer: Ludwig Nussel - -/-*/ - +\---------------------------------------------------------------------*/ +/** \file zypp/media/Mount.cc + * +*/ #include #include diff --git a/zypp/media/Mount.h b/zypp/media/Mount.h index 4aa76b3..662965f 100644 --- a/zypp/media/Mount.h +++ b/zypp/media/Mount.h @@ -1,22 +1,14 @@ /*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | | | -| __ __ ____ _____ ____ | -| \ \ / /_ _/ ___|_ _|___ \ | -| \ V / _` \___ \ | | __) | | -| | | (_| |___) || | / __/ | -| |_|\__,_|____/ |_| |_____| | -| | -| core system | -| (C) 2002 SuSE AG | -\----------------------------------------------------------------------/ - - File: Wget.h - Purpose: Declare interface to mount program - Author: Ludwig Nussel - Maintainer: Ludwig Nussel - -/-*/ - +\---------------------------------------------------------------------*/ +/** \file zypp/media/Mount.h + * +*/ // -*- C++ -*- @@ -27,6 +19,7 @@ #include #include "zypp/ExternalProgram.h" +#include "zypp/KVMap.h" namespace zypp { namespace media { @@ -47,10 +40,7 @@ namespace zypp { /** * 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 + typedef KVMap > Options; public: