libzypp 17.37.17
MediaSetAccess.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9
10#include <iostream>
11#include <fstream>
12
13#include <zypp/base/LogTools.h>
14#include <zypp/base/Regex.h>
15#include <utility>
16#include <zypp-core/base/UserRequestException>
17#include <zypp-media/MediaException>
18#include <zypp/ZYppCallbacks.h>
19#include <zypp/MediaSetAccess.h>
20#include <zypp/PathInfo.h>
21#include <zypp/TmpPath.h>
22//#include <zypp/source/MediaSetAccessReportReceivers.h>
23
24#undef ZYPP_BASE_LOGGER_LOGGROUP
25#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::fetcher"
26
27using std::endl;
28
30namespace zypp
31{
32
34
36public:
37
38 Impl( MirroredOrigin &&origin, Pathname &&prefered_attach_point )
39 : _origin(std::move(origin))
40 , _prefAttachPoint(std::move(prefered_attach_point))
41 { }
42
43 Impl( std::string &&label_r, MirroredOrigin &&origin, Pathname &&prefered_attach_point)
44 : _origin(std::move(origin))
45 , _prefAttachPoint(std::move(prefered_attach_point))
46 , _label(std::move( label_r ))
47 { }
48
51
59
60 std::string _label;
61
62 using MediaMap = std::map<media::MediaNr, media::MediaAccessId>;
63 using VerifierMap = std::map<media::MediaNr, media::MediaVerifierRef>;
64
69};
70
72
74 : MediaSetAccess( { MirroredOrigin( std::move(url)) }, std::move(prefered_attach_point) )
75 {}
76
77 MediaSetAccess::MediaSetAccess(std::string label_r, Url url, Pathname prefered_attach_point)
78 : MediaSetAccess( std::move(label_r), { MirroredOrigin( std::move(url)) }, std::move(prefered_attach_point) )
79 {}
80
82 : _pimpl( std::make_unique<Impl>( std::move(origin), std::move(prefered_attach_point) ) )
83 { }
84
85 MediaSetAccess::MediaSetAccess(std::string label_r, MirroredOrigin origin, Pathname prefered_attach_point)
86 : _pimpl( std::make_unique<Impl>( std::move(label_r), std::move(origin), std::move(prefered_attach_point) ) )
87 { }
88
90 {
91 try
92 {
93 media::MediaManager manager;
94 for ( const auto & mm : _pimpl->_medias )
95 manager.close( mm.second );
96 }
97 catch(...) {} // don't let exception escape a dtor.
98 }
99
100
101 void MediaSetAccess::setVerifier( unsigned media_nr, const media::MediaVerifierRef& verifier )
102 {
103 if (_pimpl->_medias.find(media_nr) != _pimpl->_medias.end())
104 {
105 // the media already exists, set theverifier
106 media::MediaAccessId id = _pimpl->_medias[media_nr];
107 media::MediaManager media_mgr;
108 media_mgr.addVerifier( id, verifier );
109 // remove any saved verifier for this media
110 _pimpl->_verifiers.erase(media_nr);
111 }
112 else
113 {
114 // save the verifier in the map, and set it when
115 // the media number is first attached
116 _pimpl->_verifiers[media_nr] = verifier;
117 }
118 }
119
120 const std::string &MediaSetAccess::label() const
121 { return _pimpl->_label; }
122
123 void MediaSetAccess::setLabel(const std::string &label_r)
124 { _pimpl->_label = label_r; }
125
126 void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file )
127 {
128 releaseFile( on_media_file.filename(), on_media_file.medianr() );
129 }
130
131 void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
132 {
133 media::MediaManager media_mgr;
135 DBG << "Going to release file " << file
136 << " from media number " << media_nr << endl;
137
138 if ( ! media_mgr.isAttached(media) )
139 return; //disattached media is free
140
141 media_mgr.releaseFile (media, file);
142 }
143
145 bool dots, unsigned media_nr )
146 {
147 media::MediaManager media_mgr;
149
150 // try to attach the media
151 if ( ! media_mgr.isAttached(media) )
152 media_mgr.attach(media);
153
154 media_mgr.dirInfo(media, retlist, dirname, dots);
155 }
156
158 {
161 {
162 media::MediaManager media_mgr;
163 media_mgr.provideFile( media, file );
164 result = media_mgr.localPath( media, file.filename() );
165 }
166 };
167
169 {
172 {
173 const auto &fName = file.filename();
174 media::MediaManager media_mgr;
175 media_mgr.provideDirTree( media, fName );
176 result = media_mgr.localPath( media, fName );
177 }
178 };
179
181 {
184 {
185 const auto &fName = file.filename();
186 media::MediaManager media_mgr;
187 media_mgr.provideDir( media, fName );
188 result = media_mgr.localPath( media, fName );
189 }
190 };
191
193 {
194 bool result;
198
200 {
201 const auto &fName = file.filename();
202 media::MediaManager media_mgr;
203 result = media_mgr.doesFileExist( media, fName );
204 }
205 };
206
207 Pathname MediaSetAccess::provideFile( const OnMediaLocation &resource, ProvideFileOptions options )
208 {
210 provide( std::ref(op), resource, options );
211 return op.result;
212 }
213
214 Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
215 {
216 return provideFile( OnMediaLocation( resource ).setDeltafile( deltafile ), options );
217 }
218
219 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options )
220 {
221 return provideFile( OnMediaLocation( file, media_nr ), options );
222 }
223
224 Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr )
225 {
226 try
227 {
228 return provideFile( OnMediaLocation( file, media_nr ).setOptional( true ), PROVIDE_NON_INTERACTIVE );
229 }
230 catch ( const media::MediaFileNotFoundException & excpt_r )
231 { ZYPP_CAUGHT( excpt_r ); }
232 catch ( const media::MediaForbiddenException & excpt_r )
233 { ZYPP_CAUGHT( excpt_r ); }
234 catch ( const media::MediaNotAFileException & excpt_r )
235 { ZYPP_CAUGHT( excpt_r ); }
236 return Pathname();
237 }
238
239 ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
240 {
241 Url url(file_url);
242 Pathname path(url.getPathName());
243
244 url.setPathName ("/");
246
248
249 bool optional = options & PROVIDE_NON_INTERACTIVE;
250 Pathname file = access.provideFile( OnMediaLocation(path, 1).setOptional( optional ), options );
251
252 //prevent the file from being deleted when MediaSetAccess gets out of scope
253 if ( filesystem::hardlinkCopy(file, tmpFile) != 0 )
254 ZYPP_THROW(Exception("Can't copy file from " + file.asString() + " to " + tmpFile->asString() ));
255
256 return tmpFile;
257 }
258
260 {
261 try
262 {
264 }
265 catch ( const media::MediaFileNotFoundException & excpt_r )
266 { ZYPP_CAUGHT( excpt_r ); }
267 catch ( const media::MediaNotAFileException & excpt_r )
268 { ZYPP_CAUGHT( excpt_r ); }
269 return ManagedFile();
270 }
271
272 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
273 {
275 OnMediaLocation resource(file, media_nr);
276 provide( std::ref(op), resource, PROVIDE_DEFAULT );
277 return op.result;
278 }
279
280 void MediaSetAccess::precacheFiles(const std::vector<OnMediaLocation> &files)
281 {
282 media::MediaManager media_mgr;
283
284 for ( const auto &resource : files ) {
285 unsigned media_nr(resource.medianr());
287
288 if ( !media_mgr.isOpen( media ) ) {
289 MIL << "Skipping precache of file " << resource.filename() << " media is not open";
290 continue;
291 }
292
293 if ( ! media_mgr.isAttached(media) )
294 media_mgr.attach(media);
295
296 media_mgr.precacheFiles( media, { resource } );
297 }
298 }
299
301 const OnMediaLocation &resource,
302 ProvideFileOptions options )
303 {
304 const auto &file(resource.filename());
305 unsigned media_nr(resource.medianr());
306
308 media::MediaManager media_mgr;
309
311
312 do
313 {
314 // get the mediaId, but don't try to attach it here
315 media = getMediaAccessId( media_nr);
316
317 try
318 {
319 DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
320 << " from media number " << media_nr << endl;
321 // try to attach the media
322 if ( ! media_mgr.isAttached(media) )
323 media_mgr.attach(media);
324 op(media, resource);
325 break;
326 }
327 catch ( media::MediaException & excp )
328 {
329 ZYPP_CAUGHT(excp);
331 unsigned int devindex = 0;
332 std::vector<std::string> devices;
333 media_mgr.getDetectedDevices(media, devices, devindex);
334
335 do
336 {
337 // set up the reason
339
340 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
341 typeid(excp) == typeid( media::MediaNotAFileException ) )
342 {
344 }
345 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
346 typeid(excp) == typeid( media::MediaNotAttachedException) )
347 {
349 }
350 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
351 typeid(excp) == typeid( media::MediaTemporaryProblemException))
352 {
354 }
355
356 // Propagate the original error if _no_ callback receiver is connected, or
357 // non_interactive mode (for optional files) is used (except for wrong media).
359 || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
360 {
361 MIL << "Can't provide file. Non-Interactive mode." << endl;
362 ZYPP_RETHROW(excp);
363 }
364 else
365 {
366 // release all media before requesting another (#336881)
367 media_mgr.releaseAll();
368
369 zypp::Url u = _pimpl->_origin.authority().url();
370 user = report->requestMedia (
371 u,
372 media_nr,
373 _pimpl->_label,
374 reason,
375 excp.asUserHistory(),
376 devices,
377 devindex
378 );
379
380 // if the user changes the primary URL, we can no longer use the mirrors,
381 // so we drop them and the settings for the primary too!
382 if ( u != _pimpl->_origin.authority().url() ) {
383 MIL << "User changed the URL, dropping all mirrors" << std::endl;
384 _pimpl->_origin.clearMirrors();
385 _pimpl->_origin.setAuthority(u);
386 }
387 }
388
389 MIL << "ProvideFile exception caught, callback answer: " << user << endl;
390
392 {
393 DBG << "Aborting" << endl;
394 AbortRequestException aexcp("Aborting requested by user");
395 aexcp.remember(excp);
396 ZYPP_THROW(aexcp);
397 }
398 else if ( user == media::MediaChangeReport::IGNORE )
399 {
400 DBG << "Skipping" << endl;
401 SkipRequestException nexcp("User-requested skipping of a file");
402 nexcp.remember(excp);
403 ZYPP_THROW(nexcp);
404 }
405 else if ( user == media::MediaChangeReport::EJECT )
406 {
407 DBG << "Eject: try to release" << endl;
408 try
409 {
410 media_mgr.releaseAll();
411 media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
412 }
413 catch ( const Exception & e)
414 {
415 ZYPP_CAUGHT(e);
416 }
417 }
418 else if ( user == media::MediaChangeReport::RETRY ||
420 {
421 // retry
422 DBG << "Going to try again" << endl;
423 // invalidate current media access id
424 media_mgr.close(media);
425 _pimpl->_medias.erase(media_nr);
426
427 // not attaching, media set will do that for us
428 // this could generate uncaught exception (#158620)
429 break;
430 }
431 else
432 {
433 DBG << "Don't know, let's ABORT" << endl;
434 ZYPP_RETHROW ( excp );
435 }
436 } while( user == media::MediaChangeReport::EJECT );
437 }
438
439 // retry or change URL
440 } while( true );
441 }
442
444 bool recursive,
445 unsigned media_nr,
446 ProvideFileOptions options )
447 {
448 OnMediaLocation resource(dir, media_nr);
449 if ( recursive )
450 {
452 provide( std::ref(op), resource, options );
453 return op.result;
454 }
456 provide( std::ref(op), resource, options );
457 return op.result;
458 }
459
461 {
462 if ( _pimpl->_medias.find( medianr ) != _pimpl->_medias.end() )
463 {
464 return _pimpl->_medias[medianr];
465 }
466
467 MirroredOrigin rewrittenOrigin = _pimpl->_origin;
468 if ( medianr > 1 ) {
469 for ( auto &url : rewrittenOrigin ) {
470 url.setUrl ( rewriteUrl (url.url(), medianr) );
471 }
472 }
473 media::MediaManager media_mgr;
474 media::MediaAccessId id = media_mgr.open( rewrittenOrigin, _pimpl->_prefAttachPoint );
475 _pimpl->_medias[medianr] = id;
476
477 try
478 {
479 if ( _pimpl->_verifiers.find(medianr) != _pimpl->_verifiers.end() )
480 {
481 // a verifier is set for this media
482 // FIXME check the case where the verifier exists
483 // but we have no access id for the media
484 media_mgr.delVerifier( id );
485 media_mgr.addVerifier( id, _pimpl->_verifiers[medianr] );
486 // remove any saved verifier for this media
487 _pimpl->_verifiers.erase( medianr );
488 }
489 }
490 catch ( const Exception &e )
491 {
492 ZYPP_CAUGHT(e);
493 WAR << "Verifier not found" << endl;
494 }
495
496 return id;
497 }
498
499
500 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
501 {
502 std::string scheme = url_r.getScheme();
503 if (scheme == "cd" || scheme == "dvd")
504 return url_r;
505
506 DBG << "Rewriting url " << url_r << endl;
507
508 if( scheme == "iso")
509 {
510 // TODO the iso parameter will not be required in the future, this
511 // code has to be adapted together with the MediaISO change.
512 // maybe some MediaISOURL interface should be used.
513 std::string isofile = url_r.getQueryParam("iso");
514 str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
515
516 str::smatch what;
517 if(str::regex_match(isofile, what, e))
518 {
519 Url url( url_r);
520 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
521 url.setQueryParam("iso", isofile);
522 DBG << "Url rewrite result: " << url << endl;
523 return url;
524 }
525 }
526 else
527 {
528 std::string pathname = url_r.getPathName();
529 str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
530 str::smatch what;
531 if(str::regex_match(pathname, what, e))
532 {
533 Url url( url_r);
534 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
535 url.setPathName(pathname);
536 DBG << "Url rewrite result: " << url << endl;
537 return url;
538 }
539 }
540 return url_r;
541 }
542
544 {
545 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
546 media::MediaManager manager;
547 for ( auto m = _pimpl->_medias.begin(); m != _pimpl->_medias.end(); ++m )
548 manager.release(m->second, "");
549 }
550
551 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
552 {
553 str << "MediaSetAccess (URL='" << _pimpl->_origin.authority().url() << "', attach_point_hint='" << _pimpl->_prefAttachPoint << "')";
554 return str;
555 }
556
558} // namespace zypp
Base class for Exception.
Definition Exception.h:153
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:140
Pathname _prefAttachPoint
Prefered mount point.
Impl(std::string &&label_r, MirroredOrigin &&origin, Pathname &&prefered_attach_point)
MirroredOrigin _origin
Media Origin configuration.
VerifierMap _verifiers
Mapping between media number and corespondent verifier.
std::map< media::MediaNr, media::MediaVerifierRef > VerifierMap
std::map< media::MediaNr, media::MediaAccessId > MediaMap
MediaMap _medias
Mapping between media number and Media Access ID.
Impl(MirroredOrigin &&origin, Pathname &&prefered_attach_point)
Media access layer responsible for handling files distributed on a set of media with media change and...
media::MediaAccessId getMediaAccessId(media::MediaNr medianr)
Pathname provideDir(const Pathname &dir, bool recursive, unsigned media_nr=1, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides direcotry dir from media number media_nr.
void precacheFiles(const std::vector< OnMediaLocation > &files)
Tries to fetch the given files and precaches them.
void setVerifier(unsigned media_nr, const media::MediaVerifierRef &verifier)
Sets a MediaVerifier verifier for given media number.
MediaSetAccess(Url url, Pathname prefered_attach_point="")
Creates a callback enabled media access for specified url.
static ManagedFile provideFileFromUrl(const Url &file_url, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides file from url.
void provide(const ProvideOperation &op, const OnMediaLocation &resource, ProvideFileOptions options)
std::unique_ptr< Impl > _pimpl
Pointer to implementation.
@ PROVIDE_DEFAULT
The user is not asked anything, and the error exception is just propagated.
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides a file from a media location.
void setLabel(const std::string &label_r)
Set the label identifing this media set and to be sent in a media change request.
Pathname provideOptionalFile(const Pathname &file, unsigned media_nr=1)
Provides an optional file from media media_nr.
static ManagedFile provideOptionalFileFromUrl(const Url &file_url)
Provides an optional file from url.
bool doesFileExist(const Pathname &file, unsigned media_nr=1)
Checks if a file exists on the specified media, with user callbacks.
void dirInfo(filesystem::DirContent &retlist, const Pathname &dirname, bool dots=true, unsigned media_nr=1)
Fills retlist with directory information.
void release()
Release all attached media of this set.
function< void(media::MediaAccessId, const OnMediaLocation &)> ProvideOperation
static Url rewriteUrl(const Url &url_r, const media::MediaNr medianr)
Replaces media number in specified url with given medianr.
std::ostream & dumpOn(std::ostream &str) const override
Overload to realize std::ostream & operator<<.
void releaseFile(const OnMediaLocation &resource)
Release file from media.
const std::string & label() const
The label identifing this media set and to be sent in a media change request.
Manages a data source characterized by an authoritative URL and a list of mirror URLs.
Describes a resource file located on a medium.
bool optional() const
Whether this is an optional resource.
const Pathname & filename() const
The path to the resource on the medium.
unsigned medianr() const
The media number the resource is located on.
Url manipulation class.
Definition Url.h:93
std::string getScheme() const
Returns the scheme name of the URL.
Definition Url.cc:551
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition Url.cc:622
std::string getQueryParam(const std::string &param, EEncoding eflag=zypp::url::E_DECODED) const
Return the value for the specified query parameter.
Definition Url.cc:678
const std::string & asString() const
String representation.
Definition Pathname.h:93
static ManagedFile asManagedFile()
Create a temporary file and convert it to a automatically cleaned up ManagedFile.
Definition TmpPath.cc:240
Just inherits Exception to separate media exceptions.
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees,...
MediaAccessId open(const Url &url, const Pathname &preferred_attach_point="")
Opens the media access for specified with the url.
void delVerifier(MediaAccessId accessId)
Remove verifier for specified media id.
void releaseFile(MediaAccessId accessId, const Pathname &filename) const
FIXME: see MediaAccess class.
void releaseAll()
Release all attached media.
void attach(MediaAccessId accessId)
Attach the media using the concrete handler (checks all devices).
bool isOpen(MediaAccessId accessId) const
Query if the media access is open / exists.
void dirInfo(MediaAccessId accessId, std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
FIXME: see MediaAccess class.
void close(MediaAccessId accessId)
Close the media access with specified id.
ZYPP_DEPRECATED void provideFile(MediaAccessId accessId, const Pathname &filename, const ByteCount &expectedFileSize) const
void release(MediaAccessId accessId, const std::string &ejectDev="")
Release the attached media and optionally eject.
void precacheFiles(MediaAccessId accessId, const std::vector< OnMediaLocation > &files)
Tries to fetch the given files and precaches them.
bool isAttached(MediaAccessId accessId) const
Check if media is attached or not.
bool doesFileExist(MediaAccessId accessId, const Pathname &filename) const
FIXME: see MediaAccess class.
void provideDir(MediaAccessId accessId, const Pathname &dirname) const
FIXME: see MediaAccess class.
Pathname localPath(MediaAccessId accessId, const Pathname &pathname) const
Shortcut for 'localRoot() + pathname', but returns an empty pathname if media is not attached.
void provideDirTree(MediaAccessId accessId, const Pathname &dirname) const
FIXME: see MediaAccess class.
void addVerifier(MediaAccessId accessId, const MediaVerifierRef &verifier)
Add verifier implementation for the specified media id.
void getDetectedDevices(MediaAccessId accessId, std::vector< std::string > &devices, unsigned int &index) const
Fill in a vector of detected ejectable devices and the index of the currently attached device within ...
Regular expression.
Definition Regex.h:95
@ icase
Do not differentiate case.
Definition Regex.h:99
Regular expression match result.
Definition Regex.h:168
Definition Arch.h:364
String related utilities and Regular expression matching.
std::list< DirEntry > DirContent
Returned by readdir.
Definition PathInfo.h:526
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition PathInfo.cc:888
unsigned int MediaNr
unsigned int MediaAccessId
Media manager access Id type.
Definition MediaSource.h:30
zypp::RW_pointer< MediaVerifierBase > MediaVerifierRef
A shared reference to the MediaVerifier implementation.
std::string numstring(char n, int w=0)
Definition String.h:290
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
Definition Regex.h:70
Url details namespace.
Definition UrlBase.cc:58
Easy-to use interface to the ZYPP dependency resolver.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
static bool connected()
Definition Callback.h:251
@ IO_SOFT
IO error which can happen on worse connection like timeout exceed.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:479
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define DBG
Definition Logger.h:99
#define MIL
Definition Logger.h:100
#define WAR
Definition Logger.h:101
#define IMPL_PTR_TYPE(NAME)