MediaAccess.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00013 #include <ctype.h>
00014 
00015 #include <iostream>
00016 #include <map>
00017 
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/ZConfig.h"
00020 #include "zypp/PluginScript.h"
00021 #include "zypp/ExternalProgram.h"
00022 
00023 #include "zypp/media/MediaException.h"
00024 #include "zypp/media/MediaAccess.h"
00025 #include "zypp/media/MediaHandler.h"
00026 
00027 #include "zypp/media/MediaNFS.h"
00028 #include "zypp/media/MediaCD.h"
00029 #include "zypp/media/MediaDIR.h"
00030 #include "zypp/media/MediaDISK.h"
00031 #include "zypp/media/MediaCIFS.h"
00032 #include "zypp/media/MediaCurl.h"
00033 #include "zypp/media/MediaAria2c.h"
00034 #include "zypp/media/MediaISO.h"
00035 #include "zypp/media/MediaPlugin.h"
00036 #include "zypp/media/UrlResolverPlugin.h"
00037 
00038 using namespace std;
00039 
00040 namespace zypp {
00041   namespace media {
00042 
00044 //
00045 //      CLASS NAME : MediaAccess
00046 //
00048 
00049 const Pathname MediaAccess::_noPath; // empty path
00050 
00052 // constructor
00053 MediaAccess::MediaAccess ()
00054     : _handler (0)
00055 {
00056 }
00057 
00058 // destructor
00059 MediaAccess::~MediaAccess()
00060 {
00061   try
00062     {
00063       close(); // !!! make sure handler gets properly deleted.
00064     }
00065   catch(...) {}
00066 }
00067 
00068 AttachedMedia
00069 MediaAccess::attachedMedia() const
00070 {
00071         return _handler ? _handler->attachedMedia()
00072                         : AttachedMedia();
00073 }
00074 
00075 bool
00076 MediaAccess::isSharedMedia() const
00077 {
00078         return _handler ? _handler->isSharedMedia()
00079                         : false;
00080 }
00081 
00082 void
00083 MediaAccess::resetParentId()
00084 {
00085         if( _handler) _handler->resetParentId();
00086 }
00087 
00088 bool
00089 MediaAccess::dependsOnParent() const
00090 {
00091         return _handler ? _handler->dependsOnParent() : false;
00092 }
00093 
00094 bool
00095 MediaAccess::dependsOnParent(MediaAccessId parentId,
00096                              bool exactIdMatch) const
00097 {
00098         return _handler ? _handler->dependsOnParent(parentId, exactIdMatch)
00099                         : false;
00100 }
00101 
00102 // open URL
00103 void
00104 MediaAccess::open (const Url& o_url, const Pathname & preferred_attach_point)
00105 {
00106     if(!o_url.isValid()) {
00107         MIL << "Url is not valid" << endl;
00108         ZYPP_THROW(MediaBadUrlException(o_url));
00109     }
00110 
00111     close();
00112 
00113     UrlResolverPlugin::HeaderList custom_headers;
00114     Url url = UrlResolverPlugin::resolveUrl(o_url, custom_headers);
00115     
00116     std::string scheme = url.getScheme();
00117     MIL << "Trying scheme '" << scheme << "'" << endl;
00118 
00119     /*
00120     ** WARNING: Don't forget to update MediaAccess::downloads(url)
00121     **          if you are adding a new url scheme / handler!
00122     */
00123     if (scheme == "cd" || scheme == "dvd")
00124         _handler = new MediaCD (url,preferred_attach_point);
00125     else if (scheme == "nfs" || scheme == "nfs4")
00126         _handler = new MediaNFS (url,preferred_attach_point);
00127     else if (scheme == "iso")
00128         _handler = new MediaISO (url,preferred_attach_point);
00129     else if (scheme == "file" || scheme == "dir")
00130         _handler = new MediaDIR (url,preferred_attach_point);
00131     else if (scheme == "hd")
00132         _handler = new MediaDISK (url,preferred_attach_point);
00133     else if (scheme == "cifs" || scheme == "smb")
00134         _handler = new MediaCIFS (url,preferred_attach_point);
00135     else if (scheme == "ftp" || scheme == "http" || scheme == "https")
00136     {
00137         // Another good idea would be activate MediaAria2c handler via external var
00138         bool use_aria = false;
00139         bool use_multicurl = true;
00140         const char *ariaenv = getenv( "ZYPP_ARIA2C" );
00141         const char *multicurlenv = getenv( "ZYPP_MULTICURL" );
00142         // if user disabled it manually
00143         if ( use_multicurl && multicurlenv && ( strcmp(multicurlenv, "0" ) == 0 ) )
00144         {
00145             WAR << "multicurl manually disabled." << endl;
00146             use_multicurl = false;
00147         }
00148         else if ( !use_multicurl && multicurlenv && ( strcmp(multicurlenv, "1" ) == 0 ) )
00149         {
00150             WAR << "multicurl manually enabled." << endl;
00151             use_multicurl = true;
00152         }
00153         // if user disabled it manually
00154         if ( use_aria && ariaenv && ( strcmp(ariaenv, "0" ) == 0 ) )
00155         {
00156             WAR << "aria2c manually disabled. Falling back to curl" << endl;
00157             use_aria = false;
00158         }
00159         else if ( !use_aria && ariaenv && ( strcmp(ariaenv, "1" ) == 0 ) )
00160         {
00161             WAR << "aria2c manually enabled." << endl;
00162             use_aria = true;
00163         }
00164 
00165         // disable if it does not exist
00166         if ( use_aria && ! MediaAria2c::existsAria2cmd() )
00167         {
00168             WAR << "aria2c not found. Falling back to curl" << endl;
00169             use_aria = false;
00170         }
00171 
00172         MediaCurl *curl;        
00173 
00174         if ( use_aria )
00175             curl = new MediaAria2c (url,preferred_attach_point);        
00176               else
00177             curl = new MediaCurl (url,preferred_attach_point);
00178         
00179         UrlResolverPlugin::HeaderList::const_iterator it;
00180         for (it = custom_headers.begin();
00181              it != custom_headers.end();
00182              ++it) {
00183             std::string header = it->first + ": " + it->second;            
00184             MIL << "Added custom header -> " << header << endl;
00185             curl->settings().addHeader(header);
00186         }
00187         _handler = curl;        
00188     }
00189     else if (scheme == "plugin" )
00190         _handler = new MediaPlugin (url,preferred_attach_point);
00191     else
00192     {
00193         ZYPP_THROW(MediaUnsupportedUrlSchemeException(url));
00194     }
00195 
00196     // check created handler
00197     if ( !_handler ){
00198       ERR << "Failed to create media handler" << endl;
00199       ZYPP_THROW(MediaSystemException(url, "Failed to create media handler"));
00200     }
00201 
00202     MIL << "Opened: " << *this << endl;
00203 }
00204 
00205 // Type of media if open, otherwise NONE.
00206 std::string
00207 MediaAccess::protocol() const
00208 {
00209   if ( !_handler )
00210     return "unknown";
00211 
00212   return _handler->protocol();
00213 }
00214 
00215 bool
00216 MediaAccess::downloads() const
00217 {
00218         return _handler ? _handler->downloads() : false;
00219 }
00220 
00222 //
00223 //
00224 //      METHOD NAME : MediaAccess::url
00225 //      METHOD TYPE : Url
00226 //
00227 Url MediaAccess::url() const
00228 {
00229   if ( !_handler )
00230     return Url();
00231 
00232   return _handler->url();
00233 }
00234 
00235 // close handler
00236 void
00237 MediaAccess::close ()
00238 {
00240   // !!! make shure handler gets properly deleted.
00241   // I.e. release attached media before deleting the handler.
00243   if ( _handler ) {
00244     try {
00245       _handler->release();
00246     }
00247     catch (const MediaException & excpt_r)
00248     {
00249       ZYPP_CAUGHT(excpt_r);
00250       WAR << "Close: " << *this << " (" << excpt_r << ")" << endl;
00251       ZYPP_RETHROW(excpt_r);
00252     }
00253     MIL << "Close: " << *this << " (OK)" << endl;
00254     delete _handler;
00255     _handler = 0;
00256   }
00257 }
00258 
00259 
00260 // attach media
00261 void MediaAccess::attach (bool next)
00262 {
00263   if ( !_handler ) {
00264     ZYPP_THROW(MediaNotOpenException("attach"));
00265   }
00266   _handler->attach(next);
00267 }
00268 
00269 // True if media is open and attached.
00270 bool
00271 MediaAccess::isAttached() const
00272 {
00273   return( _handler && _handler->isAttached() );
00274 }
00275 
00276 
00277 bool MediaAccess::hasMoreDevices() const
00278 {
00279   return _handler && _handler->hasMoreDevices();
00280 }
00281 
00282 
00283 void
00284 MediaAccess::getDetectedDevices(std::vector<std::string> & devices,
00285                                 unsigned int & index) const
00286 {
00287   if (_handler)
00288   {
00289     _handler->getDetectedDevices(devices, index);
00290     return;
00291   }
00292 
00293   if (!devices.empty())
00294     devices.clear();
00295   index = 0;
00296 }
00297 
00298 
00299 // local directory that corresponds to medias url
00300 // If media is not open an empty pathname.
00301 Pathname
00302 MediaAccess::localRoot() const
00303 {
00304   if ( !_handler )
00305     return _noPath;
00306 
00307   return _handler->localRoot();
00308 }
00309 
00310 // Short for 'localRoot() + pathname', but returns an empty
00311 // * pathname if media is not open.
00312 Pathname
00313 MediaAccess::localPath( const Pathname & pathname ) const
00314 {
00315   if ( !_handler )
00316     return _noPath;
00317 
00318   return _handler->localPath( pathname );
00319 }
00320 
00321 void
00322 MediaAccess::disconnect()
00323 {
00324   if ( !_handler )
00325     ZYPP_THROW(MediaNotOpenException("disconnect"));
00326 
00327   _handler->disconnect();
00328 }
00329 
00330 
00331 void
00332 MediaAccess::release( const std::string & ejectDev )
00333 {
00334   if ( !_handler )
00335     return;
00336 
00337   _handler->release( ejectDev );
00338 }
00339 
00340 // provide file denoted by path to attach dir
00341 //
00342 // filename is interpreted relative to the attached url
00343 // and a path prefix is preserved to destination
00344 void
00345 MediaAccess::provideFile( const Pathname & filename ) const
00346 {
00347   if ( !_handler ) {
00348     ZYPP_THROW(MediaNotOpenException("provideFile(" + filename.asString() + ")"));
00349   }
00350 
00351   _handler->provideFile( filename );
00352 }
00353 
00354 void
00355 MediaAccess::releaseFile( const Pathname & filename ) const
00356 {
00357   if ( !_handler )
00358     return;
00359 
00360   _handler->releaseFile( filename );
00361 }
00362 
00363 // provide directory tree denoted by path to attach dir
00364 //
00365 // dirname is interpreted relative to the attached url
00366 // and a path prefix is preserved to destination
00367 void
00368 MediaAccess::provideDir( const Pathname & dirname ) const
00369 {
00370   if ( !_handler ) {
00371     ZYPP_THROW(MediaNotOpenException("provideDir(" + dirname.asString() + ")"));
00372   }
00373 
00374   _handler->provideDir( dirname );
00375 }
00376 
00377 void
00378 MediaAccess::provideDirTree( const Pathname & dirname ) const
00379 {
00380   if ( !_handler ) {
00381     ZYPP_THROW(MediaNotOpenException("provideDirTree(" + dirname.asString() + ")"));
00382   }
00383 
00384   _handler->provideDirTree( dirname );
00385 }
00386 
00387 void
00388 MediaAccess::releaseDir( const Pathname & dirname ) const
00389 {
00390   if ( !_handler )
00391     return;
00392 
00393   _handler->releaseDir( dirname );
00394 }
00395 
00396 void
00397 MediaAccess::releasePath( const Pathname & pathname ) const
00398 {
00399   if ( !_handler )
00400     return;
00401 
00402   _handler->releasePath( pathname );
00403 }
00404 
00405 // Return content of directory on media
00406 void
00407 MediaAccess::dirInfo( std::list<std::string> & retlist, const Pathname & dirname, bool dots ) const
00408 {
00409   retlist.clear();
00410 
00411   if ( !_handler ) {
00412     ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
00413   }
00414 
00415   _handler->dirInfo( retlist, dirname, dots );
00416 }
00417 
00418 // Return content of directory on media
00419 void
00420 MediaAccess::dirInfo( filesystem::DirContent & retlist, const Pathname & dirname, bool dots ) const
00421 {
00422   retlist.clear();
00423 
00424   if ( !_handler ) {
00425     ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
00426   }
00427 
00428   _handler->dirInfo( retlist, dirname, dots );
00429 }
00430 
00431 // return if a file exists
00432 bool
00433 MediaAccess::doesFileExist( const Pathname & filename ) const
00434 {
00435   if ( !_handler ) {
00436     ZYPP_THROW(MediaNotOpenException("doesFileExist(" + filename.asString() + ")"));
00437   }
00438 
00439   return _handler->doesFileExist( filename );
00440 }
00441 
00442 std::ostream &
00443 MediaAccess::dumpOn( std::ostream & str ) const
00444 {
00445   if ( !_handler )
00446     return str << "MediaAccess( closed )";
00447 
00448   str << _handler->protocol() << "(" << *_handler << ")";
00449   return str;
00450 }
00451 
00452 void MediaAccess::getFile( const Url &from, const Pathname &to )
00453 {
00454   DBG << "From: " << from << endl << "To: " << to << endl;
00455 
00456   Pathname path = from.getPathData();
00457   Pathname dir = path.dirname();
00458   string base = path.basename();
00459 
00460   Url u = from;
00461   u.setPathData( dir.asString() );
00462 
00463   MediaAccess media;
00464 
00465   try {
00466     media.open( u );
00467     media.attach();
00468     media._handler->provideFileCopy( base, to );
00469     media.release();
00470   }
00471   catch (const MediaException & excpt_r)
00472   {
00473     ZYPP_RETHROW(excpt_r);
00474   }
00475 }
00476 
00477     std::ostream & operator<<( std::ostream & str, const MediaAccess & obj )
00478     { return obj.dumpOn( str ); }
00479 
00481   } // namespace media
00482 } // namespace zypp

doxygen