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
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 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
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.
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: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 char * c_str() const
String representation.
Definition: Pathname.h:110
const std::string & asString() const
String representation.
Definition: Pathname.h:91
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 verifyer 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.
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...