1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Fetcher.cc
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/DefaultIntegral.h"
17 #include "zypp/ZYppFactory.h"
18 #include "zypp/Fetcher.h"
19 #include "zypp/KeyRing.h"
23 ///////////////////////////////////////////////////////////////////
25 { /////////////////////////////////////////////////////////////////
27 Fetcher::ChecksumFileChecker::ChecksumFileChecker( const CheckSum &checksum )
32 bool Fetcher::ChecksumFileChecker::operator()( const Pathname &file ) const
34 callback::SendReport<DigestReport> report;
35 CheckSum real_checksum( _checksum.type(), filesystem::checksum( file, _checksum.type() ));
37 if ( _checksum.empty() )
39 MIL << "File " << file << " has no checksum available." << std::endl;
40 if ( report->askUserToAcceptNoDigest(file) )
42 MIL << "User accepted " << file << " with no checksum." << std::endl;
52 if ( (real_checksum == _checksum) )
54 if ( report->askUserToAcceptWrongDigest( file, _checksum.checksum(), real_checksum.checksum() ) )
56 WAR << "User accepted " << file << " with WRONG CHECKSUM." << std::endl;
71 bool Fetcher::NullFileChecker::operator()(const Pathname &file ) const
76 bool Fetcher::CompositeFileChecker::operator()(const Pathname &file ) const
79 for ( list<Fetcher::FileChecker>::const_iterator it = _checkers.begin(); it != _checkers.end(); ++it )
81 result = result && (*it)(file);
86 void Fetcher::CompositeFileChecker::add( const FileChecker &checker )
88 _checkers.push_back(checker);
91 Fetcher::SignatureFileChecker::SignatureFileChecker( const Pathname &signature )
92 : _signature(signature)
96 Fetcher::SignatureFileChecker::SignatureFileChecker()
100 void Fetcher::SignatureFileChecker::addPublicKey( const Pathname &publickey )
102 ZYpp::Ptr z = getZYpp();
103 z->keyRing()->importKey(publickey, false);
106 bool Fetcher::SignatureFileChecker::operator()(const Pathname &file ) const
108 ZYpp::Ptr z = getZYpp();
109 MIL << "checking " << file << " file validity using digital signature.." << endl;
110 bool valid = z->keyRing()->verifyFileSignatureWorkflow( file, string(), _signature);
115 * Class to encapsulate the \ref OnMediaLocation object
116 * and the \ref Fetcher::FileChcker together
120 FetcherJob( const OnMediaLocation &loc )
126 OnMediaLocation location;
127 Fetcher::CompositeFileChecker checkers;
130 ///////////////////////////////////////////////////////////////////
132 // CLASS NAME : Fetcher::Impl
134 /** Fetcher implementation. */
140 void enqueue( const OnMediaLocation &resource, const Fetcher::FileChecker &checker );
141 void enqueueDigested( const OnMediaLocation &resource, const Fetcher::FileChecker &checker );
142 void addCachePath( const Pathname &cache_dir );
144 void start( const Pathname &dest_dir, MediaSetAccess &media );
146 /** Offer default Impl. */
147 static shared_ptr<Impl> nullimpl()
149 static shared_ptr<Impl> _nullimpl( new Impl );
154 friend Impl * rwcowClone<Impl>( const Impl * rhs );
155 /** clone for RWCOW_pointer */
157 { return new Impl( *this ); }
159 std::list<FetcherJob> _resources;
160 std::list<Pathname> _caches;
162 ///////////////////////////////////////////////////////////////////
165 void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
167 CompositeFileChecker composite;
168 composite.add(ChecksumFileChecker(resource.checksum()));
169 composite.add(checker);
170 enqueue(resource, composite);
173 void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
175 FetcherJob job(resource);
176 job.checkers.add(checker);
177 _resources.push_back(resource);
180 void Fetcher::Impl::reset()
186 void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
188 _caches.push_back(cache_dir);
191 void Fetcher::Impl::start( const Pathname &dest_dir, MediaSetAccess &media )
193 for ( list<FetcherJob>::const_iterator it_res = _resources.begin(); it_res != _resources.end(); ++it_res )
195 bool got_from_cache = false;
196 for ( list<Pathname>::const_iterator it_cache = _caches.begin(); it_cache != _caches.end(); ++it_cache )
198 // Pathinfos could be cached to avoid too many stats?
199 PathInfo info(*it_cache);
202 // does the current file exists in the current cache?
203 Pathname cached_file = *it_cache + (*it_res).location.filename();
204 if ( PathInfo( cached_file ).isExist() )
206 // check the checksum
207 if ( is_checksum( cached_file, (*it_res).location.checksum() ) )
210 MIL << "file " << (*it_res).location.filename() << " found in previous cache. Using cached copy." << endl;
211 // checksum is already checked.
212 // we could later implement double failover and try to download if file copy fails.
214 // replicate the complete path in the target directory
215 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
216 if ( assert_dir( dest_full_path.dirname() ) != 0 )
217 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
219 if ( filesystem::copy(cached_file, dest_full_path ) != 0 )
221 //ZYPP_THROW(SourceIOException("Can't copy " + cached_file.asString() + " to " + destination.asString()));
222 ERR << "Can't copy " << cached_file + " to " + dest_dir << endl;
227 got_from_cache = true;
233 // File exists in cache but with a different checksum
234 // so just try next cache
240 // skip bad cache directory and try with next one
241 ERR << "Skipping cache : " << *it_cache << endl;
246 if ( ! got_from_cache )
248 // try to get the file from the net
251 Pathname tmp_file = media.provideFile((*it_res).location);
252 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
253 if ( assert_dir( dest_full_path.dirname() ) != 0 )
254 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
255 if ( filesystem::copy(tmp_file, dest_full_path ) != 0 )
257 ZYPP_THROW( Exception("Can't copy " + tmp_file.asString() + " to " + dest_dir.asString()));
262 catch (const Exception & excpt_r)
264 ZYPP_CAUGHT(excpt_r);
265 ZYPP_THROW(Exception("Can't provide " + (*it_res).location.filename().asString() + " : " + excpt_r.msg() ));
270 // We got the file from cache
271 // continue with next file
275 // no matter where did we got the file, try to validate it:
276 Pathname localfile = dest_dir + (*it_res).location.filename();
277 // call the checker function
278 bool good = (*it_res).checkers(localfile);
281 //FIXME better message
282 ZYPP_THROW(Exception("File " + (*it_res).location.filename().asString() + " does not validate." ));
288 /** \relates Fetcher::Impl Stream output */
289 inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
291 return str << "Fetcher::Impl";
294 ///////////////////////////////////////////////////////////////////
296 // CLASS NAME : Fetcher
298 ///////////////////////////////////////////////////////////////////
300 ///////////////////////////////////////////////////////////////////
302 // METHOD NAME : Fetcher::Fetcher
303 // METHOD TYPE : Ctor
306 : _pimpl( Impl::nullimpl() )
309 ///////////////////////////////////////////////////////////////////
311 // METHOD NAME : Fetcher::~Fetcher
312 // METHOD TYPE : Dtor
317 void Fetcher::enqueueDigested( const OnMediaLocation &resource, const Fetcher::FileChecker &checker )
319 _pimpl->enqueue(resource, checker);
322 void Fetcher::enqueue( const OnMediaLocation &resource, const Fetcher::FileChecker &checker )
324 _pimpl->enqueue(resource, checker);
327 void Fetcher::addCachePath( const Pathname &cache_dir )
329 _pimpl->addCachePath(cache_dir);
332 void Fetcher::reset()
337 void Fetcher::start( const Pathname &dest_dir, MediaSetAccess &media )
339 _pimpl->start(dest_dir, media);
343 /******************************************************************
345 ** FUNCTION NAME : operator<<
346 ** FUNCTION TYPE : std::ostream &
348 std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
350 return str << *obj._pimpl;
353 /////////////////////////////////////////////////////////////////
355 ///////////////////////////////////////////////////////////////////