SourceImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <fstream>
00014 #include "zypp/base/Logger.h"
00015 #include "zypp/base/Gettext.h"
00016 #include "zypp/Digest.h"
00017 #include "zypp/SourceFactory.h"
00018 #include "zypp/source/SourceImpl.h"
00019 #include "zypp/ZYppCallbacks.h"
00020 #include "zypp/SourceManager.h"
00021 #include "zypp/ZYppFactory.h"
00022 #include <fstream>
00023 
00024 using std::endl;
00025 
00027 namespace zypp
00028 { 
00029 
00030 namespace source
00031 { 
00032 
00033 IMPL_PTR_TYPE(SourceImpl);
00034 
00035 // Taken from KApplication
00036 static int random()
00037 {
00038   static bool init = false;
00039   if (!init)
00040   {
00041     unsigned int seed;
00042     init = true;
00043     int fd = open("/dev/urandom", O_RDONLY);
00044     if (fd < 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed))
00045     {
00046       // No /dev/urandom... try something else.
00047       srand(getpid());
00048       seed = rand()+time(0);
00049     }
00050     if (fd >= 0) close(fd);
00051     srand(seed);
00052   }
00053   return rand();
00054 }
00055 
00056 // Taken from KApplication
00057 static std::string randomString(int length)
00058 {
00059   if (length <=0 ) return std::string();
00060 
00061   std::string str;
00062   str.resize( length );
00063   int i = 0;
00064   while (length--)
00065   {
00066     int r=random() % 62;
00067     r+=48;
00068     if (r>57) r+=7;
00069     if (r>90) r+=6;
00070     str[i++] =  char(r);
00071     // so what if I work backwards?
00072   }
00073   return str;
00074 }
00075 
00076 
00077 class DownloadProgressPackageReceiver : public callback::ReceiveReport<media::DownloadProgressReport>
00078 {
00079   callback::SendReport <DownloadResolvableReport> & _report;
00080   Resolvable::constPtr _resolvable;
00081 
00082 public:
00083 
00084   DownloadProgressPackageReceiver ( callback::SendReport <DownloadResolvableReport> & report_r, Resolvable::constPtr resolvable_r )
00085       : _report (report_r), _resolvable (resolvable_r)
00086   {}
00087 
00088   virtual ~DownloadProgressPackageReceiver ()
00089   {}
00090   virtual void reportbegin()
00091   {}
00092   virtual void reportend()
00093   {}
00094 
00099   virtual bool progress( int percent, const Url& )
00100   {
00101     return _report->progress( percent, _resolvable );
00102   }
00103 };
00104 
00105 
00106 class DownloadProgressFileReceiver : public callback::ReceiveReport<media::DownloadProgressReport>
00107 {
00108   callback::SendReport<SourceReport> & _report;
00109 
00110 public:
00111 
00112   DownloadProgressFileReceiver ( callback::SendReport<SourceReport> & report_r )
00113       : _report (report_r)
00114   {}
00115 
00116   virtual ~DownloadProgressFileReceiver ()
00117   {}
00118   virtual void reportbegin()
00119   {}
00120   virtual void reportend()
00121   {}
00122 
00127   virtual bool progress( int percent, const Url& url )
00128   {
00129     return _report->progress( percent);
00130   }
00131 };
00132 
00136 SourceImpl::SourceImpl( const null & )
00137     : base::ProvideNumericId<SourceImpl,Source_Ref::NumericId>( NULL )
00138     , _res_store_initialized(true)
00139 {}
00140 
00142 //
00143 //      METHOD NAME : SourceImpl::SourceImpl
00144 //      METHOD TYPE : Ctor
00145 //
00146 SourceImpl::SourceImpl()
00147     : _enabled(true)
00148     , _autorefresh(true)
00149     , _priority (0)
00150     , _priority_unsubscribed (0)
00151     , _subscribed(false)
00152     , _base_source(false)
00153     , _res_store_initialized(false)
00154 {}
00155 
00157 //
00158 //      METHOD NAME : SourceImpl::factoryCtor
00159 //      METHOD TYPE : void
00160 //
00161 void SourceImpl::factoryCtor( const media::MediaId & media_r,
00162                               const Pathname & path_r,
00163                               const std::string & alias_r,
00164                               const Pathname cache_dir_r,
00165                               bool base_source,
00166                               bool auto_refresh )
00167 {
00168   _media_set = new MediaSet( selfSourceRef() );
00169   _url = media_mgr.url( media_r );
00170   _media_set->redirect( 1, media_r );
00171   _path      = path_r;
00172   _alias     = alias_r;
00173   _cache_dir = cache_dir_r;
00174   _subscribed = true;
00175   _base_source = base_source;
00176 
00177   MIL << "Setting autorefresh: " << auto_refresh << endl;
00178   _autorefresh = auto_refresh;
00179 
00180   try
00181   {
00182     factoryInit();
00183   }
00184   catch ( Exception & excpt )
00185   {
00186     _store.clear();
00187     ZYPP_RETHROW( excpt );
00188   }
00189 }
00190 
00192 //
00193 //      METHOD NAME : SourceImpl::factoryInit
00194 //      METHOD TYPE : void
00195 //
00196 void SourceImpl::factoryInit()
00197 {
00198   ZYPP_THROW( Exception( "FactoryInit not implemented!" ) );
00199 }
00200 
00202 //
00203 //      METHOD NAME : SourceImpl::~SourceImpl
00204 //      METHOD TYPE : Dtor
00205 //
00206 SourceImpl::~SourceImpl()
00207 {
00208   if (_media_set)
00209   {
00210     media::MediaAccessId _media = _media_set->getMediaAccessId( 1 );
00211     media_mgr.release (_media, false);
00212   }
00213 }
00214 
00215 bool SourceImpl::enabled() const
00216 {
00217   return _enabled;
00218 }
00219 
00220 void SourceImpl::disable()
00221 {
00222   _enabled = false;
00223 }
00224 
00225 bool SourceImpl::autorefresh() const
00226 {
00227   return _autorefresh;
00228 }
00229 
00230 void SourceImpl::setAutorefresh( bool enable )
00231 {
00232   MIL << "Changing source [" << alias() << "] [" << url() << "] to autorefresh: " << enable << endl;
00233   _autorefresh = enable;
00234 }
00235 
00236 const ResStore & SourceImpl::resolvables() const
00237 {
00238   if ( !_res_store_initialized )
00239   {
00240     // cast away const to allow late init
00241     Source_Ref self( const_cast<SourceImpl*>(this)->selfSourceRef() );
00242     const_cast<SourceImpl*>(this)->createResolvables(self);
00243     const_cast<SourceImpl*>(this)->_res_store_initialized = true;
00244   }
00245   return _store;
00246 }
00247 
00248 std::set<zypp::Resolvable::Kind> SourceImpl::resolvableKinds() const
00249   {
00250     return std::set<zypp::Resolvable::Kind>();
00251   }
00252 
00253 const ResStore SourceImpl::resolvables(zypp::Resolvable::Kind kind) const
00254 {
00255   Source_Ref self( const_cast<SourceImpl*>(this)->selfSourceRef() );
00256   return const_cast<SourceImpl*>(this)->provideResolvablesByKind(self, kind);
00257 }
00258 
00259 Pathname SourceImpl::tmpMetadataDir() const
00260 {
00261   if ( !_tmp_metadata_dir_ptr )
00262     _tmp_metadata_dir_ptr.reset(new filesystem::TmpDir(getZYpp()->tmpPath()));
00263   return _tmp_metadata_dir_ptr->path();
00264 }
00265 
00266 Date SourceImpl::timestamp() const
00267 {
00268   return Date::now();
00269 }
00270 
00271 std::string SourceImpl::checksum() const
00272 {
00273   return randomString(48);
00274 }
00275 
00276 void SourceImpl::dirInfo(const unsigned media_nr,
00277                          std::list<std::string> &retlist,
00278                          const Pathname         &path_r,
00279                          bool                    dots ) const
00280 {
00281   DBG << "reading " << path_r << " file list" << endl;
00282   media::MediaAccessId _media = _media_set->getMediaAccessId( media_nr );
00283   media_mgr.dirInfo( _media, retlist, path_r, dots );
00284 }
00285 
00286 const Pathname SourceImpl::providePackage( Package::constPtr package )
00287 {
00288   bool retry = true;
00289   bool digest_ok = false;
00290   Pathname file;
00291   callback::SendReport<source::DownloadResolvableReport> report;
00292   DownloadProgressPackageReceiver download_report( report, package );
00293 
00294   while (retry)
00295   {
00296     report->start( package, package->source().url() );
00297 
00298     callback::TempConnect<media::DownloadProgressReport> tmp_download( download_report );
00299 
00300     try
00301     {
00302       file = provideJustFile( package->location(), package->sourceMediaNr());
00303     }
00304     catch (const Exception &e)
00305     {
00306       ERR << "Failed to provide " << package << " from " << url() << " in source " << alias() << std::endl;
00307       ZYPP_RETHROW (e);
00308     }
00309 
00310     report->finish( package, source::DownloadResolvableReport::NO_ERROR, "" );
00311 
00312     CheckSum checksum = package->checksum();
00313     std::string calculated_digest;
00314 
00315     // check digest
00316     try
00317     {
00318       std::ifstream is(file.asString().c_str(), std::ifstream::binary);
00319       calculated_digest = Digest::digest(checksum.type(), is);
00320       is.close();
00321     }
00322     catch (std::exception &e)
00323     {
00324       ERR << "Can't open " << file << " for integrity check." << std::endl;
00325     }
00326 
00327     if ( checksum.checksum() == calculated_digest )
00328     {
00329       MIL << package->location() << " ok. [" << calculated_digest << "]" << std::endl;
00330       digest_ok = true;
00331       retry = false;
00332     }
00333 
00334     if (!digest_ok)
00335     {
00336       std::string  package_str = package->name() + "-" + package->edition().asString();
00337       
00338       // TranslatorExplanation %s = package
00339       source::DownloadResolvableReport::Action useraction = report->problem(package, source::DownloadResolvableReport::INVALID, str::form(_("Package %s fails integrity check. Do you want to retry downloading it, or abort installation?"), package_str.c_str() ));
00340 
00341       if ( useraction == source::DownloadResolvableReport::ABORT )
00342       {
00343         ZYPP_THROW(Exception("Package " + package->location().asString() + " fails integrity check. Expected: [" + checksum.checksum() + "] Read: [" + calculated_digest + "] (" + checksum.type() + ")"));
00344       }
00345       else if ( useraction == source::DownloadResolvableReport::RETRY )
00346       {
00347         retry = true;
00348       }
00349     }
00350   }
00351   return file;
00352 }
00353 
00354 void SourceImpl::getPossiblyCachedMetadataFile( const Pathname &file_to_download, const Pathname &destination, const Pathname &cached_file, const CheckSum &checksum )
00355 {
00356   Pathname downloaded_file;
00357   Url file_url( url().asString() + file_to_download.asString() );
00358   // if we have a cached file and its the same
00359   if ( PathInfo(cached_file).isExist() && (! checksum.empty()) && is_checksum( cached_file, checksum ) )
00360   {
00361     MIL << "file " << file_url << " found in previous cache. Using cached copy." << std::endl;
00362     // checksum is already checked.
00363     // we could later implement double failover and try to download if file copy fails.
00364     if ( filesystem::copy(cached_file, destination) != 0 )
00365       ZYPP_THROW(SourceIOException("Can't copy " + cached_file.asString() + " to " + destination.asString()));
00366   }
00367   else
00368   {
00369     try
00370     {
00371       // we dont have it or its not the same, download it.
00372       downloaded_file = provideFile( file_to_download);
00373     }
00374     catch (const Exception & excpt_r)
00375     {
00376       ZYPP_CAUGHT(excpt_r);
00377       ZYPP_THROW(SourceIOException("Can't provide " + downloaded_file.asString() + " : " + excpt_r.msg() ));
00378     }
00379 
00380     if ( filesystem::copy(downloaded_file, destination) != 0 )
00381       ZYPP_THROW(SourceIOException("Can't copy " + downloaded_file.asString() + " to " + destination.asString()));
00382 
00383     callback::SendReport<DigestReport> report;
00384     if ( checksum.empty() )
00385     {
00386       MIL << "File " <<  file_url << " has no checksum available." << std::endl;
00387       if ( report->askUserToAcceptNoDigest(file_to_download) )
00388       {
00389         MIL << "User accepted " <<  file_url << " with no checksum." << std::endl;
00390         return;
00391       }
00392       else
00393       {
00394         ZYPP_THROW(SourceMetadataException( file_url.asString() + " " + N_(" miss checksum.") ));
00395       }
00396     }
00397     else
00398     {
00399       if (! is_checksum( destination, checksum))
00400         ZYPP_THROW(SourceMetadataException( file_url.asString() + " " + N_(" fails checksum verification.") ));
00401     }
00402 
00403   }
00404 }
00405 
00406 void SourceImpl::resetMediaVerifier()
00407 {
00408   try
00409   {
00410     media::MediaManager media_mgr;
00411     MIL << "Reseting media verifier" << std::endl;
00412 
00413     // don't try to attach media
00414     media::MediaAccessId _media = _media_set->getMediaAccessId(1, true);
00415     media_mgr.delVerifier(_media);
00416     media_mgr.addVerifier(_media, media::MediaVerifierRef(new media::NoVerifier()));
00417   }
00418   catch (const Exception & excpt_r)
00419   {
00420     ZYPP_CAUGHT(excpt_r);
00421     WAR << "Media Verifier not found." << endl;
00422   }
00423 }
00424 
00425 const Pathname SourceImpl::provideFile(const Pathname & file_r,
00426                                        const unsigned media_nr,
00427                                        bool cached,
00428                                        bool checkonly )
00429 {
00430   bool retry = true;
00431   Pathname downloaded_file;
00432   callback::SendReport<source::SourceReport> report;
00433   DownloadProgressFileReceiver download_report( report );
00434   Url file_url( url().asString() + file_r.asString() );
00435 
00436   callback::TempConnect<media::DownloadProgressReport> tmp_download( download_report );
00437 
00438   while (retry)
00439   {
00440     // TranslatorExplanation %s = file being downloaded
00441     report->start( selfSourceRef(), str::form( _("Downloading %s"), file_url.asString().c_str() ) );
00442     try
00443     {
00444       downloaded_file = provideJustFile(file_r, media_nr, cached, checkonly);
00445       report->finish( selfSourceRef(), str::form( _("Downloading %s"), file_url.asString().c_str() ), SourceReport::NO_ERROR, str::form(_("Downloaded %s from %s"), file_r.asString().c_str(), url().asString().c_str()) );
00446       retry = false;
00447     }
00448     catch ( const SkipRequestedException &e )
00449     {
00450       // TranslatorExplanation %s = file being downloaded
00451       report->finish( selfSourceRef(), str::form( _("Downloading %s"), file_url.asString().c_str() ), SourceReport::IO, str::form(_("Can't provide %s from %s"), file_r.asString().c_str(), url().asString().c_str()) );
00452       ZYPP_RETHROW(e);
00453     }
00454     catch (const Exception &e)
00455     {
00456       // TranslatorExplanation %s = file that was not able to download
00457       if ( report->problem(selfSourceRef(), SourceReport::IO, str::form(_("Can't provide %s from %s"), file_r.asString().c_str(), url().asString().c_str())) != SourceReport::RETRY )
00458       {
00459         report->finish( selfSourceRef(), str::form( _("Downloading %s"), file_url.asString().c_str() ), SourceReport::IO, str::form(_("Can't provide %s from %s"), file_r.asString().c_str(), url().asString().c_str()) );
00460         ZYPP_THROW(Exception("Can't provide " + file_r.asString() + " from " + url().asString() ));
00461       }
00462     }
00463 
00464   }
00465   return downloaded_file;
00466 }
00467 
00468 const Pathname SourceImpl::tryToProvideFile( const Pathname & file, const unsigned media_nr )
00469 {
00470   media::MediaAccessId _media = _media_set->getMediaAccessId( media_nr);
00471   media_mgr.provideFile (_media, file, false, false);
00472   return media_mgr.localPath( _media, file );
00473 }
00474 
00475 void SourceImpl::copyLocalMetadata(const Pathname &src, const Pathname &dst) const
00476 {
00477   // refuse to use stupid paths as cache dir
00478   if (dst == Pathname("/") )
00479     ZYPP_THROW(Exception("I refuse to use / as local dir"));
00480 
00481   if (0 != assert_dir(dst, 0755))
00482     ZYPP_THROW(Exception("Cannot create local directory" + dst.asString()));
00483 
00484   MIL << "Cleaning up local dir" << std::endl;
00485   filesystem::clean_dir(dst);
00486   MIL << "Copying " << src << " content to local : " << dst << std::endl;
00487 
00488   if ( copy_dir_content( src, dst) != 0)
00489   {
00490     filesystem::clean_dir(dst);
00491     ZYPP_THROW(Exception( "Can't copy downloaded data to local dir. local dir cleaned."));
00492   }
00493 }
00494 
00495 const Pathname SourceImpl::provideJustFile(const Pathname & file_r,
00496     const unsigned media_nr,
00497     bool cached,
00498     bool checkonly )
00499 {
00500   callback::SendReport<media::MediaChangeReport> report;
00501 
00502   SourceFactory source_factory;
00503 
00504   // get the mediaId, but don't try to attach it here
00505   media::MediaAccessId _media = _media_set->getMediaAccessId( media_nr, true );
00506   do
00507   {
00508     try
00509     {
00510       DBG << "Going to try provide file " << file_r << " from " << media_nr << endl;
00511 
00512       // try to attach the media
00513       _media = _media_set->getMediaAccessId( media_nr ); // in case of redirect
00514       media_mgr.provideFile (_media, file_r, cached, checkonly);
00515       break;
00516     }
00517     catch ( Exception & excp )
00518     {
00519       ZYPP_CAUGHT(excp);
00520       media::MediaChangeReport::Action user;
00521 
00522       do
00523       {
00524 
00525         DBG << "Media couldn't provide file " << file_r << " , releasing." << endl;
00526         try
00527         {
00528           media_mgr.release (_media, false);
00529         }
00530         catch (const Exception & excpt_r)
00531         {
00532           ZYPP_CAUGHT(excpt_r);
00533           MIL << "Failed to release media " << _media << endl;
00534         }
00535         MIL << "Releasing all medias of all sources" << endl;
00536         try
00537         {
00538           zypp::SourceManager::sourceManager()->releaseAllSources();
00539         }
00540         catch (const zypp::Exception& excpt_r)
00541         {
00542           ZYPP_CAUGHT(excpt_r);
00543           ERR << "Failed to release all sources" << endl;
00544         }
00545 
00546         // set up the reason
00547         media::MediaChangeReport::Error reason
00548         = media::MediaChangeReport::INVALID;
00549 
00550         if ( typeid(excp) == typeid( media::MediaFileNotFoundException )  ||
00551              typeid(excp) == typeid( media::MediaNotAFileException ) )
00552         {
00553           reason = media::MediaChangeReport::NOT_FOUND;
00554         }
00555         else if ( typeid(excp) == typeid( media::MediaNotDesiredException)  ||
00556                   typeid(excp) == typeid( media::MediaNotAttachedException) )
00557         {
00558           reason = media::MediaChangeReport::WRONG;
00559         }
00560 
00561         user  = checkonly ? media::MediaChangeReport::ABORT :
00562                 report->requestMedia (
00563                   source_factory.createFrom( this ),
00564                   media_nr,
00565                   reason,
00566                   excp.asUserString()
00567                 );
00568 
00569         DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00570 
00571         if ( user == media::MediaChangeReport::ABORT )
00572         {
00573           DBG << "Aborting" << endl;
00574           ZYPP_RETHROW ( excp );
00575         }
00576         else if ( user == media::MediaChangeReport::IGNORE )
00577         {
00578           DBG << "Skipping" << endl;
00579           ZYPP_THROW ( SkipRequestedException("User-requested skipping of a file") );
00580         }
00581         else if ( user == media::MediaChangeReport::EJECT )
00582         {
00583           DBG << "Eject: try to release" << endl;
00584           try
00585           {
00586             zypp::SourceManager::sourceManager()->releaseAllSources();
00587           }
00588           catch (const zypp::Exception& excpt_r)
00589           {
00590             ZYPP_CAUGHT(excpt_r);
00591             ERR << "Failed to release all sources" << endl;
00592           }
00593           
00594           try
00595           {
00596             media_mgr.release (_media, true); // one more release needed for eject
00597           }
00598           catch (const zypp::media::MediaNotEjectedException & excpt_r)
00599           {
00600             ZYPP_CAUGHT(excpt_r);
00601             ERR << "Failed to eject" << endl;
00602             break;
00603           }
00604           // FIXME: this will not work, probably
00605         }
00606         else if ( user == media::MediaChangeReport::RETRY  ||
00607                   user == media::MediaChangeReport::CHANGE_URL )
00608         {
00609           // retry
00610           DBG << "Going to try again" << endl;
00611 
00612           // not attaching, media set will do that for us
00613           // this could generate uncaught exception (#158620)
00614 
00615           break;
00616         }
00617         else
00618         {
00619           DBG << "Don't know, let's ABORT" << endl;
00620 
00621           ZYPP_RETHROW ( excp );
00622         }
00623       }
00624       while ( user == media::MediaChangeReport::EJECT );
00625     }
00626 
00627     // retry or change URL
00628   }
00629   while ( true );
00630 
00631   return media_mgr.localPath( _media, file_r );
00632 }
00633 
00634 const Pathname SourceImpl::provideDirTree(const Pathname & path_r, const unsigned media_nr)
00635 {
00636   callback::SendReport<media::MediaChangeReport> report;
00637   SourceFactory source_factory;
00638   // get the mediaId, but don't try to attach it here
00639   media::MediaAccessId _media = _media_set->getMediaAccessId( media_nr, true );
00640   do
00641   {
00642     try
00643     {
00644       DBG << "Going to try provide tree " << path_r << " from " << media_nr << endl;
00645       // try to attach the media
00646       _media = _media_set->getMediaAccessId( media_nr ); // in case of redirect
00647       media_mgr.provideDirTree (_media, path_r);
00648       break;
00649     }
00650     catch ( Exception & excp )
00651     {
00652       ZYPP_CAUGHT(excp);
00653       media::MediaChangeReport::Action user;
00654 
00655       do
00656       {
00657         DBG << "Media couldn't provide tree " << path_r << " , releasing." << endl;
00658         try
00659         {
00660           media_mgr.release (_media, false);
00661         }
00662         catch (const Exception & excpt_r)
00663         {
00664           ZYPP_CAUGHT(excpt_r);
00665           MIL << "Failed to release media " << _media << endl;
00666         }
00667         MIL << "Releasing all medias of all sources" << endl;
00668         try
00669         {
00670           zypp::SourceManager::sourceManager()->releaseAllSources();
00671         }
00672         catch (const zypp::Exception& excpt_r)
00673         {
00674           ZYPP_CAUGHT(excpt_r);
00675           ERR << "Failed to release all sources" << endl;
00676         }
00677         // set up the reason
00678         media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00679 
00680         if ( typeid(excp) == typeid( media::MediaFileNotFoundException )  || typeid(excp) == typeid( media::MediaNotAFileException ) )
00681         {
00682           reason = media::MediaChangeReport::NOT_FOUND;
00683         }
00684         else if ( typeid(excp) == typeid( media::MediaNotDesiredException)  || typeid(excp) == typeid( media::MediaNotAttachedException) )
00685         {
00686           reason = media::MediaChangeReport::WRONG;
00687         }
00688         user  = report->requestMedia ( source_factory.createFrom( this ), media_nr, reason, excp.asUserString() );
00689 
00690         DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00691 
00692         if ( user == media::MediaChangeReport::ABORT )
00693         {
00694           DBG << "Aborting" << endl;
00695           ZYPP_RETHROW ( excp );
00696         }
00697         else if ( user == media::MediaChangeReport::EJECT )
00698         {
00699           DBG << "Eject: try to release" << endl;
00700           try
00701           {
00702             zypp::SourceManager::sourceManager()->releaseAllSources();
00703           }
00704           catch (const zypp::Exception& excpt_r)
00705           {
00706             ZYPP_CAUGHT(excpt_r);
00707             ERR << "Failed to release all sources" << endl;
00708           }
00709           media_mgr.release (_media, true); // one more release needed for eject
00710           // FIXME: this will not work, probably
00711         }
00712         else if ( user == media::MediaChangeReport::RETRY  ||
00713                   user == media::MediaChangeReport::CHANGE_URL )
00714         {
00715           // retry
00716           DBG << "Going to try again" << endl;
00717 
00718           // not attaching, media set will do that for us
00719           // this could generate uncaught exception (#158620)
00720 
00721           break;
00722         }
00723         else
00724         {
00725           DBG << "Don't know, let's ABORT" << endl;
00726 
00727           ZYPP_RETHROW ( excp );
00728         }
00729       }
00730       while ( user == media::MediaChangeReport::EJECT );
00731     }
00732     // retry or change URL
00733   }
00734   while ( true );
00735   return media_mgr.localPath( _media, path_r );
00736 }
00737 
00738 const void SourceImpl::releaseFile(const Pathname & file_r,
00739                                    const unsigned media_nr)
00740 {
00741   DBG << "releaseFile(" << file_r << ", " << media_nr << ")" << endl;
00742   media::MediaAccessId _media = _media_set->getMediaAccessId( media_nr );
00743   media_mgr.releaseFile(_media, file_r);
00744 }
00745 
00746 const void SourceImpl::releaseDir(const Pathname & path_r,
00747                                   const unsigned media_nr,
00748                                   const bool recursive)
00749 {
00750   DBG << "releaseDir(" << path_r << ", " << media_nr << (recursive?", recursive":"") << ")" << endl;
00751   media::MediaAccessId _media = _media_set->getMediaAccessId( media_nr );
00752   if (recursive)
00753     media_mgr.releasePath(_media, path_r);
00754   else
00755     media_mgr.releaseDir(_media, path_r);
00756 }
00757 
00758 void SourceImpl::changeMedia( const media::MediaId & media_r, const Pathname & path_r )
00759 {
00760   DBG << "changeMedia(" << path_r << ")" << endl;
00761   _url = media_mgr.url( media_r );
00762   _media_set->reset();
00763   _media_set->redirect( 1, media_r );
00764   _path = path_r;
00765 }
00766 
00767 void SourceImpl::enable()
00768 {
00769 //      if (autorefresh())
00770 //      refresh();
00771   _enabled = true;
00772 }
00773 
00774 void SourceImpl::createResolvables(Source_Ref source_r)
00775 {
00776   WAR << "createResolvables not implemented by the source" << endl;
00777 }
00778 
00779 ResStore SourceImpl::provideResolvablesByKind(Source_Ref source_r, zypp::Resolvable::Kind kind)
00780 {
00781   WAR << "provideResolvablesByKind not implemented by the source" << endl;
00782   return ResStore();
00783 }
00784 
00785 void SourceImpl::storeMetadata(const Pathname & cache_dir_r)
00786 {}
00787 
00788 void SourceImpl::refresh()
00789 {
00790   MIL << "Refreshing" << endl;
00791   // TODO: will this work in chroot?
00792   // TODO: better download somewhere else and then copy over
00793   try
00794   {
00795     storeMetadata( _cache_dir );
00796   }
00797   catch ( const zypp::Exception & excpt )
00798   {
00799     ERR << "Unable to refresh the source cache" << endl;
00800     if ( ! _cache_dir.empty() && _cache_dir != "/" )
00801       filesystem::clean_dir( _cache_dir );
00802 
00803     ZYPP_RETHROW( excpt );
00804   }
00805 }
00806 
00807 void SourceImpl::redirect(unsigned media_nr, const Url & new_url)
00808 {
00809   DBG << "redirect(" << new_url << ")" << endl;
00810   media::MediaAccessId id = media_mgr.open( new_url );
00811   _media_set->redirect( media_nr, id );
00812 }
00813 void SourceImpl::reattach(const Pathname &attach_point)
00814 {
00815   DBG << "reattach(" << attach_point << ")" << endl;
00816   _media_set->reattach( attach_point );
00817 }
00818 
00819 void SourceImpl::release()
00820 {
00821   if (_media_set)
00822     _media_set->release();
00823 }
00824 
00825 media::MediaVerifierRef SourceImpl::verifier(unsigned media_nr)
00826 {
00827   return media::MediaVerifierRef(new media::NoVerifier());
00828 }
00829 
00831 // attribute accessors
00832 
00833 std::string SourceImpl::type (void) const
00834 {
00835   return "undefined";
00836 }
00837 
00838 std::string SourceImpl::id (void) const
00839 {
00840   return _id;
00841 }
00842 
00843 void SourceImpl::setId (const std::string id_r)
00844 {
00845   _id = id_r;
00846 }
00847 
00848 unsigned SourceImpl::priority (void) const
00849 {
00850   return _priority;
00851 }
00852 
00853 void SourceImpl::setPriority (unsigned p)
00854 {
00855   _priority = p;
00856 }
00857 
00858 unsigned SourceImpl::priorityUnsubscribed (void) const
00859 {
00860   return _priority_unsubscribed;
00861 }
00862 
00863 void SourceImpl::setPriorityUnsubscribed (unsigned p)
00864 {
00865   _priority_unsubscribed = p;
00866 }
00867 
00868 bool SourceImpl::subscribed (void) const
00869 {
00870   return _subscribed;
00871 }
00872 
00873 void SourceImpl::setSubscribed (bool s)
00874 {
00875   _subscribed = s;
00876 }
00877 
00878 const Pathname & SourceImpl::cacheDir (void)
00879 {
00880   return _cache_dir;
00881 }
00882 
00883 Url SourceImpl::url (void) const
00884 {
00885   return _url;
00886 }
00887 
00888 void SourceImpl::setUrl( const Url & url )
00889 {
00890   _url = url;
00891 }
00892 
00893 bool SourceImpl::remote() const
00894 {
00895   bool downloads = false;
00896   try
00897   {
00898     downloads = media::MediaManager::downloads(_url);
00899   }
00900   catch (const zypp::Exception &e)
00901   {
00902     // should not happen, but ...
00903     ZYPP_CAUGHT(e);
00904   }
00905   return downloads;
00906 }
00907 
00908 const Pathname & SourceImpl::path (void) const
00909 {
00910   return _path;
00911 }
00912 
00913 unsigned SourceImpl::numberOfMedia(void) const
00914 {
00915   return 1;
00916 }
00917 
00918 std::string SourceImpl::vendor (void) const
00919 {
00920   return "";
00921 }
00922 
00923 const std::list<Pathname> SourceImpl::publicKeys()
00924 {
00925   return std::list<Pathname>();
00926 }
00927 
00928 std::string SourceImpl::unique_id (void) const
00929 {
00930   return "";
00931 }
00932 
00934 
00938 std::string SourceImpl::zmdName (void) const
00939 {
00940   return "zmdname";
00941 }
00942 
00943 void SourceImpl::setZmdName (const std::string name_r)
00944 {
00945   return;
00946 }
00947 
00948 std::string SourceImpl::zmdDescription (void) const
00949 {
00950   return "zmddescription";
00951 }
00952 
00953 void SourceImpl::setZmdDescription (const std::string desc_r)
00954 {
00955   return;
00956 }
00957 
00959 
00960 std::ostream & SourceImpl::dumpOn( std::ostream & str ) const
00961 {
00962   str << "Source[" << numericId() << "|" << type();
00963   if ( !_alias.empty() )
00964     str << "|" << _alias;
00965   str << "]";
00966 
00967   str << "{"
00968   << _url << "(" << _path << ")";
00969   if ( ! _cache_dir.empty() )
00970     str << "; cache " << _cache_dir;
00971 
00972   str << "; autorefresh: " << _autorefresh;
00973   str << "; enabled: " << _enabled;
00974   str << "}";
00975 
00976   return str;
00977 }
00978 
00979 SourceImpl::Verifier::Verifier(const std::string & vendor_r, const std::string & id_r, const media::MediaNr media_nr)
00980     : _media_vendor(vendor_r)
00981     , _media_id(id_r)
00982     , _media_nr(media_nr)
00983 {}
00984 
00985 bool SourceImpl::Verifier::isDesiredMedia(const media::MediaAccessRef &ref)
00986 {
00987   if (_media_vendor.empty() || _media_id.empty())
00988     return true;
00989 #warning TODO define what does missing media_id/media_vendor mean
00990 
00991   Pathname media_file = "/media." + str::numstring(_media_nr) + "/media";
00992   ref->provideFile (media_file);
00993   media_file = ref->localPath(media_file);
00994   std::ifstream str(media_file.asString().c_str());
00995   std::string vendor;
00996   std::string id;
00997 
00998 #warning check the stream status
00999   getline(str, vendor);
01000   getline(str, id);
01001 
01002   return (vendor == _media_vendor && id == _media_id );
01003 }
01004 
01006 } // namespace source
01009 } // namespace zypp

Generated on Tue Nov 28 16:49:32 2006 for zypp by  doxygen 1.5.0