libzypp 17.36.3
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
36
38 Pathname prefered_attach_point)
39 : _url(std::move(url))
40 , _prefAttachPoint(std::move(prefered_attach_point))
41 {}
42
43 MediaSetAccess::MediaSetAccess(std::string label_r,
44 Url url,
45 Pathname prefered_attach_point)
46 : _url(std::move(url))
47 , _prefAttachPoint(std::move(prefered_attach_point))
48 , _label(std::move( label_r ))
49 {}
50
52 {
53 try
54 {
55 media::MediaManager manager;
56 for ( const auto & mm : _medias )
57 manager.close( mm.second );
58 }
59 catch(...) {} // don't let exception escape a dtor.
60 }
61
62
63 void MediaSetAccess::setVerifier( unsigned media_nr, const media::MediaVerifierRef& verifier )
64 {
65 if (_medias.find(media_nr) != _medias.end())
66 {
67 // the media already exists, set theverifier
68 media::MediaAccessId id = _medias[media_nr];
69 media::MediaManager media_mgr;
70 media_mgr.addVerifier( id, verifier );
71 // remove any saved verifier for this media
72 _verifiers.erase(media_nr);
73 }
74 else
75 {
76 // save the verifier in the map, and set it when
77 // the media number is first attached
78 _verifiers[media_nr] = verifier;
79 }
80 }
81
82 void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file )
83 {
84 releaseFile( on_media_file.filename(), on_media_file.medianr() );
85 }
86
87 void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
88 {
89 media::MediaManager media_mgr;
91 DBG << "Going to release file " << file
92 << " from media number " << media_nr << endl;
93
94 if ( ! media_mgr.isAttached(media) )
95 return; //disattached media is free
96
97 media_mgr.releaseFile (media, file);
98 }
99
101 bool dots, unsigned media_nr )
102 {
103 media::MediaManager media_mgr;
105
106 // try to attach the media
107 if ( ! media_mgr.isAttached(media) )
108 media_mgr.attach(media);
109
110 media_mgr.dirInfo(media, retlist, dirname, dots);
111 }
112
114 {
117 {
118 media::MediaManager media_mgr;
119 media_mgr.provideFile( media, file );
120 result = media_mgr.localPath( media, file.filename() );
121 }
122 };
123
125 {
128 {
129 const auto &fName = file.filename();
130 media::MediaManager media_mgr;
131 media_mgr.provideDirTree( media, fName );
132 result = media_mgr.localPath( media, fName );
133 }
134 };
135
137 {
140 {
141 const auto &fName = file.filename();
142 media::MediaManager media_mgr;
143 media_mgr.provideDir( media, fName );
144 result = media_mgr.localPath( media, fName );
145 }
146 };
147
149 {
150 bool result;
154
156 {
157 const auto &fName = file.filename();
158 media::MediaManager media_mgr;
159 result = media_mgr.doesFileExist( media, fName );
160 }
161 };
162
163 Pathname MediaSetAccess::provideFile( const OnMediaLocation &resource, ProvideFileOptions options )
164 {
166 provide( std::ref(op), resource, options );
167 return op.result;
168 }
169
170 Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
171 {
172 return provideFile( OnMediaLocation( resource ).setDeltafile( deltafile ), options );
173 }
174
175 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options )
176 {
177 return provideFile( OnMediaLocation( file, media_nr ), options );
178 }
179
180 Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr )
181 {
182 try
183 {
184 return provideFile( OnMediaLocation( file, media_nr ).setOptional( true ), PROVIDE_NON_INTERACTIVE );
185 }
186 catch ( const media::MediaFileNotFoundException & excpt_r )
187 { ZYPP_CAUGHT( excpt_r ); }
188 catch ( const media::MediaForbiddenException & excpt_r )
189 { ZYPP_CAUGHT( excpt_r ); }
190 catch ( const media::MediaNotAFileException & excpt_r )
191 { ZYPP_CAUGHT( excpt_r ); }
192 return Pathname();
193 }
194
195 ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
196 {
197 Url url(file_url);
198 Pathname path(url.getPathName());
199
200 url.setPathName ("/");
201 MediaSetAccess access(url);
202
204
205 bool optional = options & PROVIDE_NON_INTERACTIVE;
206 Pathname file = access.provideFile( OnMediaLocation(path, 1).setOptional( optional ), options );
207
208 //prevent the file from being deleted when MediaSetAccess gets out of scope
209 if ( filesystem::hardlinkCopy(file, tmpFile) != 0 )
210 ZYPP_THROW(Exception("Can't copy file from " + file.asString() + " to " + tmpFile->asString() ));
211
212 return tmpFile;
213 }
214
216 {
217 try
218 {
220 }
221 catch ( const media::MediaFileNotFoundException & excpt_r )
222 { ZYPP_CAUGHT( excpt_r ); }
223 catch ( const media::MediaNotAFileException & excpt_r )
224 { ZYPP_CAUGHT( excpt_r ); }
225 return ManagedFile();
226 }
227
228 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
229 {
231 OnMediaLocation resource(file, media_nr);
232 provide( std::ref(op), resource, PROVIDE_DEFAULT );
233 return op.result;
234 }
235
236 void MediaSetAccess::precacheFiles(const std::vector<OnMediaLocation> &files)
237 {
238 media::MediaManager media_mgr;
239
240 for ( const auto &resource : files ) {
241 unsigned media_nr(resource.medianr());
243
244 if ( !media_mgr.isOpen( media ) ) {
245 MIL << "Skipping precache of file " << resource.filename() << " media is not open";
246 continue;
247 }
248
249 if ( ! media_mgr.isAttached(media) )
250 media_mgr.attach(media);
251
252 media_mgr.precacheFiles( media, { resource } );
253 }
254 }
255
257 const OnMediaLocation &resource,
258 ProvideFileOptions options )
259 {
260 const auto &file(resource.filename());
261 unsigned media_nr(resource.medianr());
262
264 media::MediaManager media_mgr;
265
267
268 do
269 {
270 // get the mediaId, but don't try to attach it here
271 media = getMediaAccessId( media_nr);
272
273 try
274 {
275 DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
276 << " from media number " << media_nr << endl;
277 // try to attach the media
278 if ( ! media_mgr.isAttached(media) )
279 media_mgr.attach(media);
280 op(media, resource);
281 break;
282 }
283 catch ( media::MediaException & excp )
284 {
285 ZYPP_CAUGHT(excp);
287 unsigned int devindex = 0;
288 std::vector<std::string> devices;
289 media_mgr.getDetectedDevices(media, devices, devindex);
290
291 do
292 {
293 // set up the reason
295
296 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
297 typeid(excp) == typeid( media::MediaNotAFileException ) )
298 {
300 }
301 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
302 typeid(excp) == typeid( media::MediaNotAttachedException) )
303 {
305 }
306 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
307 typeid(excp) == typeid( media::MediaTemporaryProblemException))
308 {
310 }
311
312 // Propagate the original error if _no_ callback receiver is connected, or
313 // non_interactive mode (for optional files) is used (except for wrong media).
315 || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
316 {
317 MIL << "Can't provide file. Non-Interactive mode." << endl;
318 ZYPP_RETHROW(excp);
319 }
320 else
321 {
322 // release all media before requesting another (#336881)
323 media_mgr.releaseAll();
324
325 user = report->requestMedia (
326 _url,
327 media_nr,
328 _label,
329 reason,
330 excp.asUserHistory(),
331 devices,
332 devindex
333 );
334 }
335
336 MIL << "ProvideFile exception caught, callback answer: " << user << endl;
337
339 {
340 DBG << "Aborting" << endl;
341 AbortRequestException aexcp("Aborting requested by user");
342 aexcp.remember(excp);
343 ZYPP_THROW(aexcp);
344 }
345 else if ( user == media::MediaChangeReport::IGNORE )
346 {
347 DBG << "Skipping" << endl;
348 SkipRequestException nexcp("User-requested skipping of a file");
349 nexcp.remember(excp);
350 ZYPP_THROW(nexcp);
351 }
352 else if ( user == media::MediaChangeReport::EJECT )
353 {
354 DBG << "Eject: try to release" << endl;
355 try
356 {
357 media_mgr.releaseAll();
358 media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
359 }
360 catch ( const Exception & e)
361 {
362 ZYPP_CAUGHT(e);
363 }
364 }
365 else if ( user == media::MediaChangeReport::RETRY ||
367 {
368 // retry
369 DBG << "Going to try again" << endl;
370 // invalidate current media access id
371 media_mgr.close(media);
372 _medias.erase(media_nr);
373
374 // not attaching, media set will do that for us
375 // this could generate uncaught exception (#158620)
376 break;
377 }
378 else
379 {
380 DBG << "Don't know, let's ABORT" << endl;
381 ZYPP_RETHROW ( excp );
382 }
383 } while( user == media::MediaChangeReport::EJECT );
384 }
385
386 // retry or change URL
387 } while( true );
388 }
389
391 bool recursive,
392 unsigned media_nr,
393 ProvideFileOptions options )
394 {
395 OnMediaLocation resource(dir, media_nr);
396 if ( recursive )
397 {
399 provide( std::ref(op), resource, options );
400 return op.result;
401 }
403 provide( std::ref(op), resource, options );
404 return op.result;
405 }
406
408 {
409 if ( _medias.find( medianr ) != _medias.end() )
410 {
411 return _medias[medianr];
412 }
413
414 Url url( medianr > 1 ? rewriteUrl( _url, medianr ) : _url );
415 media::MediaManager media_mgr;
417 _medias[medianr] = id;
418
419 try
420 {
421 if ( _verifiers.find(medianr) != _verifiers.end() )
422 {
423 // a verifier is set for this media
424 // FIXME check the case where the verifier exists
425 // but we have no access id for the media
426 media_mgr.delVerifier( id );
427 media_mgr.addVerifier( id, _verifiers[medianr] );
428 // remove any saved verifier for this media
429 _verifiers.erase( medianr );
430 }
431 }
432 catch ( const Exception &e )
433 {
434 ZYPP_CAUGHT(e);
435 WAR << "Verifier not found" << endl;
436 }
437
438 return id;
439 }
440
441
442 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
443 {
444 std::string scheme = url_r.getScheme();
445 if (scheme == "cd" || scheme == "dvd")
446 return url_r;
447
448 DBG << "Rewriting url " << url_r << endl;
449
450 if( scheme == "iso")
451 {
452 // TODO the iso parameter will not be required in the future, this
453 // code has to be adapted together with the MediaISO change.
454 // maybe some MediaISOURL interface should be used.
455 std::string isofile = url_r.getQueryParam("iso");
456 str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
457
458 str::smatch what;
459 if(str::regex_match(isofile, what, e))
460 {
461 Url url( url_r);
462 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
463 url.setQueryParam("iso", isofile);
464 DBG << "Url rewrite result: " << url << endl;
465 return url;
466 }
467 }
468 else
469 {
470 std::string pathname = url_r.getPathName();
471 str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
472 str::smatch what;
473 if(str::regex_match(pathname, what, e))
474 {
475 Url url( url_r);
476 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
477 url.setPathName(pathname);
478 DBG << "Url rewrite result: " << url << endl;
479 return url;
480 }
481 }
482 return url_r;
483 }
484
486 {
487 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
488 media::MediaManager manager;
489 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
490 manager.release(m->second, "");
491 }
492
493 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
494 {
495 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
496 return str;
497 }
498
500} // namespace zypp
Base class for Exception.
Definition Exception.h:147
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:127
Media access layer responsible for handling files distributed on a set of media with media change and...
VerifierMap _verifiers
Mapping between media number and corespondent verifier.
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.
MediaMap _medias
Mapping between media number and Media Access ID.
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)
@ 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.
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.
Pathname _prefAttachPoint
Prefered mount point.
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.
Url _url
Media or media set URL.
std::ostream & dumpOn(std::ostream &str) const override
Overload to realize std::ostream & operator<<.
void releaseFile(const OnMediaLocation &resource)
Release file from media.
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:289
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:444
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:440
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:424
#define DBG
Definition Logger.h:99
#define MIL
Definition Logger.h:100
#define WAR
Definition Logger.h:101
#define IMPL_PTR_TYPE(NAME)