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