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