libzypp  13.10.6
Downloader.cc
Go to the documentation of this file.
1 
2 #include <iostream>
3 #include <fstream>
4 
5 #include "zypp/base/LogTools.h"
6 #include "zypp/base/String.h"
7 #include "zypp/base/Regex.h"
8 #include "zypp/OnMediaLocation.h"
9 #include "zypp/MediaSetAccess.h"
10 #include "zypp/Fetcher.h"
11 #include "zypp/Locale.h"
12 #include "zypp/ZConfig.h"
18 #include "zypp/KeyContext.h" // for SignatureFileChecker
19 
20 using namespace std;
21 using namespace zypp::parser;
22 using namespace zypp::parser::susetags;
23 
24 namespace zypp
25 {
26 namespace repo
27 {
28 namespace susetags
29 {
30 
31 Downloader::Downloader( const RepoInfo &repoinfo, const Pathname &delta_dir )
32  : repo::Downloader(repoinfo), _delta_dir(delta_dir)
33 {
34 }
35 
37 {
38  Pathname content = media.provideFile( repoInfo().path() + "/content");
39  // the media.1 is always in the root of the media, not like the content
40  // file which is in the path() location
41  Pathname mediafile = media.provideFile( "/media.1/media" );
42 
43  return RepoStatus(content) && RepoStatus(mediafile);
44 }
45 
46 // search old repository file file to run the delta algorithm on
47 static Pathname search_deltafile( const Pathname &dir, const Pathname &file )
48 {
49  Pathname deltafile(dir + file.basename());
50  if (PathInfo(deltafile).isExist())
51  return deltafile;
52  return Pathname();
53 }
54 
56  const Pathname &dest_dir,
57  const ProgressData::ReceiverFnc & progress )
58 {
59  downloadMediaInfo( dest_dir, media );
60 
61  SignatureFileChecker sigchecker/*(repoInfo().name())*/;
62 
63  Pathname sig = repoInfo().path() + "/content.asc";
64 
65  enqueue( OnMediaLocation( sig, 1 ).setOptional(true) );
66  start( dest_dir, media );
67  // only if there is a signature in the destination directory
68  if ( PathInfo(dest_dir / sig ).isExist() )
69  sigchecker = SignatureFileChecker( dest_dir + sig/*, repoInfo().name() */);
70  reset();
71 
72  Pathname key = repoInfo().path() + "/content.key";
73 
74  enqueue( OnMediaLocation( key, 1 ).setOptional(true) );
75  start( dest_dir, media );
76 
77  KeyContext context;
78  context.setRepoInfo(repoInfo());
79  // only if there is a key in the destination directory
80  if ( PathInfo(dest_dir / key).isExist() )
81  sigchecker.addPublicKey(dest_dir + key, context);
82  // set the checker context even if the key is not known (unsigned repo, key
83  // file missing; bnc #495977)
84  else
85  sigchecker.setKeyContext(context);
86 
87  reset();
88 
89  if ( ! repoInfo().gpgCheck() )
90  {
91  WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
92  }
93  enqueue( OnMediaLocation( repoInfo().path() + "/content", 1 ),
94  repoInfo().gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) );
95  start( dest_dir, media );
96  reset();
97 
98  Pathname descr_dir;
99 
100  // Content file first to get the repoindex
101  {
102  Pathname inputfile( dest_dir + repoInfo().path() + "/content" );
103  ContentFileReader content;
104  content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
105  content.parse( inputfile );
106  }
107  if ( ! _repoindex )
108  {
109  ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No repository index in content file." ) );
110  }
111  MIL << "RepoIndex: " << _repoindex << endl;
112  if ( _repoindex->metaFileChecksums.empty() )
113  {
114  ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No metadata checksums in content file." ) );
115  }
116  if ( _repoindex->signingKeys.empty() )
117  {
118  WAR << "No signing keys defined." << endl;
119  }
120 
121  // Prepare parsing
122  descr_dir = _repoindex->descrdir; // path below reporoot
123  //_datadir = _repoIndex->datadir; // path below reporoot
124 
125  std::map<std::string,RepoIndex::FileChecksumMap::const_iterator> availablePackageTranslations;
126 
127  for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() )
128  {
129  // omit unwanted translations
130  if ( str::hasPrefix( it->first, "packages" ) )
131  {
132  static const str::regex rx_packages( "^packages((.gz)?|(.([^.]*))(.gz)?)$" );
133  str::smatch what;
134  if ( str::regex_match( it->first, what, rx_packages ) )
135  {
136  if ( what[4].empty() // packages(.gz)?
137  || what[4] == "DU"
138  || what[4] == "en" )
139  { ; /* always downloaded */ }
140  else if ( what[4] == "FL" )
141  { continue; /* never downloaded */ }
142  else
143  {
144  // remember and decide later
145  availablePackageTranslations[what[4]] = it;
146  continue;
147  }
148  }
149  else
150  continue; // discard
151  }
152  else if ( it->first == "patterns.pat"
153  || it->first == "patterns.pat.gz" )
154  {
155  // take all patterns in one go
156  }
157  else if ( str::endsWith( it->first, ".pat" )
158  || str::endsWith( it->first, ".pat.gz" ) )
159  {
160 
161  // *** see also zypp/parser/susetags/RepoParser.cc ***
162 
163  // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716
164  // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
165  // split at dots, take .pat or .pat.gz into account
166 
167  std::vector<std::string> patparts;
168  unsigned archpos = 2;
169  // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
170  unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
171  if ( patparts[count-1] == "gz" )
172  archpos++;
173 
174  if ( count > archpos )
175  {
176  try // might by an invalid architecture
177  {
178  Arch patarch( patparts[count-archpos] );
180  {
181  // discard, if not compatible
182  MIL << "Discarding pattern " << it->first << endl;
183  continue;
184  }
185  }
186  catch ( const Exception & excpt )
187  {
188  WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
189  // keep .pat file if it doesn't contain an recognizable arch
190  }
191  }
192  }
193  MIL << "adding job " << it->first << endl;
194  OnMediaLocation location( repoInfo().path() + descr_dir + it->first, 1 );
195  location.setChecksum( it->second );
196  enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, it->first));
197  }
198 
199  // check whether to download more package translations:
200  {
201  auto fnc_checkTransaltions( [&]( const Locale & locale_r ) {
202  for ( Locale toGet( locale_r ); toGet != Locale::noCode; toGet = toGet.fallback() )
203  {
204  auto it( availablePackageTranslations.find( toGet.code() ) );
205  if ( it != availablePackageTranslations.end() )
206  {
207  auto mit( it->second );
208  MIL << "adding job " << mit->first << endl;
209  OnMediaLocation location( repoInfo().path() + descr_dir + mit->first, 1 );
210  location.setChecksum( mit->second );
211  enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, mit->first));
212  break;
213  }
214  }
215  });
216  for ( const Locale & it : ZConfig::instance().repoRefreshLocales() )
217  {
218  fnc_checkTransaltions( it );
219  }
220  fnc_checkTransaltions( ZConfig::instance().textLocale() );
221  }
222 
223  for_( it, _repoindex->mediaFileChecksums.begin(), _repoindex->mediaFileChecksums.end() )
224  {
225  // Repo adopts license files listed in HASH
226  if ( it->first != "license.tar.gz" )
227  continue;
228 
229  MIL << "adding job " << it->first << endl;
230  OnMediaLocation location( repoInfo().path() + it->first, 1 );
231  location.setChecksum( it->second );
232  enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir, it->first));
233  }
234 
235  for_( it, _repoindex->signingKeys.begin(),_repoindex->signingKeys.end() )
236  {
237  MIL << "adding job " << it->first << endl;
238  OnMediaLocation location( repoInfo().path() + it->first, 1 );
239  location.setChecksum( it->second );
240  enqueueDigested(location);
241  }
242 
243  start( dest_dir, media );
244 }
245 
246 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
247 {
248  MIL << "Consuming repo index" << endl;
249  _repoindex = data_r;
250 }
251 
252 }// ns susetags
253 }// ns source
254 } // ns zypp
static const Locale noCode
No or empty code.
Definition: Locale.h:71
#define MIL
Definition: Logger.h:47
Checks for nothing Used as the default checker.
Definition: FileChecker.h:135
std::string alias() const
unique identifier for this source.
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
Definition: Arch.cc:518
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:320
Describes a path on a certain media amongs as the information required to download it...
Regular expression.
Definition: Regex.h:86
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:655
unsigned split(const C_Str &line_r, _OutputIterator result_r, const C_Str &sepchars_r=" \t")
Split line_r into words.
Definition: String.h:394
Checks for the validity of a signature.
Definition: FileChecker.h:85
Architecture.
Definition: Arch.h:36
void downloadMediaInfo(const Pathname &dest_dir, MediaSetAccess &media, const ProgressData::ReceiverFnc &progressrcv)
Downloads the media info (/media.1) to a local directory.
What is known about a repository.
Definition: RepoInfo.h:66
parser::susetags::RepoIndex_Ptr _repoindex
Definition: Downloader.h:68
void consumeIndex(const parser::susetags::RepoIndex_Ptr &data_r)
Content file parser consumer.
Definition: Downloader.cc:246
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
const RepoInfo & repoInfo() const
Definition: Downloader.h:58
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: ProgressData.h:144
void addPublicKey(const PublicKey &publickey, const KeyContext &keycontext=KeyContext())
add a public key to the list of known keys
Definition: FileChecker.cc:114
void enqueueDigested(const OnMediaLocation &resource, const FileChecker &checker=FileChecker(), const Pathname &deltafile=Pathname())
Enqueue a object for transferal, they will not be transfered until start() is called.
Definition: Fetcher.cc:871
Downloader for SUSETags (YaST2) repositories Encapsulates all the knowledge of which files have to be...
Definition: Downloader.h:34
Locale fallback() const
Return a fallback locale for this locale, when giving up, returns empty Locale()
Definition: Locale.cc:223
LocaleSet repoRefreshLocales() const
List of locales for which translated package descriptions should be downloaded.
Definition: ZConfig.cc:827
void reset()
Reset the transfer (jobs) list.
Definition: Fetcher.cc:907
#define WAR
Definition: Logger.h:48
Parse repoindex part from a content file.
OnMediaLocation & setChecksum(const CheckSum &val_r)
Set the files checksum.
void start(const Pathname &dest_dir, MediaSetAccess &media, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
start the transfer to a destination directory dest_dir You have to provde a media set access media to...
Definition: Fetcher.cc:912
void setRepoIndexConsumer(const RepoIndexConsumer &fnc_r)
Consumer to call when repo index was parsed.
void download(MediaSetAccess &media, const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Download metadata to a local directory.
Definition: Downloader.cc:55
static Pathname search_deltafile(const Pathname &dir, const Pathname &file)
Definition: Downloader.cc:47
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
Definition: String.h:861
std::string asString(const Patch::SeverityFlag &obj)
Definition: Patch.cc:149
Regular expression match result.
Definition: Regex.h:145
RepoStatus status(MediaSetAccess &media)
Status of the remote repository.
Definition: Downloader.cc:36
Base class for Exception.
Definition: Exception.h:143
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Definition: Regex.h:70
Local facts about a repository This class represents the status of a repository on the system...
Definition: RepoStatus.h:37
Arch systemArchitecture() const
The system architecture zypp uses.
Definition: ZConfig.cc:698
function< void(const Pathname &file)> FileChecker
Functor signature used to check files.
Definition: FileChecker.h:27
void setRepoInfo(const RepoInfo &repoinfo)
Definition: KeyContext.h:16
void enqueue(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Enqueue a object for transferal, they will not be transfered until start() is called.
Definition: Fetcher.cc:897
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT, const Pathname &deltafile=Pathname())
Provides a file from a media location.
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:828
virtual void parse(const InputStream &imput_r, const ProgressData::ReceiverFnc &fnc_r=ProgressData::ReceiverFnc())
Parse the stream.
Media access layer responsible for handling files distributed on a set of media with media change and...
Pathname path() const
Repository path.
Definition: RepoInfo.cc:243
void setKeyContext(const KeyContext &keycontext)
Set context for this checker.
Definition: FileChecker.cc:108