libzypp 17.31.0
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 <zypp-core/base/UserRequestException>
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
34using std::endl;
35using std::set;
36
38namespace 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 SUSEMediaVerifier lverifier { mediafile };
189 if ( lverifier ) {
190 DBG << "Verifier for repo '" << repo.alias() << "':" << lverifier << endl;
191 for ( media::MediaNr i = 1; i <= lverifier.totalMedia(); ++i ) {
193 media->setVerifier( i, verifier);
194 }
195 _verifier[media] = repo;
196 }
197 else {
198 WAR << "Invalid verifier for repo '" << repo.alias() << "' in '" << repo.metadataPath() << "': " << lverifier << endl;
199 }
200 }
201 else
202 {
203 DBG << "No media verifier for repo '" << repo.alias() << "' media.1/media does not exist in '" << repo.metadataPath() << "'" << endl;
204 }
205 }
206 else
207 {
208 WAR << "'" << repo.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl;
209 }
210 }
211
212 private:
213 std::map<shared_ptr<MediaSetAccess>, RepoInfo> _verifier;
214 std::map<Url, shared_ptr<MediaSetAccess> > _medias;
215
216 public:
218 };
220
221
223 : _impl( new Impl( defaultPolicy_r ) )
224 {}
225
227 {}
228
230 { _impl->_defaultPolicy = policy_r; }
231
233 { return _impl->_defaultPolicy; }
234
236 const OnMediaLocation & loc_rx,
237 const ProvideFilePolicy & policy_r )
238 {
239 const OnMediaLocation locWithPath( OnMediaLocation(loc_rx).prependPath( repo_r.path() ) );
240
241 MIL << locWithPath << endl;
242 // Arrange DownloadFileReportHack to recieve the source::DownloadFileReport
243 // and redirect download progress triggers to call the ProvideFilePolicy
244 // callback.
245 DownloadFileReportHack dumb( std::bind( std::mem_fn(&ProvideFilePolicy::progress), std::ref(policy_r), _1 ) );
246
247 RepoException repo_excpt(repo_r,
248 str::form(_("Can't provide file '%s' from repository '%s'"),
249 locWithPath.filename().c_str(),
250 repo_r.alias().c_str() ) );
251
252 if ( repo_r.baseUrlsEmpty() )
253 {
254 repo_excpt.remember(RepoException(_("No url in repository.")));
255 ZYPP_THROW(repo_excpt);
256 }
257
258 Fetcher fetcher;
259 fetcher.addCachePath( repo_r.packagesPath() );
260 MIL << "Added cache path " << repo_r.packagesPath() << endl;
261
262 // Test whether download destination is writable, if not
263 // switch into the tmpspace (e.g. bnc#755239, download and
264 // install srpms as user).
265 Pathname destinationDir( repo_r.packagesPath() );
266
267 PathInfo pi( destinationDir );
268 if ( ! pi.isExist() )
269 {
270 // try to create it...
271 assert_dir( destinationDir );
272 pi();
273 }
274 if ( geteuid() != 0 && ! pi.userMayW() )
275 {
276 WAR << "Destination dir '" << destinationDir << "' is not user writable, using tmp space." << endl;
277 destinationDir = getZYpp()->tmpPath() / destinationDir;
278 assert_dir( destinationDir );
279 fetcher.addCachePath( destinationDir );
280 MIL << "Added cache path " << destinationDir << endl;
281 }
282
283 // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1)
285
287 it != repo_r.baseUrlsEnd();
288 /* incremented in the loop */ )
289 {
290 Url url( *it );
291 ++it;
292 try
293 {
294 MIL << "Providing file of repo '" << repo_r.alias() << "' from " << url << endl;
295 shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl( url, repo_r );
296
297 fetcher.enqueue( locWithPath, policy_r.fileChecker() );
298 fetcher.start( destinationDir, *access );
299
300 // reached if no exception has been thrown, so this is the correct file
301 ManagedFile ret( destinationDir + locWithPath.filename() );
302 if ( !repo_r.keepPackages() )
303 {
305 }
306
307 MIL << "provideFile at " << ret << endl;
308 return ret;
309 }
310 catch ( const UserRequestException & excpt )
311 {
312 ZYPP_RETHROW( excpt );
313 }
314 catch ( const FileCheckException & excpt )
315 {
316 ZYPP_RETHROW( excpt );
317 }
318 catch ( const Exception &e )
319 {
320 ZYPP_CAUGHT( e );
321
322 repo_excpt.remember(e);
323
324 WAR << "Trying next url" << endl;
325 continue;
326 }
327 } // iteration over urls
328
329 ZYPP_THROW(repo_excpt);
330 return ManagedFile(); // not reached
331 }
332
334 } // namespace repo
337} // namespace zypp
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:94
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Definition: AutoDispose.h:176
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, 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:908
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:887
void addCachePath(const Pathname &cache_dir)
adds a directory to the list of directories where to look for cached files
Definition: Fetcher.cc:893
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.
ProvideFilePolicy & fileChecker(FileChecker fileChecker_r)
Add a FileCecker passed down to the Fetcher.
bool progress(int value) const
Evaluate callback.
What is known about a repository.
Definition: RepoInfo.h:72
Pathname metadataPath() const
Path where this repo metadata was read from.
Definition: RepoInfo.cc:679
bool baseUrlsEmpty() const
whether repository urls are available
Definition: RepoInfo.cc:742
urls_size_type baseUrlsSize() const
number of repository urls
Definition: RepoInfo.cc:739
bool keepPackages() const
Whether packages downloaded from this repository will be kept in local cache.
Definition: RepoInfo.cc:676
urls_const_iterator baseUrlsEnd() const
iterator that points at end of repository urls
Definition: RepoInfo.cc:736
Pathname path() const
Repository path.
Definition: RepoInfo.cc:721
urls_const_iterator baseUrlsBegin() const
iterator that points at begin of repository urls
Definition: RepoInfo.cc:733
Pathname packagesPath() const
Path where this repo packages are cached.
Definition: RepoInfo.cc:682
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 char * c_str() const
String representation.
Definition: Pathname.h:110
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
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
std::map< Url, shared_ptr< MediaSetAccess > > _medias
shared_ptr< MediaSetAccess > mediaAccessForUrl(const Url &url, RepoInfo repo)
Provide a MediaSetAccess for url with label and verifier adjusted.
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.
Implementation of the traditional SUSE media verifier.
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:700
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:319
@ Error
Definition: IOTools.h:73
unsigned int MediaNr
Definition: MediaManager.h:30
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...
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:440
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:436
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:428
#define _(MSG)
Definition: Gettext.h:37
#define DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96
#define WAR
Definition: Logger.h:97