libzypp  11.13.5
Downloader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
10 #include <fstream>
11 #include "zypp/base/String.h"
12 #include "zypp/base/Logger.h"
13 #include "zypp/base/Function.h"
14 
15 #include "zypp/Date.h"
16 
19 #include "Downloader.h"
22 #include "zypp/parser/xml/Reader.h"
23 #include "zypp/KeyContext.h"
24 
25 using namespace std;
26 using namespace zypp::xml;
27 using namespace zypp::parser::yum;
28 
29 namespace zypp
30 {
31 namespace repo
32 {
33 namespace yum
34 {
35 
36 Downloader::Downloader( const RepoInfo &repoinfo , const Pathname &delta_dir)
37  : repo::Downloader(repoinfo), _delta_dir(delta_dir), _media_ptr(0L)
38 {
39 }
40 
41 
43 {
44  Pathname repomd = media.provideFile( repoInfo().path() + "/repodata/repomd.xml");
45  return RepoStatus(repomd);
46 }
47 
48 static OnMediaLocation
50  const Pathname & prefix)
51 {
52  if (prefix.empty() || prefix == "/")
53  return loc;
54 
55  OnMediaLocation loc_with_path(loc);
56  loc_with_path.changeFilename(prefix / loc.filename());
57  return loc_with_path;
58 }
59 
60 // search old repository file file to run the delta algorithm on
61 static Pathname search_deltafile( const Pathname &dir, const Pathname &file )
62 {
63  Pathname deltafile;
64  if (!PathInfo(dir).isDir())
65  return deltafile;
66  string base = file.basename();
67  size_t hypoff = base.find("-");
68  if (hypoff != string::npos)
69  base.replace(0, hypoff + 1, "");
70  size_t basesize = base.size();
71  std::list<Pathname> retlist;
72  if (!filesystem::readdir(retlist, dir, false))
73  {
74  for_( it, retlist.begin(), retlist.end() )
75  {
76  string fn = it->asString();
77  if (fn.size() >= basesize && fn.substr(fn.size() - basesize, basesize) == base)
78  deltafile = *it;
79  }
80  }
81  return deltafile;
82 }
83 
85  const string &id )
86 {
87  OnMediaLocation loc_with_path(loc_with_path_prefix(loc, repoInfo().path()));
88  MIL << id << " : " << loc_with_path << endl;
89  this->enqueueDigested(loc_with_path, FileChecker(), search_deltafile(_delta_dir + "repodata", loc.filename()));
90  return true;
91 }
92 
94  const ResourceType &dtype )
95 {
96  OnMediaLocation loc_with_path(loc_with_path_prefix(loc, repoInfo().path()));
97  MIL << dtype << " : " << loc_with_path << endl;
98 
100  // skip other
101  if ( dtype == ResourceType::OTHER )
102  {
103  MIL << "Skipping other.xml" << endl;
104  return true;
105  }
106  // skip filelists
107  if ( dtype == ResourceType::FILELISTS )
108  {
109  MIL << "Skipping filelists.xml.gz" << endl;
110  return true;
111  }
112 
113  this->enqueueDigested(loc_with_path, FileChecker(), search_deltafile(_delta_dir + "repodata", loc.filename()));
114 
115  // We got a patches file we need to read, to add patches listed
116  // there, so we transfer what we have in the queue, and
117  // queue the patches in the patches callback
118  if ( dtype == ResourceType::PATCHES )
119  {
120  this->start( _dest_dir, *_media_ptr );
121  // now the patches.xml file must exists
122  PatchesFileReader( _dest_dir + repoInfo().path() + loc.filename(),
123  bind( &Downloader::patches_Callback, this, _1, _2));
124  }
125 
126  return true;
127 }
128 
130  const Pathname &dest_dir,
131  const ProgressData::ReceiverFnc & progressrcv )
132 {
133  Pathname repomdpath = repoInfo().path() + "/repodata/repomd.xml";
134  Pathname keypath = repoInfo().path() + "/repodata/repomd.xml.key";
135  Pathname sigpath = repoInfo().path() + "/repodata/repomd.xml.asc";
136 
137  _media_ptr = (&media);
138 
139  ProgressData progress;
140  progress.sendTo(progressrcv);
141  progress.toMin();
142 
143  //downloadMediaInfo( dest_dir, _media );
144 
145  _dest_dir = dest_dir;
146 
147 #warning Do we need SignatureFileChecker(string descr)?
148  SignatureFileChecker sigchecker/*(repoInfo().name())*/;
149 
150  this->enqueue( OnMediaLocation(sigpath,1).setOptional(true) );
151  this->start( dest_dir, *_media_ptr);
152  // only add the signature if it exists
153  if ( PathInfo(dest_dir / sigpath).isExist() )
154  sigchecker = SignatureFileChecker(dest_dir / sigpath);
155  this->reset();
156 
157  this->enqueue( OnMediaLocation(keypath,1).setOptional(true) );
158  this->start( dest_dir, *_media_ptr);
159 
160  KeyContext context;
161  context.setRepoInfo(repoInfo());
162  // only add the key if it exists
163  if ( PathInfo(dest_dir / keypath).isExist() )
164  sigchecker.addPublicKey(dest_dir + keypath, context);
165  // set the checker context even if the key is not known (unsigned repo, key
166  // file missing; bnc #495977)
167  else
168  sigchecker.setKeyContext(context);
169 
170  this->reset();
171 
172  if ( ! progress.tick() )
173  ZYPP_THROW(AbortRequestException());
174 
175  if ( ! repoInfo().gpgCheck() )
176  WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
177 
178  this->enqueue( OnMediaLocation(repomdpath,1),
179  repoInfo().gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) );
180  this->start( dest_dir, *_media_ptr);
181 
182  if ( ! progress.tick() )
183  ZYPP_THROW(AbortRequestException());
184 
185  this->reset();
186 
187  Reader reader( dest_dir + repoInfo().path() + "/repodata/repomd.xml" );
188  RepomdFileReader( dest_dir + repoInfo().path() + "/repodata/repomd.xml", bind( &Downloader::repomd_Callback, this, _1, _2));
189 
190  // ready, go!
191  this->start( dest_dir, *_media_ptr);
192  progress.toMax();
193 }
194 
195 }// ns yum
196 }// ns source
197 } // ns zypp
198 
199 
200