libzypp 17.31.0
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 <zypp-core/base/UserRequestException>
16#include <zypp-media/MediaException>
17#include <zypp/ZYppCallbacks.h>
18#include <zypp/MediaSetAccess.h>
19#include <zypp/PathInfo.h>
20#include <zypp/TmpPath.h>
21//#include <zypp/source/MediaSetAccessReportReceivers.h>
22
23#undef ZYPP_BASE_LOGGER_LOGGROUP
24#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::fetcher"
25
26using std::endl;
27
29namespace zypp
30{
31
33
35
37 const Pathname & prefered_attach_point)
38 : _url(url)
39 , _prefAttachPoint(prefered_attach_point)
40 {}
41
42 MediaSetAccess::MediaSetAccess(const std::string & label_r,
43 const Url &url,
44 const Pathname & prefered_attach_point)
45 : _url(url)
46 , _prefAttachPoint(prefered_attach_point)
47 , _label( label_r )
48 {}
49
51 {
52 try
53 {
54 media::MediaManager manager;
55 for ( const auto & mm : _medias )
56 manager.close( mm.second );
57 }
58 catch(...) {} // don't let exception escape a dtor.
59 }
60
61
63 {
64 if (_medias.find(media_nr) != _medias.end())
65 {
66 // the media already exists, set theverifier
67 media::MediaAccessId id = _medias[media_nr];
68 media::MediaManager media_mgr;
69 media_mgr.addVerifier( id, verifier );
70 // remove any saved verifier for this media
71 _verifiers.erase(media_nr);
72 }
73 else
74 {
75 // save the verifier in the map, and set it when
76 // the media number is first attached
77 _verifiers[media_nr] = verifier;
78 }
79 }
80
81 void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file )
82 {
83 releaseFile( on_media_file.filename(), on_media_file.medianr() );
84 }
85
86 void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
87 {
88 media::MediaManager media_mgr;
90
91 media = getMediaAccessId( media_nr);
92 DBG << "Going to release file " << file
93 << " from media number " << media_nr << endl;
94
95 if ( ! media_mgr.isAttached(media) )
96 return; //disattached media is free
97
98 media_mgr.releaseFile (media, file);
99 }
100
102 bool dots, unsigned media_nr )
103 {
104 media::MediaManager media_mgr;
106 media = getMediaAccessId(media_nr);
107
108 // try to attach the media
109 if ( ! media_mgr.isAttached(media) )
110 media_mgr.attach(media);
111
112 media_mgr.dirInfo(media, retlist, dirname, dots);
113 }
114
116 {
119 {
120 media::MediaManager media_mgr;
121 media_mgr.provideFile( media, file );
122 result = media_mgr.localPath( media, file.filename() );
123 }
124 };
125
127 {
130 {
131 const auto &fName = file.filename();
132 media::MediaManager media_mgr;
133 media_mgr.provideDirTree( media, fName );
134 result = media_mgr.localPath( media, fName );
135 }
136 };
137
139 {
142 {
143 const auto &fName = file.filename();
144 media::MediaManager media_mgr;
145 media_mgr.provideDir( media, fName );
146 result = media_mgr.localPath( media, fName );
147 }
148 };
149
151 {
152 bool result;
154 : result(false)
155 {}
156
158 {
159 const auto &fName = file.filename();
160 media::MediaManager media_mgr;
161 result = media_mgr.doesFileExist( media, fName );
162 }
163 };
164
165 Pathname MediaSetAccess::provideFile( const OnMediaLocation &resource, ProvideFileOptions options )
166 {
168 provide( std::ref(op), resource, options );
169 return op.result;
170 }
171
172 Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
173 {
174 return provideFile( OnMediaLocation( resource ).setDeltafile( deltafile ), options );
175 }
176
177 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options )
178 {
179 return provideFile( OnMediaLocation( file, media_nr ), options );
180 }
181
182 Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr )
183 {
184 try
185 {
186 if ( doesFileExist( file, media_nr ) )
187 return provideFile( OnMediaLocation( file, media_nr ), PROVIDE_NON_INTERACTIVE );
188 }
189 catch ( const media::MediaFileNotFoundException & excpt_r )
190 { ZYPP_CAUGHT( excpt_r ); }
191 catch ( const media::MediaForbiddenException & excpt_r )
192 { ZYPP_CAUGHT( excpt_r ); }
193 catch ( const media::MediaNotAFileException & excpt_r )
194 { ZYPP_CAUGHT( excpt_r ); }
195 return Pathname();
196 }
197
198 ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
199 {
200 Url url(file_url);
201 Pathname path(url.getPathName());
202
203 url.setPathName ("/");
204 MediaSetAccess access(url);
205
207
208 Pathname file = access.provideFile( OnMediaLocation(path, 1), options );
209
210 //prevent the file from being deleted when MediaSetAccess gets out of scope
211 if ( filesystem::hardlinkCopy(file, tmpFile) != 0 )
212 ZYPP_THROW(Exception("Can't copy file from " + file.asString() + " to " + tmpFile->asString() ));
213
214 return tmpFile;
215 }
216
218 {
219 try
220 {
222 }
223 catch ( const media::MediaFileNotFoundException & excpt_r )
224 { ZYPP_CAUGHT( excpt_r ); }
225 catch ( const media::MediaNotAFileException & excpt_r )
226 { ZYPP_CAUGHT( excpt_r ); }
227 return ManagedFile();
228 }
229
230 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
231 {
233 OnMediaLocation resource(file, media_nr);
234 provide( std::ref(op), resource, PROVIDE_DEFAULT );
235 return op.result;
236 }
237
238 void MediaSetAccess::precacheFiles(const std::vector<OnMediaLocation> &files)
239 {
240 media::MediaManager media_mgr;
241
242 for ( const auto &resource : files ) {
243 Pathname file(resource.filename());
244 unsigned media_nr(resource.medianr());
245 media::MediaAccessId media = getMediaAccessId( media_nr );
246
247 if ( !media_mgr.isOpen( media ) ) {
248 MIL << "Skipping precache of file " << resource.filename() << " media is not open";
249 continue;
250 }
251
252 if ( ! media_mgr.isAttached(media) )
253 media_mgr.attach(media);
254
255 media_mgr.precacheFiles( media, { resource } );
256 }
257 }
258
260 const OnMediaLocation &resource,
261 ProvideFileOptions options )
262 {
263 const auto &file(resource.filename());
264 unsigned media_nr(resource.medianr());
265
267 media::MediaManager media_mgr;
268
270
271 do
272 {
273 // get the mediaId, but don't try to attach it here
274 media = getMediaAccessId( media_nr);
275
276 try
277 {
278 DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
279 << " from media number " << media_nr << endl;
280 // try to attach the media
281 if ( ! media_mgr.isAttached(media) )
282 media_mgr.attach(media);
283 op(media, resource);
284 break;
285 }
286 catch ( media::MediaException & excp )
287 {
288 ZYPP_CAUGHT(excp);
290 unsigned int devindex = 0;
291 std::vector<std::string> devices;
292 media_mgr.getDetectedDevices(media, devices, devindex);
293
294 do
295 {
296 if (user != media::MediaChangeReport::EJECT) // no use in calling this again
297 {
298 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
299 try
300 {
301 media_mgr.release(media);
302 }
303 catch (const Exception & excpt_r)
304 {
305 ZYPP_CAUGHT(excpt_r);
306 MIL << "Failed to release media " << media << endl;
307 }
308 }
309
310 // set up the reason
312
313 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
314 typeid(excp) == typeid( media::MediaNotAFileException ) )
315 {
317 }
318 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
319 typeid(excp) == typeid( media::MediaNotAttachedException) )
320 {
322 }
323 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
324 typeid(excp) == typeid( media::MediaTemporaryProblemException))
325 {
327 }
328
329 // Propagate the original error if _no_ callback receiver is connected, or
330 // non_interactive mode (for optional files) is used (except for wrong media).
332 || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
333 {
334 MIL << "Can't provide file. Non-Interactive mode." << endl;
335 ZYPP_RETHROW(excp);
336 }
337 else
338 {
339 // release all media before requesting another (#336881)
340 media_mgr.releaseAll();
341
342 user = report->requestMedia (
343 _url,
344 media_nr,
345 _label,
346 reason,
347 excp.asUserHistory(),
348 devices,
349 devindex
350 );
351 }
352
353 MIL << "ProvideFile exception caught, callback answer: " << user << endl;
354
356 {
357 DBG << "Aborting" << endl;
358 AbortRequestException aexcp("Aborting requested by user");
359 aexcp.remember(excp);
360 ZYPP_THROW(aexcp);
361 }
362 else if ( user == media::MediaChangeReport::IGNORE )
363 {
364 DBG << "Skipping" << endl;
365 SkipRequestException nexcp("User-requested skipping of a file");
366 nexcp.remember(excp);
367 ZYPP_THROW(nexcp);
368 }
369 else if ( user == media::MediaChangeReport::EJECT )
370 {
371 DBG << "Eject: try to release" << endl;
372 try
373 {
374 media_mgr.releaseAll();
375 media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
376 }
377 catch ( const Exception & e)
378 {
379 ZYPP_CAUGHT(e);
380 }
381 }
382 else if ( user == media::MediaChangeReport::RETRY ||
384 {
385 // retry
386 DBG << "Going to try again" << endl;
387 // invalidate current media access id
388 media_mgr.close(media);
389 _medias.erase(media_nr);
390
391 // not attaching, media set will do that for us
392 // this could generate uncaught exception (#158620)
393 break;
394 }
395 else
396 {
397 DBG << "Don't know, let's ABORT" << endl;
398 ZYPP_RETHROW ( excp );
399 }
400 } while( user == media::MediaChangeReport::EJECT );
401 }
402
403 // retry or change URL
404 } while( true );
405 }
406
408 bool recursive,
409 unsigned media_nr,
410 ProvideFileOptions options )
411 {
412 OnMediaLocation resource(dir, media_nr);
413 if ( recursive )
414 {
416 provide( std::ref(op), resource, options );
417 return op.result;
418 }
420 provide( std::ref(op), resource, options );
421 return op.result;
422 }
423
425 {
426 if ( _medias.find( medianr ) != _medias.end() )
427 {
428 return _medias[medianr];
429 }
430
431 Url url( medianr > 1 ? rewriteUrl( _url, medianr ) : _url );
432 media::MediaManager media_mgr;
433 media::MediaAccessId id = media_mgr.open( url, _prefAttachPoint );
434 _medias[medianr] = id;
435
436 try
437 {
438 if ( _verifiers.find(medianr) != _verifiers.end() )
439 {
440 // a verifier is set for this media
441 // FIXME check the case where the verifier exists
442 // but we have no access id for the media
443 media_mgr.delVerifier( id );
444 media_mgr.addVerifier( id, _verifiers[medianr] );
445 // remove any saved verifier for this media
446 _verifiers.erase( medianr );
447 }
448 }
449 catch ( const Exception &e )
450 {
451 ZYPP_CAUGHT(e);
452 WAR << "Verifier not found" << endl;
453 }
454
455 return id;
456 }
457
458
459 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
460 {
461 std::string scheme = url_r.getScheme();
462 if (scheme == "cd" || scheme == "dvd")
463 return url_r;
464
465 DBG << "Rewriting url " << url_r << endl;
466
467 if( scheme == "iso")
468 {
469 // TODO the iso parameter will not be required in the future, this
470 // code has to be adapted together with the MediaISO change.
471 // maybe some MediaISOURL interface should be used.
472 std::string isofile = url_r.getQueryParam("iso");
473 str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
474
475 str::smatch what;
476 if(str::regex_match(isofile, what, e))
477 {
478 Url url( url_r);
479 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
480 url.setQueryParam("iso", isofile);
481 DBG << "Url rewrite result: " << url << endl;
482 return url;
483 }
484 }
485 else
486 {
487 std::string pathname = url_r.getPathName();
488 str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
489 str::smatch what;
490 if(str::regex_match(pathname, what, e))
491 {
492 Url url( url_r);
493 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
494 url.setPathName(pathname);
495 DBG << "Url rewrite result: " << url << endl;
496 return url;
497 }
498 }
499 return url_r;
500 }
501
503 {
504 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
505 media::MediaManager manager;
506 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
507 manager.release(m->second, "");
508 }
509
510 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
511 {
512 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
513 return str;
514 }
515
517} // namespace zypp
MediaVerifierRef verifier
Pathname deltafile
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:94
Base class for Exception.
Definition: Exception.h:146
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.
virtual std::ostream & dumpOn(std::ostream &str) const
Overload to realize std::ostream & operator<<.
void precacheFiles(const std::vector< OnMediaLocation > &files)
Tries to fetch the given files and precaches them.
function< void(media::MediaAccessId, const OnMediaLocation &)> ProvideOperation
static ManagedFile provideFileFromUrl(const Url &file_url, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides file from url.
@ 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.
void setVerifier(unsigned media_nr, media::MediaVerifierRef verifier)
Sets a MediaVerifier verifier for given media number.
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.
MediaSetAccess(const Url &url, const Pathname &prefered_attach_point="")
Creates a callback enabled media access for specified url.
void release()
Release all attached media of this set.
Pathname _prefAttachPoint
Prefered mount point.
static Url rewriteUrl(const Url &url_r, const media::MediaNr medianr)
Replaces media number in specified url with given medianr.
void provide(ProvideOperation op, const OnMediaLocation &resource, ProvideFileOptions options)
Url _url
Media or media set URL.
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:92
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:533
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:604
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:660
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:764
void setQueryParam(const std::string &param, const std::string &value)
Set or add value for the specified query parameter.
Definition: Url.cc:838
const std::string & asString() const
String representation.
Definition: Pathname.h:91
static ManagedFile asManagedFile()
Create a temporary file and convert it to a automatically cleaned up ManagedFile.
Definition: TmpPath.cc:230
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees,...
Definition: MediaManager.h:454
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
String related utilities and Regular expression matching.
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:883
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:518
unsigned int MediaNr
Definition: MediaManager.h:30
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
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
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
IMPL_PTR_TYPE(Application)
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)
Wrapper for const correct access via Smart pointer types.
Definition: PtrTypes.h:286
@ 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: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 DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96
#define WAR
Definition: Logger.h:97