libzypp  17.25.7
RepoProvideFile.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 <sstream>
15 #include <set>
16 
17 #include <zypp/base/Gettext.h>
18 #include <zypp/base/Logger.h>
19 #include <zypp/base/String.h>
22 #include <zypp/ZYppCallbacks.h>
23 #include <zypp/MediaSetAccess.h>
24 #include <zypp/ZConfig.h>
25 #include <zypp/ZYppFactory.h>
28 
31 #include <zypp/FileChecker.h>
32 #include <zypp/Fetcher.h>
33 
34 using std::endl;
35 using std::set;
36 
38 namespace zypp
39 {
41  namespace repo
42  {
43 
45  //
46  // provideFile
47  //
49 
51  namespace
52  {
53 
59  struct DownloadFileReportHack : public callback::ReceiveReport<media::DownloadProgressReport>
60  {
61  typedef callback::ReceiveReport<ReportType> BaseType;
62  typedef function<bool(int)> RedirectType;
63 
64  DownloadFileReportHack( RedirectType redirect_r )
65  : _oldRec( Distributor::instance().getReceiver() )
66  , _redirect( redirect_r )
67  { connect(); }
68  ~DownloadFileReportHack()
69  { if ( _oldRec ) Distributor::instance().setReceiver( *_oldRec ); else Distributor::instance().noReceiver(); }
70 
71  virtual void start( const Url & file, Pathname localfile )
72  {
73  if ( _oldRec )
74  _oldRec->start( file, localfile );
75  else
76  BaseType::start( file, localfile );
77  }
78 
79  virtual bool progress( int value, const Url & file, double dbps_avg = -1, double dbps_current = -1 )
80  {
81  bool ret = true;
82  if ( _oldRec )
83  ret &= _oldRec->progress( value, file, dbps_avg, dbps_current );
84  if ( _redirect )
85  ret &= _redirect( value );
86  return ret;
87  }
88 
89  virtual Action problem( const Url & file, Error error, const std::string & description )
90  {
91  if ( _oldRec )
92  return _oldRec->problem( file, error, description );
93  return BaseType::problem( file, error, description );
94  }
95  virtual void finish( const Url & file, Error error, const std::string & reason )
96  {
97  if ( _oldRec )
98  _oldRec->finish( file, error, reason );
99  else
100  BaseType::finish( file, error, reason );
101  }
102 
103  private:
104  Receiver * _oldRec;
105  RedirectType _redirect;
106  };
107 
109  } // namespace
111 
113  const OnMediaLocation & loc_r,
114  const ProvideFilePolicy & policy_r )
115  {
116  RepoMediaAccess access;
117  return access.provideFile(repo_r, loc_r, policy_r );
118  }
119 
122  {
123  public:
124  Impl( const ProvideFilePolicy & defaultPolicy_r )
125  : _defaultPolicy( defaultPolicy_r )
126  {}
127 
129  {
130  std::map<Url, shared_ptr<MediaSetAccess> >::iterator it;
131  for ( it = _medias.begin();
132  it != _medias.end();
133  ++it )
134  {
135  it->second->release();
136  }
137  }
138 
146  shared_ptr<MediaSetAccess> mediaAccessForUrl( const Url &url, RepoInfo repo )
147  {
148  std::map<Url, shared_ptr<MediaSetAccess> >::const_iterator it;
149  it = _medias.find(url);
150  shared_ptr<MediaSetAccess> media;
151  if ( it != _medias.end() )
152  {
153  media = it->second;
154  }
155  else
156  {
157  media.reset( new MediaSetAccess(url) );
158  _medias[url] = media;
159  }
160  setVerifierForRepo( repo, media );
161  return media;
162  }
163 
164  private:
165  void setVerifierForRepo( RepoInfo repo, shared_ptr<MediaSetAccess> media )
166  {
167  // Always set the MediaSetAccess label.
168  media->setLabel( repo.name() );
169 
170  // set a verifier if the repository has it
171 
172  Pathname mediafile = repo.metadataPath() + "/media.1/media";
173  if ( ! repo.metadataPath().empty() )
174  {
175  if ( PathInfo(mediafile).isExist() )
176  {
177  std::map<shared_ptr<MediaSetAccess>, RepoInfo>::const_iterator it;
178  it = _verifier.find(media);
179  if ( it != _verifier.end() )
180  {
181  if ( it->second.alias() == repo.alias() )
182  {
183  // this media is already using this repo verifier
184  return;
185  }
186  }
187 
188  std::ifstream str(mediafile.asString().c_str());
189  std::string vendor;
190  std::string mediaid;
191  std::string buffer;
192  if ( str )
193  {
194  getline(str, vendor);
195  getline(str, mediaid);
196  getline(str, buffer);
197 
198  unsigned media_nr = str::strtonum<unsigned>(buffer);
199  MIL << "Repository '" << repo.alias() << "' has " << media_nr << " medias"<< endl;
200 
201  for ( unsigned i=1; i <= media_nr; ++i )
202  {
203  media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( vendor, mediaid, i ) );
204 
205  media->setVerifier( i, verifier);
206  }
207  _verifier[media] = repo;
208  }
209  else
210  {
212  }
213  }
214  else
215  {
216  WAR << "No media verifier for repo '" << repo.alias() << "' media.1/media does not exist in '" << repo.metadataPath() << "'" << endl;
217  }
218  }
219  else
220  {
221  WAR << "'" << repo.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl;
222  }
223  }
224 
225  private:
226  std::map<shared_ptr<MediaSetAccess>, RepoInfo> _verifier;
227  std::map<Url, shared_ptr<MediaSetAccess> > _medias;
228 
229  public:
231  };
233 
234 
236  : _impl( new Impl( defaultPolicy_r ) )
237  {}
238 
240  {}
241 
243  { _impl->_defaultPolicy = policy_r; }
244 
246  { return _impl->_defaultPolicy; }
247 
249  const OnMediaLocation & loc_rx,
250  const ProvideFilePolicy & policy_r )
251  {
252  const OnMediaLocation locWithPath( OnMediaLocation(loc_rx).prependPath( repo_r.path() ) );
253 
254  MIL << locWithPath << endl;
255  // Arrange DownloadFileReportHack to recieve the source::DownloadFileReport
256  // and redirect download progress triggers to call the ProvideFilePolicy
257  // callback.
258  DownloadFileReportHack dumb( bind( mem_fun_ref( &ProvideFilePolicy::progress ), ref( policy_r ), _1 ) );
259 
260  RepoException repo_excpt(repo_r,
261  str::form(_("Can't provide file '%s' from repository '%s'"),
262  locWithPath.filename().c_str(),
263  repo_r.alias().c_str() ) );
264 
265  if ( repo_r.baseUrlsEmpty() )
266  {
267  repo_excpt.remember(RepoException(_("No url in repository.")));
268  ZYPP_THROW(repo_excpt);
269  }
270 
271  Fetcher fetcher;
272  fetcher.addCachePath( repo_r.packagesPath() );
273  MIL << "Added cache path " << repo_r.packagesPath() << endl;
274 
275  // Test whether download destination is writable, if not
276  // switch into the tmpspace (e.g. bnc#755239, download and
277  // install srpms as user).
278  Pathname destinationDir( repo_r.packagesPath() );
279 
280  PathInfo pi( destinationDir );
281  if ( ! pi.isExist() )
282  {
283  // try to create it...
284  assert_dir( destinationDir );
285  pi();
286  }
287  if ( geteuid() != 0 && ! pi.userMayW() )
288  {
289  WAR << "Destination dir '" << destinationDir << "' is not user writable, using tmp space." << endl;
290  destinationDir = getZYpp()->tmpPath() / destinationDir;
291  assert_dir( destinationDir );
292  fetcher.addCachePath( destinationDir );
293  MIL << "Added cache path " << destinationDir << endl;
294  }
295 
296  // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1)
298 
299  for ( RepoInfo::urls_const_iterator it = repo_r.baseUrlsBegin();
300  it != repo_r.baseUrlsEnd();
301  /* incremented in the loop */ )
302  {
303  Url url( *it );
304  ++it;
305  try
306  {
307  MIL << "Providing file of repo '" << repo_r.alias() << "' from " << url << endl;
308  shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl( url, repo_r );
309 
310  fetcher.enqueue( locWithPath, policy_r.fileChecker() );
311  fetcher.start( destinationDir, *access );
312 
313  // reached if no exception has been thrown, so this is the correct file
314  ManagedFile ret( destinationDir + locWithPath.filename() );
315  if ( !repo_r.keepPackages() )
316  {
318  }
319 
320  MIL << "provideFile at " << ret << endl;
321  return ret;
322  }
323  catch ( const UserRequestException & excpt )
324  {
325  ZYPP_RETHROW( excpt );
326  }
327  catch ( const FileCheckException & excpt )
328  {
329  ZYPP_RETHROW( excpt );
330  }
331  catch ( const Exception &e )
332  {
333  ZYPP_CAUGHT( e );
334 
335  repo_excpt.remember(e);
336 
337  WAR << "Trying next url" << endl;
338  continue;
339  }
340  } // iteration over urls
341 
342  ZYPP_THROW(repo_excpt);
343  return ManagedFile(); // not reached
344  }
345 
347  } // namespace repo
350 } // namespace zypp
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:400
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Interface to gettext.
#define _(MSG)
Definition: Gettext.h:37
#define MIL
Definition: Logger.h:79
#define WAR
Definition: Logger.h:80
Url url
Definition: MediaCurl.cc:66
MediaVerifierRef verifier
RedirectType _redirect
Receiver * _oldRec
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:93
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Definition: AutoDispose.h:158
Base class for Exception.
Definition: Exception.h:146
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:105
This class allows to retrieve a group of files in a confortable way, providing some smartness that do...
Definition: Fetcher.h:106
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:872
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:857
void addCachePath(const Pathname &cache_dir)
adds a directory to the list of directories where to look for cached files
Definition: Fetcher.cc:862
Media access layer responsible for handling files distributed on a set of media with media change and...
Describes a resource file located on a medium.
const Pathname & filename() const
The path to the resource on the medium.
Policy for provideFile and RepoMediaAccess.
bool progress(int value) const
Evaluate callback.
ProvideFilePolicy & fileChecker(FileChecker fileChecker_r)
Add a FileCecker passed down to the Fetcher.
What is known about a repository.
Definition: RepoInfo.h:72
Pathname metadataPath() const
Path where this repo metadata was read from.
Definition: RepoInfo.cc:680
bool baseUrlsEmpty() const
whether repository urls are available
Definition: RepoInfo.cc:743
urls_size_type baseUrlsSize() const
number of repository urls
Definition: RepoInfo.cc:740
bool keepPackages() const
Whether packages downloaded from this repository will be kept in local cache.
Definition: RepoInfo.cc:677
urls_const_iterator baseUrlsEnd() const
iterator that points at end of repository urls
Definition: RepoInfo.cc:737
Pathname path() const
Repository path.
Definition: RepoInfo.cc:722
urls_const_iterator baseUrlsBegin() const
iterator that points at begin of repository urls
Definition: RepoInfo.cc:734
Pathname packagesPath() const
Path where this repo packages are cached.
Definition: RepoInfo.cc:683
transform_iterator< repo::RepoVariablesUrlReplacer, url_set::const_iterator > urls_const_iterator
Definition: RepoInfo.h:105
Url manipulation class.
Definition: Url.h:92
Base for exceptions caused by explicit user request.
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
const std::string & asString() const
String representation.
Definition: Pathname.h:91
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
const char * c_str() const
String representation.
Definition: Pathname.h:110
Exception for repository handling.
Definition: RepoException.h:38
std::string name() const
Repository name.
std::string alias() const
unique identifier for this source.
Impl(const ProvideFilePolicy &defaultPolicy_r)
std::map< shared_ptr< MediaSetAccess >, RepoInfo > _verifier
shared_ptr< MediaSetAccess > mediaAccessForUrl(const Url &url, RepoInfo repo)
Provide a MediaSetAccess for url with label and verifyer adjusted.
std::map< Url, shared_ptr< MediaSetAccess > > _medias
void setVerifierForRepo(RepoInfo repo, shared_ptr< MediaSetAccess > media)
Provides files from different repos.
void setDefaultPolicy(const ProvideFilePolicy &policy_r)
Set a new default ProvideFilePolicy.
RW_pointer< Impl > _impl
const ProvideFilePolicy & defaultPolicy() const
Get the current default ProvideFilePolicy.
ManagedFile provideFile(RepoInfo repo_r, const OnMediaLocation &loc_r, const ProvideFilePolicy &policy_r)
Provide a file from a Repository.
RepoMediaAccess(const ProvideFilePolicy &defaultPolicy_r=ProvideFilePolicy())
Ctor taking the default ProvideFilePolicy.
thrown when it was impossible to use the raw metadata for this repo.
Implementation of the traditional SUSE media verifier.
String related utilities and Regular expression matching.
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:662
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
@ Error
Definition: IOTools.h:58
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
ManagedFile provideFile(RepoInfo repo_r, const OnMediaLocation &loc_r, const ProvideFilePolicy &policy_r)
Provide a file from a Repository.
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
Wrapper for const correct access via Smart pointer types.
Definition: PtrTypes.h:286
Temporarily disable MediaChangeReport Sometimes helpful to suppress interactive messages connected to...