libzypp  17.25.2
Fetcher.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <fstream>
14 #include <list>
15 #include <map>
16 
17 #include <zypp/base/Easy.h>
18 #include <zypp/base/LogControl.h>
19 #include <zypp/base/LogTools.h>
20 #include <zypp/base/PtrTypes.h>
22 #include <zypp/base/String.h>
23 #include <zypp/Fetcher.h>
24 #include <zypp/ZYppFactory.h>
25 #include <zypp/CheckSum.h>
29 
30 #undef ZYPP_BASE_LOGGER_LOGGROUP
31 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp:fetcher"
32 
34 namespace zypp
35 {
36 
42  struct FetcherIndex
43  {
45  : location(loc)
46  {}
51  };
52 
53  typedef shared_ptr<FetcherIndex> FetcherIndex_Ptr;
54 
57  {
58  bool operator()( const FetcherIndex_Ptr & lhs, const FetcherIndex_Ptr & rhs ) const
59  {
60  if ( lhs == rhs )
61  return false; // incl. NULL == NULL
62  if ( ! lhs )
63  return true; // NULL < nonNULL
64  if ( ! rhs )
65  return false; // nonNULL > NULL
66  // both nonNULL ==> compare medianr and path
67  if ( lhs->location.medianr() == rhs->location.medianr() )
68  return lhs->location.filename() < rhs->location.filename();
69  //else
70  return lhs->location.medianr() < rhs->location.medianr();
71  }
72  };
73 
78  struct FetcherJob
79  {
80  enum Flag
81  {
82  None = 0x0000,
83  Directory = 0x0001,
84  Recursive = 0x0002,
86  // check checksums even if there is no such
87  // checksum (warns of no checksum)
89  };
90  ZYPP_DECLARE_FLAGS(Flags, Flag);
91 
92 
93  FetcherJob( const OnMediaLocation &loc, const Pathname dfile = Pathname())
94  : location(loc)
95  , deltafile(dfile)
96  , flags(None)
97  {
98  //MIL << location << endl;
99  }
100 
102  {
103  //MIL << location << " | * " << checkers.size() << endl;
104  }
105 
108  //CompositeFileChecker checkers;
109  std::list<FileChecker> checkers;
110  Flags flags;
111  };
112 
113  ZYPP_DECLARE_OPERATORS_FOR_FLAGS(FetcherJob::Flags);
114  typedef shared_ptr<FetcherJob> FetcherJob_Ptr;
115 
116  std::ostream & operator<<( std::ostream & str, const FetcherJob_Ptr & obj )
117  {
118  return str << obj->location;
119  }
120 
122  //
123  // CLASS NAME : Fetcher::Impl
124  //
127  {
128  friend std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj );
129 
130  public:
131  Impl();
132 
133  ~Impl() {}
134 
135  void setOptions( Fetcher::Options options );
136  Fetcher::Options options() const;
137 
138  void addIndex( const OnMediaLocation &resource );
139 
140  void enqueueDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
141  void enqueueDigestedDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
142 
143  void enqueue( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() );
144  void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker(), const Pathname &deltafile = Pathname() );
145  void addCachePath( const Pathname &cache_dir );
146  void reset();
147  void setMediaSetAccess ( MediaSetAccess &media );
148  void start( const Pathname &dest_dir,
149  const ProgressData::ReceiverFnc &progress );
150  void start( const Pathname &dest_dir,
151  MediaSetAccess &media,
152  const ProgressData::ReceiverFnc & progress_receiver );
153 
155  static shared_ptr<Impl> nullimpl()
156  {
157  static shared_ptr<Impl> _nullimpl( new Impl );
158  return _nullimpl;
159  }
160  private:
164  void downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir);
165 
169  void downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir);
170 
178  void readIndex( const Pathname &index, const Pathname &basedir );
179 
181  void readChecksumsIndex( const Pathname &index, const Pathname &basedir );
182 
184  void readContentFileIndex( const Pathname &index, const Pathname &basedir );
185 
187  void getDirectoryContent( MediaSetAccess &media, const OnMediaLocation &resource, filesystem::DirContent &content );
188 
194  Pathname locateInCache( const OnMediaLocation & resource_r, const Pathname & destDir_r );
199  void validate( const Pathname & localfile_r, const std::list<FileChecker> & checkers_r );
200 
204  void addDirJobs( MediaSetAccess &media, const OnMediaLocation &resource,
205  const Pathname &dest_dir, FetcherJob::Flags flags );
206 
210  void autoaddIndexes( const filesystem::DirContent &content,
211  MediaSetAccess &media,
212  const OnMediaLocation &resource,
213  const Pathname &dest_dir );
217  void provideToDest( MediaSetAccess & media_r, const Pathname & destDir_r , const FetcherJob_Ptr & jobp_r );
218 
219  private:
220  friend Impl * rwcowClone<Impl>( const Impl * rhs );
222  Impl * clone() const
223  { return new Impl( *this ); }
224 
225  std::list<FetcherJob_Ptr> _resources;
226  std::set<FetcherIndex_Ptr,SameFetcherIndex> _indexes;
227  std::set<Pathname> _caches;
228  // checksums read from the indexes
229  std::map<std::string, CheckSum> _checksums;
230  // cache of dir contents
231  std::map<std::string, filesystem::DirContent> _dircontent;
232 
234 
235  Fetcher::Options _options;
236  };
238 
239  void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile )
240  {
241  if ( _mediaSetAccess )
242  _mediaSetAccess->precacheFiles( {resource} );
243 
244  FetcherJob_Ptr job;
245  job.reset(new FetcherJob(resource, deltafile));
246  job->flags |= FetcherJob:: AlwaysVerifyChecksum;
247  _resources.push_back(job);
248  }
249 
251  : _options(0)
252  {
253  }
254 
255  void Fetcher::Impl::setOptions( Fetcher::Options options )
256  { _options = options; }
257 
258  Fetcher::Options Fetcher::Impl::options() const
259  { return _options; }
260 
262  bool recursive,
263  const FileChecker &checker )
264  {
265  FetcherJob_Ptr job;
266  job.reset(new FetcherJob(resource));
267  if ( checker )
268  job->checkers.push_back(checker);
269  if ( recursive )
270  job->flags |= FetcherJob::Recursive;
271  job->flags |= FetcherJob::Directory;
272 
273  _resources.push_back(job);
274  }
275 
277  bool recursive,
278  const FileChecker &checker )
279  {
280  FetcherJob_Ptr job;
281  job.reset(new FetcherJob(resource));
282  if ( checker )
283  job->checkers.push_back(checker);
284  if ( recursive )
285  job->flags |= FetcherJob::Recursive;
286  job->flags |= FetcherJob::Directory;
287  job->flags |= FetcherJob::AlwaysVerifyChecksum;
288 
289  _resources.push_back(job);
290 
291  }
292 
293  void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
294  {
295  if ( _mediaSetAccess )
296  _mediaSetAccess->precacheFiles( {resource} );
297 
298  FetcherJob_Ptr job;
299  job.reset(new FetcherJob(resource));
300  if ( checker )
301  job->checkers.push_back(checker);
302  _resources.push_back(job);
303  }
304 
305  void Fetcher::Impl::addIndex( const OnMediaLocation &resource )
306  {
307  MIL << "adding index " << resource << endl;
308  _indexes.insert(FetcherIndex_Ptr(new FetcherIndex(resource)));
309  }
310 
311 
313  {
314  _resources.clear();
315  _indexes.clear();
316  _checksums.clear();
317  _dircontent.clear();
318  }
319 
321  {
322  _mediaSetAccess = &media;
323  }
324 
325  void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
326  {
327  PathInfo info(cache_dir);
328  if ( info.isExist() )
329  {
330  if ( info.isDir() )
331  {
332  DBG << "Adding fetcher cache: '" << cache_dir << "'." << endl;
333  _caches.insert(cache_dir);
334  }
335  else
336  {
337  // don't add bad cache directory, just log the error
338  ERR << "Not adding cache: '" << cache_dir << "'. Not a directory." << endl;
339  }
340  }
341  else
342  {
343  ERR << "Not adding cache '" << cache_dir << "'. Path does not exists." << endl;
344  }
345 
346  }
347 
348  Pathname Fetcher::Impl::locateInCache( const OnMediaLocation & resource_r, const Pathname & destDir_r )
349  {
350  Pathname ret;
351  // No checksum - no match
352  if ( resource_r.checksum().empty() )
353  return ret;
354 
355  // first check in the destination directory
356  Pathname cacheLocation = destDir_r / resource_r.filename();
357  if ( PathInfo(cacheLocation).isExist() && is_checksum( cacheLocation, resource_r.checksum() ) )
358  {
359  swap( ret, cacheLocation );
360  return ret;
361  }
362 
363  MIL << "start fetcher with " << _caches.size() << " cache directories." << endl;
364  for( const Pathname & cacheDir : _caches )
365  {
366  cacheLocation = cacheDir / resource_r.filename();
367  if ( PathInfo(cacheLocation).isExist() && is_checksum( cacheLocation, resource_r.checksum() ) )
368  {
369  MIL << "file " << resource_r.filename() << " found in cache " << cacheDir << endl;
370  swap( ret, cacheLocation );
371  return ret;
372  }
373  }
374 
375  return ret;
376  }
377 
378  void Fetcher::Impl::validate( const Pathname & localfile_r, const std::list<FileChecker> & checkers_r )
379  {
380  try
381  {
382  MIL << "Checking job [" << localfile_r << "] (" << checkers_r.size() << " checkers )" << endl;
383 
384  for ( const FileChecker & chkfnc : checkers_r )
385  {
386  if ( chkfnc )
387  chkfnc( localfile_r );
388  else
389  ERR << "Invalid checker for '" << localfile_r << "'" << endl;
390  }
391 
392  }
393  catch ( const FileCheckException &e )
394  {
395  ZYPP_RETHROW(e);
396  }
397  catch ( const Exception &e )
398  {
399  ZYPP_RETHROW(e);
400  }
401  catch (...)
402  {
403  ZYPP_THROW(Exception("Unknown error while validating " + localfile_r.asString()));
404  }
405  }
406 
408  MediaSetAccess &media,
409  const OnMediaLocation &resource,
410  const Pathname &dest_dir )
411  {
412  auto fnc_addIfInContent( [&]( const std::string & index_r ) -> bool
413  {
414  if ( find( content.begin(), content.end(), filesystem::DirEntry(index_r,filesystem::FT_FILE) ) == content.end() )
415  return false;
416  // add the index of this directory
417  OnMediaLocation indexloc( resource );
418  indexloc.changeFilename( resource.filename() + index_r );
419  addIndex( indexloc );
420  // we need to read it now
421  downloadAndReadIndexList( media, dest_dir );
422  return true;
423  } );
424 
425  if ( _options & AutoAddChecksumsIndexes )
426  {
427  fnc_addIfInContent( "CHECKSUMS" ) || fnc_addIfInContent( "SHA1SUMS" );
428  }
429  if ( _options & AutoAddContentFileIndexes )
430  {
431  fnc_addIfInContent( "content" );
432  }
433  }
434 
436  const OnMediaLocation &resource,
437  filesystem::DirContent &content )
438  {
439  if ( _dircontent.find(resource.filename().asString())
440  != _dircontent.end() )
441  {
442  filesystem::DirContent filled(_dircontent[resource.filename().asString()]);
443 
444  std::copy(filled.begin(), filled.end(), std::back_inserter(content));
445  }
446  else
447  {
448  filesystem::DirContent tofill;
449  media.dirInfo( tofill,
450  resource.filename(),
451  false /* dots */,
452  resource.medianr());
453  std::copy(tofill.begin(), tofill.end(), std::back_inserter(content));
454  _dircontent[resource.filename().asString()] = tofill;
455  }
456  }
457 
459  const OnMediaLocation &resource,
460  const Pathname &dest_dir, FetcherJob::Flags flags )
461  {
462  // first get the content of the directory so we can add
463  // individual transfer jobs
464  MIL << "Adding directory " << resource.filename() << endl;
465  filesystem::DirContent content;
466  try {
467  getDirectoryContent(media, resource, content);
468  }
469  catch ( media::MediaFileNotFoundException & exception )
470  {
471  ZYPP_CAUGHT( exception );
472  WAR << "Skiping subtree hidden at " << resource.filename() << endl;
473  return;
474  }
475 
476  // this method test for the option flags so indexes are added
477  // only if the options are enabled
478  autoaddIndexes(content, media, resource, dest_dir);
479 
480  for ( filesystem::DirContent::const_iterator it = content.begin();
481  it != content.end();
482  ++it )
483  {
484  // skip CHECKSUMS* as they were already retrieved
485  if ( str::hasPrefix(it->name, "CHECKSUMS") || str::hasPrefix(it->name, "SHA1SUMS") )
486  continue;
487 
488  Pathname filename = resource.filename() + it->name;
489 
490  switch ( it->type )
491  {
492  case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
493  case filesystem::FT_FILE:
494  {
495  CheckSum chksm(resource.checksum());
496  if ( _checksums.find(filename.asString()) != _checksums.end() )
497  {
498  // the checksum can be replaced with the one in the index.
499  chksm = _checksums[filename.asString()];
500  //MIL << "resource " << filename << " has checksum in the index file." << endl;
501  }
502  else
503  WAR << "Resource " << filename << " has no checksum in the index either." << endl;
504 
505  if ( flags & FetcherJob::AlwaysVerifyChecksum )
506  enqueueDigested(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
507  else
508  enqueue(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
509  break;
510  }
511  case filesystem::FT_DIR: // newer directory.yast contain at least directory info
512  if ( flags & FetcherJob::Recursive )
513  addDirJobs(media, filename, dest_dir, flags);
514  break;
515  default:
516  // don't provide devices, sockets, etc.
517  break;
518  }
519  }
520  }
521 
522  void Fetcher::Impl::provideToDest( MediaSetAccess & media_r, const Pathname & destDir_r , const FetcherJob_Ptr & jobp_r )
523  {
524  const OnMediaLocation & resource( jobp_r->location );
525 
526  try
527  {
528  scoped_ptr<MediaSetAccess::ReleaseFileGuard> releaseFileGuard; // will take care provided files get released
529 
530  // get cached file (by checksum) or provide from media
531  Pathname tmpFile = locateInCache( resource, destDir_r );
532  if ( tmpFile.empty() )
533  {
534  MIL << "Not found in cache, retrieving..." << endl;
535  tmpFile = media_r.provideFile( resource, resource.optional() ? MediaSetAccess::PROVIDE_NON_INTERACTIVE : MediaSetAccess::PROVIDE_DEFAULT, jobp_r->deltafile );
536  releaseFileGuard.reset( new MediaSetAccess::ReleaseFileGuard( media_r, resource ) ); // release it when we leave the block
537  }
538 
539  // The final destination: locateInCache also checks destFullPath!
540  // If we find a cache match (by checksum) at destFullPath, take
541  // care it gets deleted, in case the validation fails.
542  ManagedFile destFullPath( destDir_r / resource.filename() );
543  if ( tmpFile == destFullPath )
544  destFullPath.setDispose( filesystem::unlink );
545 
546  // validate the file (throws if not valid)
547  validate( tmpFile, jobp_r->checkers );
548 
549  // move it to the final destination
550  if ( tmpFile == destFullPath )
551  destFullPath.resetDispose(); // keep it!
552  else
553  {
554  if ( assert_dir( destFullPath->dirname() ) != 0 )
555  ZYPP_THROW( Exception( "Can't create " + destFullPath->dirname().asString() ) );
556 
557  if ( filesystem::hardlinkCopy( tmpFile, destFullPath ) != 0 )
558  ZYPP_THROW( Exception( "Can't hardlink/copy " + tmpFile.asString() + " to " + destDir_r.asString() ) );
559  }
560  }
561  catch ( Exception & excpt )
562  {
563  if ( resource.optional() )
564  {
565  ZYPP_CAUGHT( excpt );
566  WAR << "optional resource " << resource << " could not be transferred." << endl;
567  return;
568  }
569  else
570  {
571  excpt.remember( "Can't provide " + resource.filename().asString() );
572  ZYPP_RETHROW( excpt );
573  }
574  }
575  }
576 
577  // helper class to consume a content file
579  {
581  {
582  setRepoIndexConsumer( bind( &ContentReaderHelper::consumeIndex, this, _1 ) );
583  }
584 
585  void consumeIndex( const parser::susetags::RepoIndex_Ptr & data_r )
586  { _repoindex = data_r; }
587 
588  parser::susetags::RepoIndex_Ptr _repoindex;
589  };
590 
591  // generic function for reading indexes
592  void Fetcher::Impl::readIndex( const Pathname &index, const Pathname &basedir )
593  {
594  if ( index.basename() == "CHECKSUMS" || index.basename() == "SHA1SUMS" )
595  readChecksumsIndex(index, basedir);
596  else if ( index.basename() == "content" )
597  readContentFileIndex(index, basedir);
598  else
599  WAR << index << ": index file format not known" << endl;
600  }
601 
602  // reads a content file index
603  void Fetcher::Impl::readContentFileIndex( const Pathname &index, const Pathname &basedir )
604  {
605  ContentReaderHelper reader;
606  reader.parse(index);
607  MIL << index << " contains " << reader._repoindex->mediaFileChecksums.size() << " checksums." << endl;
608  for_( it, reader._repoindex->mediaFileChecksums.begin(), reader._repoindex->mediaFileChecksums.end() )
609  {
610  // content file entries don't start with /
611  _checksums[(basedir + it->first).asString()] = it->second;
612  }
613  }
614 
615  // reads a CHECKSUMS (old SHA1SUMS) file index
616  void Fetcher::Impl::readChecksumsIndex( const Pathname &index, const Pathname &basedir )
617  {
618  std::ifstream in( index.c_str() );
619  if ( ! in.fail() )
620  {
621  std::string buffer;
622  while ( getline( in, buffer ) )
623  {
624 
625  if ( buffer[0] == '#' )
626  continue; // simple comment
627 
628  CheckSum checksum( str::stripFirstWord( buffer, /*ltrim before strip*/true ) );
629  if ( checksum.empty() )
630  continue; // empty line | unknown cheksum format
631 
632  if ( buffer.empty() )
633  {
634  WAR << "Missing filename in CHECKSUMS file: " << index.asString() << " (" << checksum << ")" << endl;
635  continue;
636  }
637 
638  _checksums[(basedir/buffer).asString()] = checksum;
639  }
640  }
641  else
642  ZYPP_THROW(Exception("Can't open CHECKSUMS file: " + index.asString()));
643  }
644 
645  void Fetcher::Impl::downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
646  {
647  MIL << "downloading index " << resource << endl;
648  // create a new fetcher with a different state to transfer the
649  // file containing checksums and its signature
650  Fetcher fetcher;
651  // signature checker for index. We havent got the signature from
652  // the nextwork yet.
653  SignatureFileChecker sigchecker;
654 
655  // build the name of the index and the signature
656  OnMediaLocation idxloc(resource);
657  OnMediaLocation sigloc(resource);
658  OnMediaLocation keyloc(resource);
659 
660  // we should not fail the download if those don't exists
661  // the checking will warn later
662  sigloc.setOptional(true);
663  keyloc.setOptional(true);
664 
665  // calculate signature and key name
666  sigloc.changeFilename( sigloc.filename().extend(".asc") );
667  keyloc.changeFilename( keyloc.filename().extend(".key") );
668 
669  //assert_dir(dest_dir + idxloc.filename().dirname());
670 
671  // transfer the signature
672  fetcher.enqueue(sigloc);
673  fetcher.start( dest_dir, media );
674  // if we get the signature, update the checker
675  if ( PathInfo(dest_dir + sigloc.filename()).isExist() )
676  sigchecker = SignatureFileChecker(dest_dir + sigloc.filename());
677 
678  fetcher.reset();
679 
680  // now the key
681  fetcher.enqueue(keyloc);
682  fetcher.start( dest_dir, media );
683  fetcher.reset();
684 
685  // try to import the key
686  if ( PathInfo(dest_dir + keyloc.filename()).isExist() )
687  getZYpp()->keyRing()->importKey(PublicKey(dest_dir + keyloc.filename()), false);
688  else
689  WAR << "No public key specified by user for index '" << keyloc.filename() << "'"<< endl;
690 
691  // now the index itself
692  fetcher.enqueue( idxloc, FileChecker(sigchecker) );
693  fetcher.start( dest_dir, media );
694  fetcher.reset();
695  }
696 
697  // this method takes all the user pointed indexes, gets them and also tries to
698  // download their signature, and verify them. After that, its parses each one
699  // to fill the checksum cache.
701  {
702  // if there is no indexes, then just return to avoid
703  // the directory listing
704  if ( _indexes.empty() )
705  {
706  MIL << "No indexes to read." << endl;
707  return;
708  }
709 
710  for_( it_idx, _indexes.begin(), _indexes.end() )
711  {
712  if ( (*it_idx)->read )
713  {
714  DBG << "Already read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
715  }
716  else
717  {
718  // base::LogControl::TmpLineWriter shutUp;
719  downloadIndex( media, (*it_idx)->location, dest_dir );
720  // now we have the indexes in dest_dir
721  readIndex( dest_dir + (*it_idx)->location.filename(), (*it_idx)->location.filename().dirname() );
722  // Take care we don't process it again
723  MIL << "Remember read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
724  (*it_idx)->read = true;
725  }
726  }
727  MIL << "done reading indexes" << endl;
728  }
729 
730  void Fetcher::Impl::start( const Pathname &dest_dir,
731  const ProgressData::ReceiverFnc & progress )
732  {
733  if ( !_mediaSetAccess )
734  ZYPP_THROW( zypp::Exception("Called Fetcher::start without setting MediaSetAccess before.") );
735  start( dest_dir, *_mediaSetAccess, progress );
736  }
737 
738  // start processing all fetcher jobs.
739  // it processes any user pointed index first
740  void Fetcher::Impl::start( const Pathname &dest_dir,
741  MediaSetAccess &media,
742  const ProgressData::ReceiverFnc & progress_receiver )
743  {
744  _mediaSetAccess = nullptr; //reset the internally stored MediaSetAccess
745 
746  ProgressData progress(_resources.size());
747  progress.sendTo(progress_receiver);
748 
749  downloadAndReadIndexList(media, dest_dir);
750 
751  for ( const FetcherJob_Ptr & jobp : _resources )
752  {
753  if ( jobp->flags & FetcherJob::Directory )
754  {
755  const OnMediaLocation location(jobp->location);
756  addDirJobs(media, location, dest_dir, jobp->flags);
757  continue;
758  }
759 
760  // may be this code can be factored out
761  // together with the autodiscovery of indexes
762  // of addDirJobs
763  if ( ( _options & AutoAddChecksumsIndexes ) ||
764  ( _options & AutoAddContentFileIndexes ) )
765  {
766  // if auto indexing is enabled, then we need to read the
767  // index for each file. We look only in the directory
768  // where the file is. this is expensive of course.
769  filesystem::DirContent content;
770  getDirectoryContent(media, jobp->location.filename().dirname(), content);
771  // this method test for the option flags so indexes are added
772  // only if the options are enabled
773  MIL << "Autodiscovering signed indexes on '"
774  << jobp->location.filename().dirname() << "' for '"
775  << jobp->location.filename() << "'" << endl;
776 
777  autoaddIndexes(content, media, jobp->location.filename().dirname(), dest_dir);
778 
779  // also look in the root of the media
780  content.clear();
781  getDirectoryContent(media, Pathname("/"), content);
782  // this method test for the option flags so indexes are added
783  // only if the options are enabled
784  MIL << "Autodiscovering signed indexes on '"
785  << "/" << "' for '"
786  << jobp->location.filename() << "'" << endl;
787 
788  autoaddIndexes(content, media, Pathname("/"), dest_dir);
789  }
790 
791  // if the checksum is empty, but the checksum is in one of the
792  // indexes checksum, then add a checker
793  if ( jobp->location.checksum().empty() )
794  {
795  if ( _checksums.find(jobp->location.filename().asString())
796  != _checksums.end() )
797  {
798  CheckSum chksm = _checksums[jobp->location.filename().asString()];
799  ChecksumFileChecker digest_check(chksm);
800  jobp->checkers.push_back(digest_check);
801  }
802  else
803  {
804  // if the index checksum is empty too, we only add the checker
805  // if the AlwaysVerifyChecksum option is set on
806  if ( jobp->flags & FetcherJob::AlwaysVerifyChecksum )
807  {
808  // add the checker with the empty checksum
809  ChecksumFileChecker digest_check(jobp->location.checksum());
810  jobp->checkers.push_back(digest_check);
811  }
812  }
813  }
814  else
815  {
816  // checksum is not empty, so add a checksum checker
817  ChecksumFileChecker digest_check(jobp->location.checksum());
818  jobp->checkers.push_back(digest_check);
819  }
820 
821  // Provide and validate the file. If the file was not transferred
822  // and no exception was thrown, it was an optional file.
823  provideToDest( media, dest_dir, jobp );
824 
825  if ( ! progress.incr() )
826  ZYPP_THROW(AbortRequestException());
827  } // for each job
828  }
829 
831  inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
832  {
833  for ( std::list<FetcherJob_Ptr>::const_iterator it_res = obj._resources.begin(); it_res != obj._resources.end(); ++it_res )
834  {
835  str << *it_res;
836  }
837  return str;
838  }
839 
841  : _pimpl( new Impl() )
842  {}
843 
845  {}
846 
847  void Fetcher::setOptions( Fetcher::Options options )
848  {
850  }
851 
852  Fetcher::Options Fetcher::options() const
853  {
854  return _pimpl->options();
855  }
856 
857  void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile )
858  {
859  _pimpl->enqueueDigested(resource, checker, deltafile);
860  }
861 
862  void Fetcher::enqueueDir( const OnMediaLocation &resource,
863  bool recursive,
864  const FileChecker &checker )
865  {
866  _pimpl->enqueueDir(resource, recursive, checker);
867  }
868 
870  bool recursive,
871  const FileChecker &checker )
872  {
873  _pimpl->enqueueDigestedDir(resource, recursive, checker);
874  }
875 
876 
877  void Fetcher::addIndex( const OnMediaLocation &resource )
878  {
879  _pimpl->addIndex(resource);
880  }
881 
882 
883  void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
884  {
885  _pimpl->enqueue(resource, checker);
886  }
887 
888  void Fetcher::addCachePath( const Pathname &cache_dir )
889  {
890  _pimpl->addCachePath(cache_dir);
891  }
892 
894  {
895  _pimpl->reset();
896  }
897 
899  {
900  _pimpl->setMediaSetAccess( media );
901  }
902 
904  {
905  _pimpl->start( dest_dir, progress );
906  }
907 
908  void Fetcher::start( const Pathname &dest_dir,
909  MediaSetAccess &media,
910  const ProgressData::ReceiverFnc & progress_receiver )
911  {
912  _pimpl->start(dest_dir, media, progress_receiver);
913  }
914 
915  std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
916  {
917  return str << *obj._pimpl;
918  }
919 
921 } // namespace zypp
923 
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:320
void consumeIndex(const parser::susetags::RepoIndex_Ptr &data_r)
Definition: Fetcher.cc:585
#define MIL
Definition: Logger.h:79
Pathname deltafile
Definition: Fetcher.cc:107
void readContentFileIndex(const Pathname &index, const Pathname &basedir)
specific version of readIndex for content file
Definition: Fetcher.cc:603
shared_ptr< FetcherIndex > FetcherIndex_Ptr
Definition: Fetcher.cc:53
void setOptions(Options options)
Set the Fetcher options.
Definition: Fetcher.cc:847
Listentry returned by readdir.
Definition: PathInfo.h:532
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
Definition: ProgressData.h:226
void precacheFiles(const std::vector< OnMediaLocation > &files)
Tries to fetch the given files and precaches them.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Describes a resource file located on a medium.
Checks for the validity of a signature.
Definition: FileChecker.h:93
void addIndex(const OnMediaLocation &resource)
Adds an index containing metadata (for example checksums ) that will be retrieved and read before the...
Definition: Fetcher.cc:877
parser::susetags::RepoIndex_Ptr _repoindex
Definition: Fetcher.cc:588
void enqueueDigestedDir(const OnMediaLocation &resource, bool recursive, const FileChecker &checker=FileChecker())
Definition: Fetcher.cc:276
Pathname locateInCache(const OnMediaLocation &resource_r, const Pathname &destDir_r)
Tries to locate the file represented by job by looking at the cache (matching checksum is mandatory)...
Definition: Fetcher.cc:348
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:170
ZYPP_DECLARE_OPERATORS_FOR_FLAGS(DiskUsageCounter::MountPoint::HintFlags)
const char * c_str() const
String representation.
Definition: Pathname.h:110
String related utilities and Regular expression matching.
void provideToDest(MediaSetAccess &media_r, const Pathname &destDir_r, const FetcherJob_Ptr &jobp_r)
Provide the resource to dest_dir.
Definition: Fetcher.cc:522
void enqueue(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Definition: Fetcher.cc:293
void addCachePath(const Pathname &cache_dir)
adds a directory to the list of directories where to look for cached files
Definition: Fetcher.cc:888
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
If a content file is found, it is downloaded and read.
Definition: Fetcher.h:123
const CheckSum & checksum() const
The checksum of the resource on the server.
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
void enqueueDigestedDir(const OnMediaLocation &resource, bool recursive=false, const FileChecker &checker=FileChecker())
Enqueue a directory and always check for checksums.
Definition: Fetcher.cc:869
void addCachePath(const Pathname &cache_dir)
Definition: Fetcher.cc:325
OnMediaLocation location
Index localtion.
Definition: Fetcher.cc:48
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: ProgressData.h:139
std::list< FileChecker > checkers
Definition: Fetcher.cc:109
#define ERR
Definition: Logger.h:81
unsigned medianr() const
The media number the resource is located on.
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition: Fetcher.cc:155
RWCOW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: Fetcher.h:344
void enqueueDigested(const OnMediaLocation &resource, const FileChecker &checker=FileChecker(), const Pathname &deltafile=Pathname())
Enqueue a object for transferal, they will not be transferred until start() is called.
Definition: Fetcher.cc:857
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:105
void setMediaSetAccess(MediaSetAccess &media)
Sets the media set access that will be used to precache and to download the files when start is calle...
Definition: Fetcher.cc:898
void start(const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
start the transfer to a destination directory dest_dir The media has to be provides with setMediaSetA...
Definition: Fetcher.cc:903
bool operator()(const FetcherIndex_Ptr &lhs, const FetcherIndex_Ptr &rhs) const
Definition: Fetcher.cc:58
std::set< FetcherIndex_Ptr, SameFetcherIndex > _indexes
Definition: Fetcher.cc:226
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:400
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
std::string stripFirstWord(std::string &line, const bool ltrim_first)
Definition: String.cc:263
Fetcher::Options _options
Definition: Fetcher.cc:235
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Definition: Exception.cc:147
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:653
const std::string & asString() const
String representation.
Definition: Pathname.h:91
void setMediaSetAccess(MediaSetAccess &media)
Definition: Fetcher.cc:320
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
void dirInfo(filesystem::DirContent &retlist, const Pathname &dirname, bool dots=true, unsigned media_nr=1)
Fills retlist with directory information.
void reset()
Reset the transfer (jobs) list.
Definition: Fetcher.cc:893
MediaSetAccess * _mediaSetAccess
Definition: Fetcher.cc:233
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
#define WAR
Definition: Logger.h:80
void readIndex(const Pathname &index, const Pathname &basedir)
reads a downloaded index file and updates internal attributes table
Definition: Fetcher.cc:592
Parse repoindex part from a content file.
std::set ordering (less semantic)
Definition: Fetcher.cc:56
Fetcher::Options options() const
Definition: Fetcher.cc:258
Maintain [min,max] and counter (value) for progress counting.
Definition: ProgressData.h:130
void enqueueDir(const OnMediaLocation &resource, bool recursive, const FileChecker &checker=FileChecker())
Definition: Fetcher.cc:261
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
DefaultIntegral< bool, false > read
Whether we read this index.
Definition: Fetcher.cc:50
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:836
std::map< std::string, filesystem::DirContent > _dircontent
Definition: Fetcher.cc:231
OnMediaLocation location
Definition: Fetcher.cc:106
void downloadIndex(MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
download the indexes and reads them
Definition: Fetcher.cc:645
const Pathname & filename() const
The path to the resource on the medium.
std::list< FetcherJob_Ptr > _resources
Definition: Fetcher.cc:225
void start(const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress)
Definition: Fetcher.cc:730
void enqueueDigested(const OnMediaLocation &resource, const FileChecker &checker=FileChecker(), const Pathname &deltafile=Pathname())
Definition: Fetcher.cc:239
Fetcher()
Default ctor.
Definition: Fetcher.cc:840
void enqueueDir(const OnMediaLocation &resource, bool recursive=false, const FileChecker &checker=FileChecker())
Enqueue a directory.
Definition: Fetcher.cc:862
void validate(const Pathname &localfile_r, const std::list< FileChecker > &checkers_r)
Validates the provided file against its checkers.
Definition: Fetcher.cc:378
std::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
Definition: IOStream.h:50
ZYPP_DECLARE_FLAGS(Flags, Flag)
void getDirectoryContent(MediaSetAccess &media, const OnMediaLocation &resource, filesystem::DirContent &content)
reads the content of a directory but keeps a cache
Definition: Fetcher.cc:435
If a CHECKSUMS file is found, it is downloaded and read.
Definition: Fetcher.h:128
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Definition: AutoDispose.h:158
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
Class to encapsulate the OnMediaLocation object and the FileChecker together.
Definition: Fetcher.cc:78
void setOptions(Fetcher::Options options)
Definition: Fetcher.cc:255
FetcherIndex(const OnMediaLocation &loc)
Definition: Fetcher.cc:44
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Definition: PublicKey.h:275
void readChecksumsIndex(const Pathname &index, const Pathname &basedir)
specific version of readIndex for CHECKSUMS file
Definition: Fetcher.cc:616
void downloadAndReadIndexList(MediaSetAccess &media, const Pathname &dest_dir)
download the indexes and reads them
Definition: Fetcher.cc:700
Fetcher implementation.
Definition: Fetcher.cc:126
Base class for Exception.
Definition: Exception.h:145
Built in file checkers.
Definition: FileChecker.h:70
FetcherJob(const OnMediaLocation &loc, const Pathname dfile=Pathname())
Definition: Fetcher.cc:93
bool empty() const
Definition: CheckSum.cc:173
std::string checksum(const Pathname &file, const std::string &algorithm)
Compute a files checksum.
Definition: PathInfo.cc:1004
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:92
std::map< std::string, CheckSum > _checksums
Definition: Fetcher.cc:229
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
class that represents indexes which add metadata to fetcher jobs and therefore need to be retrieved i...
Definition: Fetcher.cc:42
std::set< Pathname > _caches
Definition: Fetcher.cc:227
function< void(const Pathname &file)> FileChecker
Functor signature used to check files.
Definition: FileChecker.h:28
std::ostream & operator<<(std::ostream &str, const Fetcher::Impl &obj)
Definition: Fetcher.cc:831
Options options() const
Get current options.
Definition: Fetcher.cc:852
OnMediaLocation & changeFilename(Pathname filename_r)
Individual manipulation of filename (prefer setLocation).
shared_ptr< FetcherJob > FetcherJob_Ptr
Definition: Fetcher.cc:114
void enqueue(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Enqueue a object for transferal, they will not be transferred until start() is called.
Definition: Fetcher.cc:883
virtual ~Fetcher()
Dtor.
Definition: Fetcher.cc:844
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
OnMediaLocation & setOptional(bool val)
Set whether the resource is optional.
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT, const Pathname &deltafile=Pathname())
Provides a file from a media location.
void autoaddIndexes(const filesystem::DirContent &content, MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
auto discovery and reading of indexes
Definition: Fetcher.cc:407
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1024
virtual void parse(const InputStream &imput_r, const ProgressData::ReceiverFnc &fnc_r=ProgressData::ReceiverFnc())
Parse the stream.
bool optional() const
Whether this is an optional resource.
This class allows to retrieve a group of files in a confortable way, providing some smartness that do...
Definition: Fetcher.h:105
void addIndex(const OnMediaLocation &resource)
Definition: Fetcher.cc:305
#define DBG
Definition: Logger.h:78
bool is_checksum(const Pathname &file, const CheckSum &checksum)
check files checksum
Definition: PathInfo.cc:1016
void addDirJobs(MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir, FetcherJob::Flags flags)
scan the directory and adds the individual jobs
Definition: Fetcher.cc:458
friend std::ostream & operator<<(std::ostream &str, const Fetcher::Impl &obj)
Impl * clone() const
clone for RWCOW_pointer
Definition: Fetcher.cc:222
The user is not asked anything, and the error exception is just propagated.