libzypp 17.31.23
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 return provideFile( OnMediaLocation( file, media_nr ).setOptional( true ), PROVIDE_NON_INTERACTIVE );
187 }
188 catch ( const media::MediaFileNotFoundException & excpt_r )
189 { ZYPP_CAUGHT( excpt_r ); }
190 catch ( const media::MediaForbiddenException & excpt_r )
191 { ZYPP_CAUGHT( excpt_r ); }
192 catch ( const media::MediaNotAFileException & excpt_r )
193 { ZYPP_CAUGHT( excpt_r ); }
194 return Pathname();
195 }
196
197 ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
198 {
199 Url url(file_url);
200 Pathname path(url.getPathName());
201
202 url.setPathName ("/");
203 MediaSetAccess access(url);
204
206
207 bool optional = options & PROVIDE_NON_INTERACTIVE;
208 Pathname file = access.provideFile( OnMediaLocation(path, 1).setOptional( optional ), 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 // set up the reason
298
299 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
300 typeid(excp) == typeid( media::MediaNotAFileException ) )
301 {
303 }
304 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
305 typeid(excp) == typeid( media::MediaNotAttachedException) )
306 {
308 }
309 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
310 typeid(excp) == typeid( media::MediaTemporaryProblemException))
311 {
313 }
314
315 // Propagate the original error if _no_ callback receiver is connected, or
316 // non_interactive mode (for optional files) is used (except for wrong media).
318 || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
319 {
320 MIL << "Can't provide file. Non-Interactive mode." << endl;
321 ZYPP_RETHROW(excp);
322 }
323 else
324 {
325 // release all media before requesting another (#336881)
326 media_mgr.releaseAll();
327
328 user = report->requestMedia (
329 _url,
330 media_nr,
331 _label,
332 reason,
333 excp.asUserHistory(),
334 devices,
335 devindex
336 );
337 }
338
339 MIL << "ProvideFile exception caught, callback answer: " << user << endl;
340
342 {
343 DBG << "Aborting" << endl;
344 AbortRequestException aexcp("Aborting requested by user");
345 aexcp.remember(excp);
346 ZYPP_THROW(aexcp);
347 }
348 else if ( user == media::MediaChangeReport::IGNORE )
349 {
350 DBG << "Skipping" << endl;
351 SkipRequestException nexcp("User-requested skipping of a file");
352 nexcp.remember(excp);
353 ZYPP_THROW(nexcp);
354 }
355 else if ( user == media::MediaChangeReport::EJECT )
356 {
357 DBG << "Eject: try to release" << endl;
358 try
359 {
360 media_mgr.releaseAll();
361 media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
362 }
363 catch ( const Exception & e)
364 {
365 ZYPP_CAUGHT(e);
366 }
367 }
368 else if ( user == media::MediaChangeReport::RETRY ||
370 {
371 // retry
372 DBG << "Going to try again" << endl;
373 // invalidate current media access id
374 media_mgr.close(media);
375 _medias.erase(media_nr);
376
377 // not attaching, media set will do that for us
378 // this could generate uncaught exception (#158620)
379 break;
380 }
381 else
382 {
383 DBG << "Don't know, let's ABORT" << endl;
384 ZYPP_RETHROW ( excp );
385 }
386 } while( user == media::MediaChangeReport::EJECT );
387 }
388
389 // retry or change URL
390 } while( true );
391 }
392
394 bool recursive,
395 unsigned media_nr,
396 ProvideFileOptions options )
397 {
398 OnMediaLocation resource(dir, media_nr);
399 if ( recursive )
400 {
402 provide( std::ref(op), resource, options );
403 return op.result;
404 }
406 provide( std::ref(op), resource, options );
407 return op.result;
408 }
409
411 {
412 if ( _medias.find( medianr ) != _medias.end() )
413 {
414 return _medias[medianr];
415 }
416
417 Url url( medianr > 1 ? rewriteUrl( _url, medianr ) : _url );
418 media::MediaManager media_mgr;
419 media::MediaAccessId id = media_mgr.open( url, _prefAttachPoint );
420 _medias[medianr] = id;
421
422 try
423 {
424 if ( _verifiers.find(medianr) != _verifiers.end() )
425 {
426 // a verifier is set for this media
427 // FIXME check the case where the verifier exists
428 // but we have no access id for the media
429 media_mgr.delVerifier( id );
430 media_mgr.addVerifier( id, _verifiers[medianr] );
431 // remove any saved verifier for this media
432 _verifiers.erase( medianr );
433 }
434 }
435 catch ( const Exception &e )
436 {
437 ZYPP_CAUGHT(e);
438 WAR << "Verifier not found" << endl;
439 }
440
441 return id;
442 }
443
444
445 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
446 {
447 std::string scheme = url_r.getScheme();
448 if (scheme == "cd" || scheme == "dvd")
449 return url_r;
450
451 DBG << "Rewriting url " << url_r << endl;
452
453 if( scheme == "iso")
454 {
455 // TODO the iso parameter will not be required in the future, this
456 // code has to be adapted together with the MediaISO change.
457 // maybe some MediaISOURL interface should be used.
458 std::string isofile = url_r.getQueryParam("iso");
459 str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
460
461 str::smatch what;
462 if(str::regex_match(isofile, what, e))
463 {
464 Url url( url_r);
465 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
466 url.setQueryParam("iso", isofile);
467 DBG << "Url rewrite result: " << url << endl;
468 return url;
469 }
470 }
471 else
472 {
473 std::string pathname = url_r.getPathName();
474 str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
475 str::smatch what;
476 if(str::regex_match(pathname, what, e))
477 {
478 Url url( url_r);
479 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
480 url.setPathName(pathname);
481 DBG << "Url rewrite result: " << url << endl;
482 return url;
483 }
484 }
485 return url_r;
486 }
487
489 {
490 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
491 media::MediaManager manager;
492 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
493 manager.release(m->second, "");
494 }
495
496 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
497 {
498 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
499 return str;
500 }
501
503} // namespace zypp
MediaVerifierRef verifier
Pathname deltafile
Base class for Exception.
Definition: Exception.h:146
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:91
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
Just inherits Exception to separate media exceptions.
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:32
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
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
#define IMPL_PTR_TYPE(NAME)