libzypp  17.38.7
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-core/base/Easy.h>
21 #include <zypp-core/base/DefaultIntegral>
22 #include <zypp-core/base/String.h>
23 #include <zypp-media/MediaException>
24 #include <zypp/Fetcher.h>
25 #include <zypp/ZYppFactory.h>
26 #include <zypp/CheckSum.h>
27 #include <zypp-core/base/UserRequestException>
30 
31 #undef ZYPP_BASE_LOGGER_LOGGROUP
32 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::fetcher"
33 
35 namespace zypp
36 {
37 
38  namespace {
39  // Translate leading "./(../)+" to "./(%2E%2E/)+" for Fetcher::mapToCachePath
40  inline void fixup( Pathname & path_r )
41  {
42  const std::string & s { path_r.asString() };
43 
44  // 1. Quick exit if string is too short or doesn't start with ./
45  if ( s.size() < 4 || s.compare(0, 2, "./" ) != 0 )
46  return;
47 
48  size_t count = 0;
49  size_t pos = 2;
50 
51  // 2. Count consecutive "../" sequences
52  while ( pos + 3 <= s.size() && s.compare(pos, 3, "../") == 0 ) {
53  ++count;
54  pos += 3;
55  }
56 
57  if (count == 0)
58  return;
59 
60  {
61  std::string s { path_r.asString() };
62 
63  // 3. Resize string once to avoid multiple reallocations
64  size_t original_size = s.size();
65  size_t added_space = count * 4; // ".."(2) becomes "%2E%2E"(6)
66  s.resize(original_size + added_space);
67 
68  // 4. Move the 'tail' of the string to the new end
69  size_t tail_start = 2 + (count * 3);
70  size_t tail_length = original_size - tail_start;
71  if (tail_length > 0) {
72  std::copy_backward(s.begin() + tail_start, s.begin() + original_size, s.end());
73  }
74 
75  // 5. Fill the gap with %2E%2E/
76  size_t write_pos = 2;
77  for (size_t i = 0; i < count; ++i) {
78  s.replace(write_pos, 7, "%2E%2E/");
79  write_pos += 7;
80  }
81 
82  path_r = s;
83  }
84  }
85  } // namespace
86 
92  struct FetcherIndex
93  {
95  : location(loc)
96  {}
101  };
102 
103  using FetcherIndex_Ptr = shared_ptr<FetcherIndex>;
104 
107  {
108  bool operator()( const FetcherIndex_Ptr & lhs, const FetcherIndex_Ptr & rhs ) const
109  {
110  if ( lhs == rhs )
111  return false; // incl. NULL == NULL
112  if ( ! lhs )
113  return true; // NULL < nonNULL
114  if ( ! rhs )
115  return false; // nonNULL > NULL
116  // both nonNULL ==> compare medianr and path
117  if ( lhs->location.medianr() == rhs->location.medianr() )
118  return lhs->location.filename() < rhs->location.filename();
119  //else
120  return lhs->location.medianr() < rhs->location.medianr();
121  }
122  };
123 
128  struct FetcherJob
129  {
130  enum Flag
131  {
132  None = 0x0000,
133  Directory = 0x0001,
134  Recursive = 0x0002,
136  // check checksums even if there is no such
137  // checksum (warns of no checksum)
139  };
140  ZYPP_DECLARE_FLAGS(Flags, Flag);
141 
142  FetcherJob(const FetcherJob &) = default;
143  FetcherJob(FetcherJob &&) = default;
144  FetcherJob &operator=(const FetcherJob &) = default;
145  FetcherJob &operator=(FetcherJob &&) = default;
146 
148  //MIL << location << endl;
149  }
150 
152  {
153  //MIL << location << " | * " << checkers.size() << endl;
154  }
155 
157  //CompositeFileChecker checkers;
158  std::list<FileChecker> checkers;
159  Flags flags;
160  };
161 
162  ZYPP_DECLARE_OPERATORS_FOR_FLAGS(FetcherJob::Flags);
163  using FetcherJob_Ptr = shared_ptr<FetcherJob>;
164 
165  std::ostream & operator<<( std::ostream & str, const FetcherJob_Ptr & obj )
166  {
167  return str << obj->location;
168  }
169 
171  //
172  // CLASS NAME : Fetcher::Impl
173  //
176  {
177  friend std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj );
178 
179  public:
180  Impl();
181 
182  Impl(const Impl &) = default;
183  Impl(Impl &&) = delete;
184  Impl &operator=(const Impl &) = delete;
185  Impl &operator=(Impl &&) = delete;
186 
187  ~Impl() {}
188 
189  struct CacheInfo{
192 
193  friend bool operator<( const CacheInfo &a, const CacheInfo & b) {
194  return a._pathName < b._pathName;
195  }
196  };
197 
198  void setOptions( Fetcher::Options options );
199  Fetcher::Options options() const;
200 
201  void addIndex( const OnMediaLocation &resource );
202 
203  void enqueueDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
204  void enqueueDigestedDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
205 
206  void enqueue( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() );
207  void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() );
208  void addCachePath( const Pathname &cache_dir, Fetcher::CacheOptions options );
209  void reset();
210  void setMediaSetAccess ( MediaSetAccess &media );
211  void start( const Pathname &dest_dir,
212  const ProgressData::ReceiverFnc &progress );
213  void start( const Pathname &dest_dir,
214  MediaSetAccess &media,
215  const ProgressData::ReceiverFnc & progress_receiver );
216 
218  static shared_ptr<Impl> nullimpl()
219  {
220  static shared_ptr<Impl> _nullimpl( new Impl );
221  return _nullimpl;
222  }
223  private:
227  void downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir);
228 
232  void downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir);
233 
241  void readIndex( const Pathname &index, const Pathname &basedir );
242 
244  void readChecksumsIndex( const Pathname &index, const Pathname &basedir );
245 
247  void readContentFileIndex( const Pathname &index, const Pathname &basedir );
248 
250  void getDirectoryContent( MediaSetAccess &media, const OnMediaLocation &resource, filesystem::DirContent &content );
251 
258  ManagedFile locateInCache( const OnMediaLocation & resource_r, const Pathname & destDir_r, const Pathname & inCachePath_r );
263  void validate( const Pathname & localfile_r, const std::list<FileChecker> & checkers_r );
264 
268  void addDirJobs( MediaSetAccess &media, const OnMediaLocation &resource,
269  const Pathname &dest_dir, FetcherJob::Flags flags );
270 
274  void autoaddIndexes( const filesystem::DirContent &content,
275  MediaSetAccess &media,
276  const OnMediaLocation &resource,
277  const Pathname &dest_dir );
281  void provideToDest( MediaSetAccess & media_r, const Pathname & destDir_r , const FetcherJob_Ptr & jobp_r );
282 
283  private:
284  friend Impl * rwcowClone<Impl>( const Impl * rhs );
286  Impl * clone() const
287  { return new Impl( *this ); }
288 
289  std::list<FetcherJob_Ptr> _resources;
290  std::set<FetcherIndex_Ptr,SameFetcherIndex> _indexes;
291  std::set<CacheInfo> _caches;
292  // checksums read from the indexes
293  std::map<std::string, CheckSum> _checksums;
294  // cache of dir contents
295  std::map<std::string, filesystem::DirContent> _dircontent;
296 
298 
299  Fetcher::Options _options;
300  };
302 
304  {
305  if ( _mediaSetAccess )
306  _mediaSetAccess->precacheFiles( {resource} );
307 
308  FetcherJob_Ptr job;
309  job.reset(new FetcherJob(resource));
310  job->flags |= FetcherJob:: AlwaysVerifyChecksum;
311  _resources.push_back(job);
312  }
313 
315  : _options(0)
316  {
317  }
318 
319  void Fetcher::Impl::setOptions( Fetcher::Options options )
320  { _options = options; }
321 
322  Fetcher::Options Fetcher::Impl::options() const
323  { return _options; }
324 
326  bool recursive,
327  const FileChecker &checker )
328  {
329  FetcherJob_Ptr job;
330  job.reset(new FetcherJob(resource));
331  if ( checker )
332  job->checkers.push_back(checker);
333  if ( recursive )
334  job->flags |= FetcherJob::Recursive;
335  job->flags |= FetcherJob::Directory;
336 
337  _resources.push_back(job);
338  }
339 
341  bool recursive,
342  const FileChecker &checker )
343  {
344  FetcherJob_Ptr job;
345  job.reset(new FetcherJob(resource));
346  if ( checker )
347  job->checkers.push_back(checker);
348  if ( recursive )
349  job->flags |= FetcherJob::Recursive;
350  job->flags |= FetcherJob::Directory;
351  job->flags |= FetcherJob::AlwaysVerifyChecksum;
352 
353  _resources.push_back(job);
354 
355  }
356 
357  void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
358  {
359  if ( _mediaSetAccess )
360  _mediaSetAccess->precacheFiles( {resource} );
361 
362  FetcherJob_Ptr job;
363  job.reset(new FetcherJob(resource));
364  if ( checker )
365  job->checkers.push_back(checker);
366  _resources.push_back(job);
367  }
368 
369  void Fetcher::Impl::addIndex( const OnMediaLocation &resource )
370  {
371  MIL << "adding index " << resource << endl;
372  _indexes.insert(FetcherIndex_Ptr(new FetcherIndex(resource)));
373  }
374 
375 
377  {
378  _resources.clear();
379  _indexes.clear();
380  _checksums.clear();
381  _dircontent.clear();
382  }
383 
385  {
386  _mediaSetAccess = &media;
387  }
388 
390  {
391  PathInfo info(cache_dir);
392  if ( info.isExist() )
393  {
394  if ( info.isDir() )
395  {
396  DBG << "Adding fetcher cache: '" << cache_dir << "'." << endl;
397  _caches.insert( { cache_dir, options } );
398  }
399  else
400  {
401  // don't add bad cache directory, just log the error
402  ERR << "Not adding cache: '" << cache_dir << "'. Not a directory." << endl;
403  }
404  }
405  else
406  {
407  WAR << "Not adding cache '" << cache_dir << "'. Path does not exists." << endl;
408  }
409 
410  }
411 
412  ManagedFile Fetcher::Impl::locateInCache( const OnMediaLocation & resource_r, const Pathname & destDir_r, const Pathname & inCachePath_r )
413  {
414  // No checksum - no match
415  if ( resource_r.checksum().empty() )
416  return {};
417 
418  // first check in the final destination
419  ManagedFile cacheLocation { destDir_r / inCachePath_r };
420  if ( PathInfo(cacheLocation).isExist() && is_checksum( cacheLocation, resource_r.checksum() ) ) {
421  pMIL( "file", inCachePath_r, "found at", destDir_r );
422  return cacheLocation;
423  }
424 
425  for( const CacheInfo & cacheInfo : _caches ) {
426  cacheLocation = ManagedFile( cacheInfo._pathName / inCachePath_r );
427  if ( PathInfo(cacheLocation).isExist() && is_checksum( cacheLocation, resource_r.checksum() ) )
428  {
429  pMIL( "file", inCachePath_r, "found in cache", cacheInfo._pathName );
430  if ( cacheInfo._options & Fetcher::CleanFiles )
431  cacheLocation.setDispose( filesystem::unlink );
432  return cacheLocation;
433  }
434  }
435 
436  return {};
437  }
438 
439  void Fetcher::Impl::validate( const Pathname & localfile_r, const std::list<FileChecker> & checkers_r )
440  {
441  try
442  {
443  MIL << "Checking job [" << localfile_r << "] (" << checkers_r.size() << " checkers )" << endl;
444 
445  for ( const FileChecker & chkfnc : checkers_r )
446  {
447  if ( chkfnc )
448  chkfnc( localfile_r );
449  else
450  ERR << "Invalid checker for '" << localfile_r << "'" << endl;
451  }
452 
453  }
454  catch ( const FileCheckException &e )
455  {
456  throw; // let known exceptions bypass silently
457  }
458  catch ( const Exception &e )
459  {
460  throw; // slet known exceptions bypass silently
461  }
462  catch (...)
463  {
464  ZYPP_THROW(Exception("Unknown error while validating " + localfile_r.asString()));
465  }
466  }
467 
469  MediaSetAccess &media,
470  const OnMediaLocation &resource,
471  const Pathname &dest_dir )
472  {
473  auto fnc_addIfInContent( [&]( const std::string & index_r ) -> bool
474  {
475  if ( find( content.begin(), content.end(), filesystem::DirEntry(index_r,filesystem::FT_FILE) ) == content.end() )
476  return false;
477  // add the index of this directory
478  OnMediaLocation indexloc( resource );
479  indexloc.changeFilename( resource.filename() + index_r );
480  addIndex( indexloc );
481  // we need to read it now
482  downloadAndReadIndexList( media, dest_dir );
483  return true;
484  } );
485 
487  {
488  fnc_addIfInContent( "CHECKSUMS" ) || fnc_addIfInContent( "SHA1SUMS" );
489  }
491  {
492  fnc_addIfInContent( "content" );
493  }
494  }
495 
497  const OnMediaLocation &resource,
498  filesystem::DirContent &content )
499  {
500  if ( _dircontent.find(resource.filename().asString())
501  != _dircontent.end() )
502  {
503  filesystem::DirContent filled(_dircontent[resource.filename().asString()]);
504 
505  std::copy(filled.begin(), filled.end(), std::back_inserter(content));
506  }
507  else
508  {
509  filesystem::DirContent tofill;
510  media.dirInfo( tofill,
511  resource.filename(),
512  false /* dots */,
513  resource.medianr());
514  std::copy(tofill.begin(), tofill.end(), std::back_inserter(content));
515  _dircontent[resource.filename().asString()] = tofill;
516  }
517  }
518 
520  const OnMediaLocation &resource,
521  const Pathname &dest_dir, FetcherJob::Flags flags )
522  {
523  // first get the content of the directory so we can add
524  // individual transfer jobs
525  MIL << "Adding directory " << resource.filename() << endl;
526  filesystem::DirContent content;
527  try {
528  getDirectoryContent(media, resource, content);
529  }
530  catch ( media::MediaFileNotFoundException & exception )
531  {
532  ZYPP_CAUGHT( exception );
533  WAR << "Skipping subtree hidden at " << resource.filename() << endl;
534  return;
535  }
536 
537  // this method test for the option flags so indexes are added
538  // only if the options are enabled
539  autoaddIndexes(content, media, resource, dest_dir);
540 
541  for ( filesystem::DirContent::const_iterator it = content.begin();
542  it != content.end();
543  ++it )
544  {
545  // skip CHECKSUMS* as they were already retrieved
546  if ( str::hasPrefix(it->name, "CHECKSUMS") || str::hasPrefix(it->name, "SHA1SUMS") )
547  continue;
548 
549  Pathname filename = resource.filename() + it->name;
550 
551  switch ( it->type )
552  {
553  case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
554  case filesystem::FT_FILE:
555  {
556  CheckSum chksm(resource.checksum());
557  if ( _checksums.find(filename.asString()) != _checksums.end() )
558  {
559  // the checksum can be replaced with the one in the index.
560  chksm = _checksums[filename.asString()];
561  //MIL << "resource " << filename << " has checksum in the index file." << endl;
562  }
563  else
564  WAR << "Resource " << filename << " has no checksum in the index either." << endl;
565 
566  if ( flags & FetcherJob::AlwaysVerifyChecksum )
567  enqueueDigested(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
568  else
569  enqueue(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
570  break;
571  }
572  case filesystem::FT_DIR: // newer directory.yast contain at least directory info
573  if ( flags & FetcherJob::Recursive )
574  addDirJobs(media, filename, dest_dir, flags);
575  break;
576  default:
577  // don't provide devices, sockets, etc.
578  break;
579  }
580  }
581  }
582 
583  void Fetcher::Impl::provideToDest( MediaSetAccess & media_r, const Pathname & destDir_r , const FetcherJob_Ptr & jobp_r )
584  {
585  const OnMediaLocation & resource { jobp_r->location };
586  Pathname inCachePath { mapToCachePath( resource ) }; // Map remote filename to a local path below destDir_r.
587  Pathname finalDestination { destDir_r / inCachePath }; // The full destination path.
588 
589  try
590  {
591  scoped_ptr<MediaSetAccess::ReleaseFileGuard> releaseFileGuard; // will take care provided files get released
592  Pathname candidate;
593 
594  // Try to get cached file (by checksum) or provide it from media.
595  ManagedFile cachedFile = locateInCache( resource, destDir_r, inCachePath );
596  if ( (*cachedFile).empty() ) {
597  pMIL( "file", inCachePath, "not found in cache, retrieving..." );
599  releaseFileGuard.reset( new MediaSetAccess::ReleaseFileGuard( media_r, resource ) ); // release it when we leave the block
600  } else {
601  candidate = cachedFile;
602  }
603 
604  if ( candidate == finalDestination ) {
605  // If we have a match at destFullPath, take care
606  // it gets deleted, in case the validation fails.
607  cachedFile.setDispose( filesystem::unlink );
608  }
609 
610  // Validate the file (throws if not valid)
611  validate( candidate, jobp_r->checkers );
612 
613  // move it to the final destination
614  if ( candidate == finalDestination )
615  cachedFile.resetDispose(); // keep it!
616  else
617  {
618  if ( assert_dir( finalDestination.dirname() ) != 0 )
619  ZYPP_THROW( Exception( str::sprint( "Can't create", finalDestination.dirname() ) ) );
620 
621  if ( filesystem::hardlinkCopy( candidate, finalDestination ) != 0 )
622  ZYPP_THROW( Exception( str::sprint( "Can't hardlink/copy", candidate, "to", finalDestination ) ) );
623  }
624  }
625  catch ( Exception & excpt )
626  {
627  if ( resource.optional() )
628  {
629  ZYPP_CAUGHT( excpt );
630  WAR << "Optional resource " << resource << " could not be transferred." << endl;
631  return;
632  }
633  else
634  {
635  excpt.remember( str::sprint("Can't provide", resource.filename() ) );
636  ZYPP_RETHROW( excpt );
637  }
638  }
639  }
640 
641  // helper class to consume a content file
643  {
645  {
646  setRepoIndexConsumer( bind( &ContentReaderHelper::consumeIndex, this, _1 ) );
647  }
648 
649  void consumeIndex( const parser::susetags::RepoIndex_Ptr & data_r )
650  { _repoindex = data_r; }
651 
652  parser::susetags::RepoIndex_Ptr _repoindex;
653  };
654 
655  // generic function for reading indexes
656  void Fetcher::Impl::readIndex( const Pathname &index, const Pathname &basedir )
657  {
658  if ( index.basename() == "CHECKSUMS" || index.basename() == "SHA1SUMS" )
659  readChecksumsIndex(index, basedir);
660  else if ( index.basename() == "content" )
661  readContentFileIndex(index, basedir);
662  else
663  WAR << index << ": index file format not known" << endl;
664  }
665 
666  // reads a content file index
667  void Fetcher::Impl::readContentFileIndex( const Pathname &index, const Pathname &basedir )
668  {
669  ContentReaderHelper reader;
670  reader.parse(index);
671  MIL << index << " contains " << reader._repoindex->mediaFileChecksums.size() << " checksums." << endl;
672  for_( it, reader._repoindex->mediaFileChecksums.begin(), reader._repoindex->mediaFileChecksums.end() )
673  {
674  // content file entries don't start with /
675  _checksums[(basedir + it->first).asString()] = it->second;
676  }
677  }
678 
679  // reads a CHECKSUMS (old SHA1SUMS) file index
680  void Fetcher::Impl::readChecksumsIndex( const Pathname &index, const Pathname &basedir )
681  {
682  std::ifstream in( index.c_str() );
683  if ( ! in.fail() )
684  {
685  std::string buffer;
686  while ( getline( in, buffer ) )
687  {
688 
689  if ( buffer[0] == '#' )
690  continue; // simple comment
691 
692  CheckSum checksum( str::stripFirstWord( buffer, /*ltrim before strip*/true ) );
693  if ( checksum.empty() )
694  continue; // empty line | unknown cheksum format
695 
696  if ( buffer.empty() )
697  {
698  WAR << "Missing filename in CHECKSUMS file: " << index.asString() << " (" << checksum << ")" << endl;
699  continue;
700  }
701 
702  _checksums[(basedir/buffer).asString()] = checksum;
703  }
704  }
705  else
706  ZYPP_THROW(Exception("Can't open CHECKSUMS file: " + index.asString()));
707  }
708 
709  void Fetcher::Impl::downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
710  {
711  MIL << "downloading index " << resource << endl;
712  // create a new fetcher with a different state to transfer the
713  // file containing checksums and its signature
714  Fetcher fetcher;
715  // signature checker for index. We havent got the signature from
716  // the nextwork yet.
717  SignatureFileChecker sigchecker;
718 
719  // build the name of the index and the signature
720  const OnMediaLocation& idxloc(resource);
721  OnMediaLocation sigloc(resource);
722  OnMediaLocation keyloc(resource);
723 
724  // we should not fail the download if those don't exists
725  // the checking will warn later
726  sigloc.setOptional(true);
727  keyloc.setOptional(true);
728 
729  // calculate signature and key name
730  sigloc.changeFilename( sigloc.filename().extend(".asc") );
731  keyloc.changeFilename( keyloc.filename().extend(".key") );
732 
733  //assert_dir(dest_dir + idxloc.filename().dirname());
734 
735  // transfer the signature
736  fetcher.enqueue(sigloc);
737  fetcher.start( dest_dir, media );
738  // if we get the signature, update the checker
739  if ( PathInfo(dest_dir + sigloc.filename()).isExist() )
740  sigchecker = SignatureFileChecker(dest_dir + sigloc.filename());
741 
742  fetcher.reset();
743 
744  // now the key
745  fetcher.enqueue(keyloc);
746  fetcher.start( dest_dir, media );
747  fetcher.reset();
748 
749  // try to import the key
750  if ( PathInfo(dest_dir + keyloc.filename()).isExist() )
751  getZYpp()->keyRing()->importKey(PublicKey(dest_dir + keyloc.filename()), false);
752  else
753  WAR << "No public key specified by user for index '" << keyloc.filename() << "'"<< endl;
754 
755  // now the index itself
756  fetcher.enqueue( idxloc, FileChecker(sigchecker) );
757  fetcher.start( dest_dir, media );
758  fetcher.reset();
759  }
760 
761  // this method takes all the user pointed indexes, gets them and also tries to
762  // download their signature, and verify them. After that, it parses each one
763  // to fill the checksum cache.
765  {
766  // if there is no indexes, then just return to avoid
767  // the directory listing
768  if ( _indexes.empty() )
769  {
770  MIL << "No indexes to read." << endl;
771  return;
772  }
773 
774  for_( it_idx, _indexes.begin(), _indexes.end() )
775  {
776  if ( (*it_idx)->read )
777  {
778  DBG << "Already read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
779  }
780  else
781  {
782  // base::LogControl::TmpLineWriter shutUp;
783  downloadIndex( media, (*it_idx)->location, dest_dir );
784  // now we have the indexes in dest_dir
785  readIndex( dest_dir + (*it_idx)->location.filename(), (*it_idx)->location.filename().dirname() );
786  // Take care we don't process it again
787  MIL << "Remember read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
788  (*it_idx)->read = true;
789  }
790  }
791  MIL << "done reading indexes" << endl;
792  }
793 
794  void Fetcher::Impl::start( const Pathname &dest_dir,
795  const ProgressData::ReceiverFnc & progress )
796  {
797  if ( !_mediaSetAccess )
798  ZYPP_THROW( zypp::Exception("Called Fetcher::start without setting MediaSetAccess before.") );
799  start( dest_dir, *_mediaSetAccess, progress );
800  }
801 
802  // start processing all fetcher jobs.
803  // it processes any user pointed index first
804  void Fetcher::Impl::start( const Pathname &dest_dir,
805  MediaSetAccess &media,
806  const ProgressData::ReceiverFnc & progress_receiver )
807  {
808  _mediaSetAccess = nullptr; //reset the internally stored MediaSetAccess
809 
810  ProgressData progress(_resources.size());
811  progress.sendTo(progress_receiver);
812 
813  downloadAndReadIndexList(media, dest_dir);
814 
815  for ( const FetcherJob_Ptr & jobp : _resources )
816  {
817  if ( jobp->flags & FetcherJob::Directory )
818  {
819  const OnMediaLocation location(jobp->location);
820  addDirJobs(media, location, dest_dir, jobp->flags);
821  continue;
822  }
823 
824  // may be this code can be factored out
825  // together with the autodiscovery of indexes
826  // of addDirJobs
827  if ( ( _options & AutoAddChecksumsIndexes ) ||
829  {
830  // if auto indexing is enabled, then we need to read the
831  // index for each file. We look only in the directory
832  // where the file is. this is expensive of course.
833  filesystem::DirContent content;
834  getDirectoryContent(media, jobp->location.filename().dirname(), content);
835  // this method test for the option flags so indexes are added
836  // only if the options are enabled
837  MIL << "Autodiscovering signed indexes on '"
838  << jobp->location.filename().dirname() << "' for '"
839  << jobp->location.filename() << "'" << endl;
840 
841  autoaddIndexes(content, media, jobp->location.filename().dirname(), dest_dir);
842 
843  // also look in the root of the media
844  content.clear();
845  getDirectoryContent(media, Pathname("/"), content);
846  // this method test for the option flags so indexes are added
847  // only if the options are enabled
848  MIL << "Autodiscovering signed indexes on '"
849  << "/" << "' for '"
850  << jobp->location.filename() << "'" << endl;
851 
852  autoaddIndexes(content, media, Pathname("/"), dest_dir);
853  }
854 
855  // if the checksum is empty, but the checksum is in one of the
856  // indexes checksum, then add a checker
857  if ( jobp->location.checksum().empty() )
858  {
859  if ( _checksums.find(jobp->location.filename().asString())
860  != _checksums.end() )
861  {
862  CheckSum chksm = _checksums[jobp->location.filename().asString()];
863  ChecksumFileChecker digest_check(chksm);
864  jobp->checkers.push_back(digest_check);
865  }
866  else
867  {
868  // if the index checksum is empty too, we only add the checker
869  // if the AlwaysVerifyChecksum option is set on
870  if ( jobp->flags & FetcherJob::AlwaysVerifyChecksum )
871  {
872  // add the checker with the empty checksum
873  ChecksumFileChecker digest_check(jobp->location.checksum());
874  jobp->checkers.push_back(digest_check);
875  }
876  }
877  }
878  else
879  {
880  // checksum is not empty, so add a checksum checker
881  ChecksumFileChecker digest_check(jobp->location.checksum());
882  jobp->checkers.push_back(digest_check);
883  }
884 
885  // Provide and validate the file. If the file was not transferred
886  // and no exception was thrown, it was an optional file.
887  provideToDest( media, dest_dir, jobp );
888 
889  if ( ! progress.incr() )
890  ZYPP_THROW(AbortRequestException());
891  } // for each job
892  }
893 
895  inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
896  {
897  for ( std::list<FetcherJob_Ptr>::const_iterator it_res = obj._resources.begin(); it_res != obj._resources.end(); ++it_res )
898  {
899  str << *it_res;
900  }
901  return str;
902  }
903 
905  : _pimpl( new Impl() )
906  {}
907 
909  {}
910 
911  void Fetcher::setOptions( Fetcher::Options options )
912  {
914  }
915 
916  Fetcher::Options Fetcher::options() const
917  {
918  return _pimpl->options();
919  }
920 
921  void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile )
922  {
923  enqueueDigested( OnMediaLocation(resource).setDeltafile(deltafile), checker );
924  }
925 
926  void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
927  {
928  _pimpl->enqueueDigested( resource, checker );
929  }
930 
931  void Fetcher::enqueueDir( const OnMediaLocation &resource,
932  bool recursive,
933  const FileChecker &checker )
934  {
935  _pimpl->enqueueDir(resource, recursive, checker);
936  }
937 
939  bool recursive,
940  const FileChecker &checker )
941  {
942  _pimpl->enqueueDigestedDir(resource, recursive, checker);
943  }
944 
945 
946  void Fetcher::addIndex( const OnMediaLocation &resource )
947  {
948  _pimpl->addIndex(resource);
949  }
950 
951 
952  void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
953  {
954  _pimpl->enqueue(resource, checker);
955  }
956 
957 
958  void Fetcher::addCachePath( const Pathname &cache_dir )
959  {
960  _pimpl->addCachePath(cache_dir, Fetcher::Default);
961  }
962 
963  void Fetcher::addCachePath(const Pathname &cache_dir, CacheOptions options)
964  {
965  _pimpl->addCachePath(cache_dir, options);
966  }
967 
969  {
970  _pimpl->reset();
971  }
972 
974  {
975  _pimpl->setMediaSetAccess( media );
976  }
977 
979  {
980  _pimpl->start( dest_dir, progress );
981  }
982 
983  void Fetcher::start( const Pathname &dest_dir,
984  MediaSetAccess &media,
985  const ProgressData::ReceiverFnc & progress_receiver )
986  {
987  _pimpl->start(dest_dir, media, progress_receiver);
988  }
989 
991  {
992  fixup( remotePath_r );
993  return remotePath_r;
994  }
995 
996  std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
997  {
998  return str << *obj._pimpl;
999  }
1000 
1002 } // namespace zypp
1004 
void consumeIndex(const parser::susetags::RepoIndex_Ptr &data_r)
Definition: Fetcher.cc:649
#define MIL
Definition: Logger.h:103
std::set< CacheInfo > _caches
Definition: Fetcher.cc:291
void readContentFileIndex(const Pathname &index, const Pathname &basedir)
specific version of readIndex for content file
Definition: Fetcher.cc:667
Pathname deltafile
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:338
void setOptions(Options options)
Set the Fetcher options.
Definition: Fetcher.cc:911
Listentry returned by readdir.
Definition: PathInfo.h:517
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides a file from a media location.
void enqueueDigested(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Definition: Fetcher.cc:303
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
Definition: progressdata.h:229
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:459
Describes a resource file located on a medium.
unsigned short b
Checks for the validity of a signature.
Definition: FileChecker.h:70
std::string asString(const Patch::Category &obj)
relates: Patch::Category string representation.
Definition: Patch.cc:122
FetcherJob & operator=(const FetcherJob &)=default
void addIndex(const OnMediaLocation &resource)
Adds an index containing metadata (for example checksums ) that will be retrieved and read before the...
Definition: Fetcher.cc:946
parser::susetags::RepoIndex_Ptr _repoindex
Definition: Fetcher.cc:652
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: progressdata.h:140
void enqueueDigestedDir(const OnMediaLocation &resource, bool recursive, const FileChecker &checker=FileChecker())
Definition: Fetcher.cc:340
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:182
ZYPP_DECLARE_OPERATORS_FOR_FLAGS(DiskUsageCounter::MountPoint::HintFlags)
const char * c_str() const
String representation.
Definition: Pathname.h:113
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:583
void enqueue(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Definition: Fetcher.cc:357
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
void addCachePath(const Pathname &cache_dir)
adds a directory to the list of directories where to look for cached files
Definition: Fetcher.cc:958
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
If a content file is found, it is downloaded and read.
Definition: Fetcher.h:131
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:137
static Pathname mapToCachePath(Pathname remotePath_r)
Map a resource filename to a local path below a destDir.
Definition: Fetcher.cc:990
void enqueueDigestedDir(const OnMediaLocation &resource, bool recursive=false, const FileChecker &checker=FileChecker())
Enqueue a directory and always check for checksums.
Definition: Fetcher.cc:938
OnMediaLocation location
Index localtion.
Definition: Fetcher.cc:98
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:534
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:902
std::list< FileChecker > checkers
Definition: Fetcher.cc:158
#define ERR
Definition: Logger.h:105
shared_ptr< FetcherJob > FetcherJob_Ptr
Definition: Fetcher.cc:163
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
unsigned medianr() const
The media number the resource is located on.
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition: Fetcher.cc:218
RWCOW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: Fetcher.h:379
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:154
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:973
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:978
Impl & operator=(const Impl &)=delete
bool operator()(const FetcherIndex_Ptr &lhs, const FetcherIndex_Ptr &rhs) const
Definition: Fetcher.cc:108
std::set< FetcherIndex_Ptr, SameFetcherIndex > _indexes
Definition: Fetcher.cc:290
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:479
void addCachePath(const Pathname &cache_dir, Fetcher::CacheOptions options)
Definition: Fetcher.cc:389
FetcherJob(const FetcherJob &)=default
std::string stripFirstWord(std::string &line, const bool ltrim_first)
Definition: String.cc:266
Fetcher::Options _options
Definition: Fetcher.cc:299
const std::string & asString() const
String representation.
Definition: Pathname.h:94
void setMediaSetAccess(MediaSetAccess &media)
Definition: Fetcher.cc:384
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:286
void dirInfo(filesystem::DirContent &retlist, const Pathname &dirname, bool dots=true, unsigned media_nr=1)
Fills retlist with directory information.
friend bool operator<(const CacheInfo &a, const CacheInfo &b)
Definition: Fetcher.cc:193
void reset()
Reset the transfer (jobs) list.
Definition: Fetcher.cc:968
MediaSetAccess * _mediaSetAccess
Definition: Fetcher.cc:297
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:133
#define WAR
Definition: Logger.h:104
void readIndex(const Pathname &index, const Pathname &basedir)
reads a downloaded index file and updates internal attributes table
Definition: Fetcher.cc:656
Parse repoindex part from a content file.
FetcherJob(const OnMediaLocation &loc)
Definition: Fetcher.cc:147
std::set ordering (less semantic)
Definition: Fetcher.cc:106
Fetcher::Options options() const
Definition: Fetcher.cc:322
Maintain [min,max] and counter (value) for progress counting.
Definition: progressdata.h:131
void enqueueDir(const OnMediaLocation &resource, bool recursive, const FileChecker &checker=FileChecker())
Definition: Fetcher.cc:325
friend std::ostream & operator<<(std::ostream &str, const Fetcher &obj)
relates: Fetcher Stream output
Definition: Fetcher.cc:996
DefaultIntegral< bool, false > read
Whether we read this index.
Definition: Fetcher.cc:100
std::map< std::string, filesystem::DirContent > _dircontent
Definition: Fetcher.cc:295
OnMediaLocation location
Definition: Fetcher.cc:156
void enqueueDigested(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Enqueue a object for transferal, they will not be transferred until start() is called.
Definition: Fetcher.cc:926
void downloadIndex(MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
download the indexes and reads them
Definition: Fetcher.cc:709
const Pathname & filename() const
The path to the resource on the medium.
std::list< FetcherJob_Ptr > _resources
Definition: Fetcher.cc:289
void start(const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress)
Definition: Fetcher.cc:794
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:719
Fetcher()
Default ctor.
Definition: Fetcher.cc:904
void resetDispose()
Set no dispose function.
Definition: AutoDispose.h:171
void enqueueDir(const OnMediaLocation &resource, bool recursive=false, const FileChecker &checker=FileChecker())
Enqueue a directory.
Definition: Fetcher.cc:931
void validate(const Pathname &localfile_r, const std::list< FileChecker > &checkers_r)
Validates the provided file against its checkers.
Definition: Fetcher.cc:439
std::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
Definition: IOStream.h:51
ZYPP_DECLARE_FLAGS(Flags, Flag)
shared_ptr< FetcherIndex > FetcherIndex_Ptr
Definition: Fetcher.cc:103
void getDirectoryContent(MediaSetAccess &media, const OnMediaLocation &resource, filesystem::DirContent &content)
reads the content of a directory but keeps a cache
Definition: Fetcher.cc:496
If a CHECKSUMS file is found, it is downloaded and read.
Definition: Fetcher.h:136
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Definition: AutoDispose.h:167
ZYpp::Ptr getZYpp()
relates: ZYppFactory Convenience to get the Pointer to the ZYpp instance.
Definition: ZYppFactory.h:77
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:475
Class to encapsulate the OnMediaLocation object and the FileChecker together.
Definition: Fetcher.cc:128
#define pMIL
Definition: LogTools.h:305
void setOptions(Fetcher::Options options)
Definition: Fetcher.cc:319
zypp::parser::susetags::RepoIndex_Ptr _repoindex
Definition: susetags.cc:306
FetcherIndex(const OnMediaLocation &loc)
Definition: Fetcher.cc:94
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Definition: PublicKey.h:374
void readChecksumsIndex(const Pathname &index, const Pathname &basedir)
specific version of readIndex for CHECKSUMS file
Definition: Fetcher.cc:680
void downloadAndReadIndexList(MediaSetAccess &media, const Pathname &dest_dir)
download the indexes and reads them
Definition: Fetcher.cc:764
Fetcher implementation.
Definition: Fetcher.cc:175
Base class for Exception.
Definition: Exception.h:152
Built in file checkers.
Definition: FileChecker.h:47
bool empty() const
Definition: CheckSum.cc:173
std::string checksum(const Pathname &file, const std::string &algorithm)
Compute a files checksum.
Definition: PathInfo.cc:1070
unsigned short a
std::map< std::string, CheckSum > _checksums
Definition: Fetcher.cc:293
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:225
ManagedFile locateInCache(const OnMediaLocation &resource_r, const Pathname &destDir_r, const Pathname &inCachePath_r)
Tries to locate the file represented by the job by looking at it&#39;s final destination first and at the...
Definition: Fetcher.cc:412
class that represents indexes which add metadata to fetcher jobs and therefore need to be retrieved i...
Definition: Fetcher.cc:92
std::ostream & operator<<(std::ostream &str, const Capabilities &obj)
relates: Capabilities Stream output
Definition: Capabilities.cc:65
function< void(const Pathname &file)> FileChecker
Functor signature used to check files.
Definition: FileChecker.h:29
Options options() const
Get current options.
Definition: Fetcher.cc:916
OnMediaLocation & changeFilename(Pathname filename_r)
Individual manipulation of filename (prefer setLocation).
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:952
virtual ~Fetcher()
Dtor.
Definition: Fetcher.cc:908
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
OnMediaLocation & setOptional(bool val)
Set whether the resource is optional.
std::string sprint(Args &&... args)
Print words as string.
Definition: LogTools.h:266
void autoaddIndexes(const filesystem::DirContent &content, MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
auto discovery and reading of indexes
Definition: Fetcher.cc:468
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1098
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:113
Fetcher::CacheOptions _options
Definition: Fetcher.cc:191
void addIndex(const OnMediaLocation &resource)
Definition: Fetcher.cc:369
#define DBG
Definition: Logger.h:102
bool is_checksum(const Pathname &file, const CheckSum &checksum)
check files checksum
Definition: PathInfo.cc:1082
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:519
friend std::ostream & operator<<(std::ostream &str, const Fetcher::Impl &obj)
relates: Fetcher::Impl Stream output
Definition: Fetcher.cc:895
Impl * clone() const
clone for RWCOW_pointer
Definition: Fetcher.cc:286
RepoManager::RefreshServiceOptions _options
Definition: serviceswf.cc:698
The user is not asked anything, and the error exception is just propagated.