00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <fstream>
00014 #include <list>
00015 #include <map>
00016
00017 #include "zypp/base/Easy.h"
00018 #include "zypp/base/LogControl.h"
00019 #include "zypp/base/LogTools.h"
00020 #include "zypp/base/PtrTypes.h"
00021 #include "zypp/base/DefaultIntegral.h"
00022 #include "zypp/base/String.h"
00023 #include "zypp/Fetcher.h"
00024 #include "zypp/ZYppFactory.h"
00025 #include "zypp/CheckSum.h"
00026 #include "zypp/base/UserRequestException.h"
00027 #include "zypp/parser/susetags/ContentFileReader.h"
00028 #include "zypp/parser/susetags/RepoIndex.h"
00029
00030 using namespace std;
00031
00032 #undef ZYPP_BASE_LOGGER_LOGGROUP
00033 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp:fetcher"
00034
00036 namespace zypp
00037 {
00038
00044 struct FetcherIndex
00045 {
00046 FetcherIndex( const OnMediaLocation &loc )
00047 : location(loc)
00048 {}
00050 OnMediaLocation location;
00052 DefaultIntegral<bool,false> read;
00053 };
00054
00055 typedef shared_ptr<FetcherIndex> FetcherIndex_Ptr;
00056
00058 struct SameFetcherIndex
00059 {
00060 bool operator()( const FetcherIndex_Ptr & lhs, const FetcherIndex_Ptr & rhs )
00061 {
00062 if ( lhs == rhs )
00063 return false;
00064 if ( ! lhs )
00065 return true;
00066 if ( ! rhs )
00067 return false;
00068
00069 if ( lhs->location.medianr() == rhs->location.medianr() )
00070 return lhs->location.filename() < rhs->location.filename();
00071
00072 return lhs->location.medianr() < rhs->location.medianr();
00073 }
00074 };
00075
00080 struct FetcherJob
00081 {
00082 enum Flag
00083 {
00084 None = 0x0000,
00085 Directory = 0x0001,
00086 Recursive = 0x0002,
00087 RecursiveDirectory = Directory | Recursive,
00088
00089
00090 AlwaysVerifyChecksum = 0x0004,
00091 };
00092 ZYPP_DECLARE_FLAGS(Flags, Flag);
00093
00094
00095 FetcherJob( const OnMediaLocation &loc )
00096 : location(loc)
00097 , flags(None)
00098 {
00099
00100 }
00101
00102 ~FetcherJob()
00103 {
00104
00105 }
00106
00107 OnMediaLocation location;
00108
00109 list<FileChecker> checkers;
00110 Flags flags;
00111 };
00112
00113 ZYPP_DECLARE_OPERATORS_FOR_FLAGS(FetcherJob::Flags);
00114 typedef shared_ptr<FetcherJob> FetcherJob_Ptr;
00115
00116 std::ostream & operator<<( std::ostream & str, const FetcherJob_Ptr & obj )
00117 {
00118 return str << obj->location;
00119 }
00120
00122
00123
00124
00126 class Fetcher::Impl
00127 {
00128 friend std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj );
00129
00130 public:
00131 Impl();
00132
00133 ~Impl() {}
00134
00135 void setOptions( Fetcher::Options options );
00136 Fetcher::Options options() const;
00137
00138 void addIndex( const OnMediaLocation &resource );
00139
00140 void enqueueDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
00141 void enqueueDigestedDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
00142
00143 void enqueue( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() );
00144 void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() );
00145 void addCachePath( const Pathname &cache_dir );
00146 void reset();
00147 void start( const Pathname &dest_dir,
00148 MediaSetAccess &media,
00149 const ProgressData::ReceiverFnc & progress_receiver );
00150
00152 static shared_ptr<Impl> nullimpl()
00153 {
00154 static shared_ptr<Impl> _nullimpl( new Impl );
00155 return _nullimpl;
00156 }
00157 private:
00161 void downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir);
00162
00166 void downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir);
00167
00175 void readIndex( const Pathname &index, const Pathname &basedir );
00176
00178 void readSha1sumsIndex( const Pathname &index, const Pathname &basedir );
00179
00181 void readContentFileIndex( const Pathname &index, const Pathname &basedir );
00182
00184 void getDirectoryContent( MediaSetAccess &media, const OnMediaLocation &resource, filesystem::DirContent &content );
00185
00191 bool provideFromCache( const OnMediaLocation &resource, const Pathname &dest_dir );
00197 void validate( const OnMediaLocation &resource, const Pathname &dest_dir, const list<FileChecker> &checkers );
00198
00202 void addDirJobs( MediaSetAccess &media, const OnMediaLocation &resource,
00203 const Pathname &dest_dir, FetcherJob::Flags flags );
00204
00208 void autoaddIndexes( const filesystem::DirContent &content,
00209 MediaSetAccess &media,
00210 const OnMediaLocation &resource,
00211 const Pathname &dest_dir );
00215 void provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir );
00216
00217 private:
00218 friend Impl * rwcowClone<Impl>( const Impl * rhs );
00220 Impl * clone() const
00221 { return new Impl( *this ); }
00222
00223 list<FetcherJob_Ptr> _resources;
00224 std::set<FetcherIndex_Ptr,SameFetcherIndex> _indexes;
00225 std::set<Pathname> _caches;
00226
00227 map<string, CheckSum> _checksums;
00228
00229 map<string, filesystem::DirContent> _dircontent;
00230
00231 Fetcher::Options _options;
00232 };
00234
00235 void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
00236 {
00237 FetcherJob_Ptr job;
00238 job.reset(new FetcherJob(resource));
00239 job->flags |= FetcherJob:: AlwaysVerifyChecksum;
00240 _resources.push_back(job);
00241 }
00242
00243 Fetcher::Impl::Impl()
00244 : _options(0)
00245 {
00246 }
00247
00248 void Fetcher::Impl::setOptions( Fetcher::Options options )
00249 { _options = options; }
00250
00251 Fetcher::Options Fetcher::Impl::options() const
00252 { return _options; }
00253
00254 void Fetcher::Impl::enqueueDir( const OnMediaLocation &resource,
00255 bool recursive,
00256 const FileChecker &checker )
00257 {
00258 FetcherJob_Ptr job;
00259 job.reset(new FetcherJob(resource));
00260 if ( checker )
00261 job->checkers.push_back(checker);
00262 if ( recursive )
00263 job->flags |= FetcherJob::Recursive;
00264 job->flags |= FetcherJob::Directory;
00265
00266 _resources.push_back(job);
00267 }
00268
00269 void Fetcher::Impl::enqueueDigestedDir( const OnMediaLocation &resource,
00270 bool recursive,
00271 const FileChecker &checker )
00272 {
00273 FetcherJob_Ptr job;
00274 job.reset(new FetcherJob(resource));
00275 if ( checker )
00276 job->checkers.push_back(checker);
00277 if ( recursive )
00278 job->flags |= FetcherJob::Recursive;
00279 job->flags |= FetcherJob::Directory;
00280 job->flags |= FetcherJob::AlwaysVerifyChecksum;
00281
00282 _resources.push_back(job);
00283
00284 }
00285
00286 void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
00287 {
00288 FetcherJob_Ptr job;
00289 job.reset(new FetcherJob(resource));
00290 if ( checker )
00291 job->checkers.push_back(checker);
00292 _resources.push_back(job);
00293 }
00294
00295 void Fetcher::Impl::addIndex( const OnMediaLocation &resource )
00296 {
00297 MIL << "adding index " << resource << endl;
00298 _indexes.insert(FetcherIndex_Ptr(new FetcherIndex(resource)));
00299 }
00300
00301
00302 void Fetcher::Impl::reset()
00303 {
00304 _resources.clear();
00305 _indexes.clear();
00306 _checksums.clear();
00307 _dircontent.clear();
00308 }
00309
00310 void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
00311 {
00312 PathInfo info(cache_dir);
00313 if ( info.isExist() )
00314 {
00315 if ( info.isDir() )
00316 {
00317 DBG << "Adding fetcher cache: '" << cache_dir << "'." << endl;
00318 _caches.insert(cache_dir);
00319 }
00320 else
00321 {
00322
00323 ERR << "Not adding cache: '" << cache_dir << "'. Not a directory." << endl;
00324 }
00325 }
00326 else
00327 {
00328 ERR << "Not adding cache '" << cache_dir << "'. Path does not exists." << endl;
00329 }
00330
00331 }
00332
00333
00334
00335
00336 bool Fetcher::Impl::provideFromCache( const OnMediaLocation &resource, const Pathname &dest_dir )
00337 {
00338 Pathname dest_full_path = dest_dir + resource.filename();
00339
00340
00341 if ( PathInfo(dest_full_path).isExist() )
00342 {
00343 if ( is_checksum( dest_full_path, resource.checksum() )
00344 && (! resource.checksum().empty() ) )
00345 return true;
00346 }
00347
00348 MIL << "start fetcher with " << _caches.size() << " cache directories." << endl;
00349 for_ ( it_cache, _caches.begin(), _caches.end() )
00350 {
00351
00352 Pathname cached_file = *it_cache + resource.filename();
00353 if ( PathInfo( cached_file ).isExist() )
00354 {
00355 DBG << "File '" << cached_file << "' exist, testing checksum " << resource.checksum() << endl;
00356
00357 if ( is_checksum( cached_file, resource.checksum() ) && (! resource.checksum().empty() ) )
00358 {
00359
00360 MIL << "file " << resource.filename() << " found in previous cache. Using cached copy." << endl;
00361
00362
00363
00364 if( dest_full_path != cached_file )
00365 {
00366 if ( assert_dir( dest_full_path.dirname() ) != 0 )
00367 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
00368
00369 if ( filesystem::hardlinkCopy(cached_file, dest_full_path ) != 0 )
00370 {
00371 ERR << "Can't hardlink/copy " << cached_file + " to " + dest_dir << endl;
00372 continue;
00373 }
00374 }
00375
00376 return true;
00377 }
00378 }
00379 }
00380 return false;
00381 }
00382
00383 void Fetcher::Impl::validate( const OnMediaLocation &resource, const Pathname &dest_dir, const list<FileChecker> &checkers )
00384 {
00385
00386 Pathname localfile = dest_dir + resource.filename();
00387
00388 try
00389 {
00390 MIL << "Checking job [" << localfile << "] (" << checkers.size() << " checkers )" << endl;
00391
00392 for ( list<FileChecker>::const_iterator it = checkers.begin();
00393 it != checkers.end();
00394 ++it )
00395 {
00396 if (*it)
00397 {
00398 (*it)(localfile);
00399 }
00400 else
00401 {
00402 ERR << "Invalid checker for '" << localfile << "'" << endl;
00403 }
00404 }
00405
00406 }
00407 catch ( const FileCheckException &e )
00408 {
00409 ZYPP_RETHROW(e);
00410 }
00411 catch ( const Exception &e )
00412 {
00413 ZYPP_RETHROW(e);
00414 }
00415 catch (...)
00416 {
00417 ZYPP_THROW(Exception("Unknown error while validating " + resource.filename().asString()));
00418 }
00419 }
00420
00421 void Fetcher::Impl::autoaddIndexes( const filesystem::DirContent &content,
00422 MediaSetAccess &media,
00423 const OnMediaLocation &resource,
00424 const Pathname &dest_dir )
00425 {
00426 if ( _options & AutoAddSha1sumsIndexes )
00427 {
00428
00429 filesystem::DirEntry shafile;
00430 shafile.name = "SHA1SUMS"; shafile.type = filesystem::FT_FILE;
00431 if ( find( content.begin(), content.end(), shafile ) != content.end() )
00432 {
00433
00434 OnMediaLocation indexloc(resource);
00435 indexloc.changeFilename(resource.filename() + "SHA1SUMS");
00436 addIndex(indexloc);
00437
00438 downloadAndReadIndexList(media, dest_dir);
00439 }
00440 }
00441 if ( _options & AutoAddContentFileIndexes )
00442 {
00443
00444 filesystem::DirEntry contentfile;
00445 contentfile.name = "content"; contentfile.type = filesystem::FT_FILE;
00446 if ( find( content.begin(), content.end(), contentfile ) != content.end() )
00447 {
00448
00449 OnMediaLocation indexloc(resource);
00450 indexloc.changeFilename(resource.filename() + "content");
00451 addIndex(indexloc);
00452
00453 downloadAndReadIndexList(media, dest_dir);
00454 }
00455 }
00456 }
00457
00458 void Fetcher::Impl::getDirectoryContent( MediaSetAccess &media,
00459 const OnMediaLocation &resource,
00460 filesystem::DirContent &content )
00461 {
00462 if ( _dircontent.find(resource.filename().asString())
00463 != _dircontent.end() )
00464 {
00465 filesystem::DirContent filled(_dircontent[resource.filename().asString()]);
00466
00467 std::copy(filled.begin(), filled.end(), std::back_inserter(content));
00468 }
00469 else
00470 {
00471 filesystem::DirContent tofill;
00472 media.dirInfo( tofill,
00473 resource.filename(),
00474 false ,
00475 resource.medianr());
00476 std::copy(tofill.begin(), tofill.end(), std::back_inserter(content));
00477 _dircontent[resource.filename().asString()] = tofill;
00478 }
00479 }
00480
00481 void Fetcher::Impl::addDirJobs( MediaSetAccess &media,
00482 const OnMediaLocation &resource,
00483 const Pathname &dest_dir, FetcherJob::Flags flags )
00484 {
00485
00486
00487 MIL << "Adding directory " << resource.filename() << endl;
00488 filesystem::DirContent content;
00489 getDirectoryContent(media, resource, content);
00490
00491
00492
00493 autoaddIndexes(content, media, resource, dest_dir);
00494
00495 for ( filesystem::DirContent::const_iterator it = content.begin();
00496 it != content.end();
00497 ++it )
00498 {
00499
00500 if ( str::hasPrefix(it->name, "SHA1SUMS") )
00501 continue;
00502
00503 Pathname filename = resource.filename() + it->name;
00504
00505 switch ( it->type )
00506 {
00507 case filesystem::FT_NOT_AVAIL:
00508 case filesystem::FT_FILE:
00509 {
00510 CheckSum chksm(resource.checksum());
00511 if ( _checksums.find(filename.asString()) != _checksums.end() )
00512 {
00513
00514 chksm = _checksums[filename.asString()];
00515
00516 }
00517 else
00518 WAR << "Resource " << filename << " has no checksum in the index either." << endl;
00519
00520 if ( flags & FetcherJob::AlwaysVerifyChecksum )
00521 enqueueDigested(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
00522 else
00523 enqueue(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
00524 break;
00525 }
00526 case filesystem::FT_DIR:
00527 if ( flags & FetcherJob::Recursive )
00528 addDirJobs(media, filename, dest_dir, flags);
00529 break;
00530 default:
00531
00532 break;
00533 }
00534 }
00535 }
00536
00537 void Fetcher::Impl::provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir )
00538 {
00539 bool got_from_cache = false;
00540
00541
00542 got_from_cache = provideFromCache(resource, dest_dir);
00543
00544 if ( ! got_from_cache )
00545 {
00546 MIL << "Not found in cache, downloading" << endl;
00547
00548
00549 try
00550 {
00551 Pathname tmp_file = media.provideFile(resource, resource.optional() ? MediaSetAccess::PROVIDE_NON_INTERACTIVE : MediaSetAccess::PROVIDE_DEFAULT );
00552
00553 Pathname dest_full_path = dest_dir + resource.filename();
00554
00555 if ( assert_dir( dest_full_path.dirname() ) != 0 )
00556 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
00557 if ( filesystem::hardlinkCopy( tmp_file, dest_full_path ) != 0 )
00558 {
00559 if ( ! PathInfo(tmp_file).isExist() )
00560 ERR << tmp_file << " does not exist" << endl;
00561 if ( ! PathInfo(dest_full_path.dirname()).isExist() )
00562 ERR << dest_full_path.dirname() << " does not exist" << endl;
00563
00564 media.releaseFile(resource);
00565 ZYPP_THROW( Exception("Can't hardlink/copy " + tmp_file.asString() + " to " + dest_dir.asString()));
00566 }
00567
00568 media.releaseFile(resource);
00569 }
00570 catch (Exception & excpt_r)
00571 {
00572 ZYPP_CAUGHT(excpt_r);
00573 excpt_r.remember("Can't provide " + resource.filename().asString() + " : " + excpt_r.msg());
00574
00575 if ( resource.optional() )
00576 {
00577 WAR << "optional resource " << resource << " could not be transfered" << endl;
00578 return;
00579 }
00580 else
00581 {
00582 ZYPP_RETHROW(excpt_r);
00583 }
00584 }
00585 }
00586 else
00587 {
00588
00589
00590 return;
00591 }
00592 }
00593
00594
00595 struct ContentReaderHelper : public parser::susetags::ContentFileReader
00596 {
00597 ContentReaderHelper()
00598 {
00599 setRepoIndexConsumer( bind( &ContentReaderHelper::consumeIndex, this, _1 ) );
00600 }
00601
00602 void consumeIndex( const parser::susetags::RepoIndex_Ptr & data_r )
00603 { _repoindex = data_r; }
00604
00605 parser::susetags::RepoIndex_Ptr _repoindex;
00606 };
00607
00608
00609 void Fetcher::Impl::readIndex( const Pathname &index, const Pathname &basedir )
00610 {
00611 if ( index.basename() == "SHA1SUMS" )
00612 readSha1sumsIndex(index, basedir);
00613 else if ( index.basename() == "content" )
00614 readContentFileIndex(index, basedir);
00615 else
00616 WAR << index << ": index file format not known" << endl;
00617 }
00618
00619
00620 void Fetcher::Impl::readContentFileIndex( const Pathname &index, const Pathname &basedir )
00621 {
00622 ContentReaderHelper reader;
00623 reader.parse(index);
00624 MIL << index << " contains " << reader._repoindex->mediaFileChecksums.size() << " checksums." << endl;
00625 for_( it, reader._repoindex->mediaFileChecksums.begin(), reader._repoindex->mediaFileChecksums.end() )
00626 {
00627
00628 _checksums[(basedir + it->first).asString()] = it->second;
00629 }
00630 }
00631
00632
00633 void Fetcher::Impl::readSha1sumsIndex( const Pathname &index, const Pathname &basedir )
00634 {
00635 std::ifstream in( index.c_str() );
00636 string buffer;
00637 if ( ! in.fail() )
00638 {
00639 while ( getline(in, buffer) )
00640 {
00641 vector<string> words;
00642 str::split( buffer, back_inserter(words) );
00643 if ( words.size() != 2 )
00644 ZYPP_THROW(Exception("Wrong format for SHA1SUMS file"));
00645
00646 if ( ! words[1].empty() )
00647 _checksums[(basedir + words[1]).asString()] = CheckSum::sha1(words[0]);
00648 }
00649 }
00650 else
00651 ZYPP_THROW(Exception("Can't open SHA1SUMS file: " + index.asString()));
00652 }
00653
00654 void Fetcher::Impl::downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
00655 {
00656 MIL << "downloading index " << resource << endl;
00657
00658
00659 Fetcher fetcher;
00660
00661
00662 SignatureFileChecker sigchecker;
00663
00664
00665 OnMediaLocation idxloc(resource);
00666 OnMediaLocation sigloc(resource);
00667 OnMediaLocation keyloc(resource);
00668
00669
00670
00671 sigloc.setOptional(true);
00672 keyloc.setOptional(true);
00673
00674
00675 sigloc.changeFilename( sigloc.filename().extend(".asc") );
00676 keyloc.changeFilename( keyloc.filename().extend(".key") );
00677
00678
00679
00680
00681 fetcher.enqueue(sigloc);
00682 fetcher.start( dest_dir, media );
00683
00684 if ( PathInfo(dest_dir + sigloc.filename()).isExist() )
00685 sigchecker = SignatureFileChecker(dest_dir + sigloc.filename());
00686
00687 fetcher.reset();
00688
00689
00690 fetcher.enqueue(keyloc);
00691 fetcher.start( dest_dir, media );
00692 fetcher.reset();
00693
00694
00695 if ( PathInfo(dest_dir + keyloc.filename()).isExist() )
00696 getZYpp()->keyRing()->importKey(PublicKey(dest_dir + keyloc.filename()), false);
00697 else
00698 WAR << "No public key specified by user for index '" << keyloc.filename() << "'"<< endl;
00699
00700
00701 fetcher.enqueue( idxloc, FileChecker(sigchecker) );
00702 fetcher.start( dest_dir, media );
00703 fetcher.reset();
00704 }
00705
00706
00707
00708
00709 void Fetcher::Impl::downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir)
00710 {
00711
00712
00713 if ( _indexes.empty() )
00714 {
00715 MIL << "No indexes to read." << endl;
00716 return;
00717 }
00718
00719 for_( it_idx, _indexes.begin(), _indexes.end() )
00720 {
00721 if ( (*it_idx)->read )
00722 {
00723 DBG << "Already read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
00724 }
00725 else
00726 {
00727
00728 downloadIndex( media, (*it_idx)->location, dest_dir );
00729
00730 readIndex( dest_dir + (*it_idx)->location.filename(), (*it_idx)->location.filename().dirname() );
00731
00732 MIL << "Remember read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
00733 (*it_idx)->read = true;
00734 }
00735 }
00736 MIL << "done reading indexes" << endl;
00737 }
00738
00739
00740
00741 void Fetcher::Impl::start( const Pathname &dest_dir,
00742 MediaSetAccess &media,
00743 const ProgressData::ReceiverFnc & progress_receiver )
00744 {
00745 ProgressData progress(_resources.size());
00746 progress.sendTo(progress_receiver);
00747
00748 downloadAndReadIndexList(media, dest_dir);
00749
00750 for ( list<FetcherJob_Ptr>::const_iterator it_res = _resources.begin(); it_res != _resources.end(); ++it_res )
00751 {
00752
00753 if ( (*it_res)->flags & FetcherJob::Directory )
00754 {
00755 const OnMediaLocation location((*it_res)->location);
00756 addDirJobs(media, location, dest_dir, (*it_res)->flags);
00757 continue;
00758 }
00759
00760
00761
00762
00763 if ( ( _options & AutoAddSha1sumsIndexes ) ||
00764 ( _options & AutoAddContentFileIndexes ) )
00765 {
00766
00767
00768
00769 filesystem::DirContent content;
00770 getDirectoryContent(media, (*it_res)->location.filename().dirname(), content);
00771
00772
00773 MIL << "Autodiscovering signed indexes on '"
00774 << (*it_res)->location.filename().dirname() << "' for '"
00775 << (*it_res)->location.filename() << "'" << endl;
00776
00777 autoaddIndexes(content, media, (*it_res)->location.filename().dirname(), dest_dir);
00778
00779
00780 content.clear();
00781 getDirectoryContent(media, Pathname("/"), content);
00782
00783
00784 MIL << "Autodiscovering signed indexes on '"
00785 << "/" << "' for '"
00786 << (*it_res)->location.filename() << "'" << endl;
00787
00788 autoaddIndexes(content, media, Pathname("/"), dest_dir);
00789 }
00790
00791 provideToDest(media, (*it_res)->location, dest_dir);
00792
00793
00794
00795 if ( ! PathInfo(dest_dir + (*it_res)->location.filename()).isExist() )
00796 return;
00797
00798
00799
00800 if ( (*it_res)->location.checksum().empty() )
00801 {
00802 if ( _checksums.find((*it_res)->location.filename().asString())
00803 != _checksums.end() )
00804 {
00805 CheckSum chksm = _checksums[(*it_res)->location.filename().asString()];
00806 ChecksumFileChecker digest_check(chksm);
00807 (*it_res)->checkers.push_back(digest_check);
00808 }
00809 else
00810 {
00811
00812
00813 if ( (*it_res)->flags & FetcherJob::AlwaysVerifyChecksum )
00814 {
00815
00816 ChecksumFileChecker digest_check((*it_res)->location.checksum());
00817 (*it_res)->checkers.push_back(digest_check);
00818 }
00819 }
00820 }
00821 else
00822 {
00823
00824 ChecksumFileChecker digest_check((*it_res)->location.checksum());
00825 (*it_res)->checkers.push_back(digest_check);
00826 }
00827
00828
00829 validate((*it_res)->location, dest_dir, (*it_res)->checkers);
00830
00831 if ( ! progress.incr() )
00832 ZYPP_THROW(AbortRequestException());
00833 }
00834 }
00835
00837 inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
00838 {
00839 for ( list<FetcherJob_Ptr>::const_iterator it_res = obj._resources.begin(); it_res != obj._resources.end(); ++it_res )
00840 {
00841 str << *it_res;
00842 }
00843 return str;
00844 }
00845
00846 Fetcher::Fetcher()
00847 : _pimpl( new Impl() )
00848 {}
00849
00850 Fetcher::~Fetcher()
00851 {}
00852
00853 void Fetcher::setOptions( Fetcher::Options options )
00854 {
00855 _pimpl->setOptions(options);
00856 }
00857
00858 Fetcher::Options Fetcher::options() const
00859 {
00860 return _pimpl->options();
00861 }
00862
00863 void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
00864 {
00865 _pimpl->enqueueDigested(resource, checker);
00866 }
00867
00868 void Fetcher::enqueueDir( const OnMediaLocation &resource,
00869 bool recursive,
00870 const FileChecker &checker )
00871 {
00872 _pimpl->enqueueDir(resource, recursive, checker);
00873 }
00874
00875 void Fetcher::enqueueDigestedDir( const OnMediaLocation &resource,
00876 bool recursive,
00877 const FileChecker &checker )
00878 {
00879 _pimpl->enqueueDigestedDir(resource, recursive, checker);
00880 }
00881
00882
00883 void Fetcher::addIndex( const OnMediaLocation &resource )
00884 {
00885 _pimpl->addIndex(resource);
00886 }
00887
00888
00889 void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
00890 {
00891 _pimpl->enqueue(resource, checker);
00892 }
00893
00894 void Fetcher::addCachePath( const Pathname &cache_dir )
00895 {
00896 _pimpl->addCachePath(cache_dir);
00897 }
00898
00899 void Fetcher::reset()
00900 {
00901 _pimpl->reset();
00902 }
00903
00904 void Fetcher::start( const Pathname &dest_dir,
00905 MediaSetAccess &media,
00906 const ProgressData::ReceiverFnc & progress_receiver )
00907 {
00908 _pimpl->start(dest_dir, media, progress_receiver);
00909 }
00910
00911 std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
00912 {
00913 return str << *obj._pimpl;
00914 }
00915
00917 }
00919