libzypp 17.31.2
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 // handle not-found condition via MediaFileNotFoundException
188 return provideFile( OnMediaLocation( file, media_nr ), PROVIDE_NON_INTERACTIVE );
189 }
190 catch ( const media::MediaFileNotFoundException & excpt_r )
191 { } // ignore not found
192 catch ( const media::MediaForbiddenException & excpt_r )
193 { ZYPP_CAUGHT( excpt_r ); }
194 catch ( const media::MediaNotAFileException & excpt_r )
195 { ZYPP_CAUGHT( excpt_r ); }
196 return Pathname();
197 }
198
199 ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
200 {
201 Url url(file_url);
202 Pathname path(url.getPathName());
203
204 url.setPathName ("/");
205 MediaSetAccess access(url);
206
208
209 Pathname file = access.provideFile( OnMediaLocation(path, 1), options );
210
211 //prevent the file from being deleted when MediaSetAccess gets out of scope
212 if ( filesystem::hardlinkCopy(file, tmpFile) != 0 )
213 ZYPP_THROW(Exception("Can't copy file from " + file.asString() + " to " + tmpFile->asString() ));
214
215 return tmpFile;
216 }
217
219 {
220 try
221 {
223 }
224 catch ( const media::MediaFileNotFoundException & excpt_r )
225 { ZYPP_CAUGHT( excpt_r ); }
226 catch ( const media::MediaNotAFileException & excpt_r )
227 { ZYPP_CAUGHT( excpt_r ); }
228 return ManagedFile();
229 }
230
231 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
232 {
234 OnMediaLocation resource(file, media_nr);
235 provide( std::ref(op), resource, PROVIDE_DEFAULT );
236 return op.result;
237 }
238
239 void MediaSetAccess::precacheFiles(const std::vector<OnMediaLocation> &files)
240 {
241 media::MediaManager media_mgr;
242
243 for ( const auto &resource : files ) {
244 Pathname file(resource.filename());
245 unsigned media_nr(resource.medianr());
246 media::MediaAccessId media = getMediaAccessId( media_nr );
247
248 if ( !media_mgr.isOpen( media ) ) {
249 MIL << "Skipping precache of file " << resource.filename() << " media is not open";
250 continue;
251 }
252
253 if ( ! media_mgr.isAttached(media) )
254 media_mgr.attach(media);
255
256 media_mgr.precacheFiles( media, { resource } );
257 }
258 }
259
261 const OnMediaLocation &resource,
262 ProvideFileOptions options )
263 {
264 const auto &file(resource.filename());
265 unsigned media_nr(resource.medianr());
266
268 media::MediaManager media_mgr;
269
271
272 do
273 {
274 // get the mediaId, but don't try to attach it here
275 media = getMediaAccessId( media_nr);
276
277 try
278 {
279 DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
280 << " from media number " << media_nr << endl;
281 // try to attach the media
282 if ( ! media_mgr.isAttached(media) )
283 media_mgr.attach(media);
284 op(media, resource);
285 break;
286 }
287 catch ( media::MediaException & excp )
288 {
289 ZYPP_CAUGHT(excp);
291 unsigned int devindex = 0;
292 std::vector<std::string> devices;
293 media_mgr.getDetectedDevices(media, devices, devindex);
294
295 do
296 {
297 if (user != media::MediaChangeReport::EJECT) // no use in calling this again
298 {
299 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
300 try
301 {
302 media_mgr.release(media);
303 }
304 catch (const Exception & excpt_r)
305 {
306 ZYPP_CAUGHT(excpt_r);
307 MIL << "Failed to release media " << media << endl;
308 }
309 }
310
311 // set up the reason
313
314 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
315 typeid(excp) == typeid( media::MediaNotAFileException ) )
316 {
318 }
319 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
320 typeid(excp) == typeid( media::MediaNotAttachedException) )
321 {
323 }
324 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
325 typeid(excp) == typeid( media::MediaTemporaryProblemException))
326 {
328 }
329
330 // Propagate the original error if _no_ callback receiver is connected, or
331 // non_interactive mode (for optional files) is used (except for wrong media).
333 || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
334 {
335 MIL << "Can't provide file. Non-Interactive mode." << endl;
336 ZYPP_RETHROW(excp);
337 }
338 else
339 {
340 // release all media before requesting another (#336881)
341 media_mgr.releaseAll();
342
343 user = report->requestMedia (
344 _url,
345 media_nr,
346 _label,
347 reason,
348 excp.asUserHistory(),
349 devices,
350 devindex
351 );
352 }
353
354 MIL << "ProvideFile exception caught, callback answer: " << user << endl;
355
357 {
358 DBG << "Aborting" << endl;
359 AbortRequestException aexcp("Aborting requested by user");
360 aexcp.remember(excp);
361 ZYPP_THROW(aexcp);
362 }
363 else if ( user == media::MediaChangeReport::IGNORE )
364 {
365 DBG << "Skipping" << endl;
366 SkipRequestException nexcp("User-requested skipping of a file");
367 nexcp.remember(excp);
368 ZYPP_THROW(nexcp);
369 }
370 else if ( user == media::MediaChangeReport::EJECT )
371 {
372 DBG << "Eject: try to release" << endl;
373 try
374 {
375 media_mgr.releaseAll();
376 media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
377 }
378 catch ( const Exception & e)
379 {
380 ZYPP_CAUGHT(e);
381 }
382 }
383 else if ( user == media::MediaChangeReport::RETRY ||
385 {
386 // retry
387 DBG << "Going to try again" << endl;
388 // invalidate current media access id
389 media_mgr.close(media);
390 _medias.erase(media_nr);
391
392 // not attaching, media set will do that for us
393 // this could generate uncaught exception (#158620)
394 break;
395 }
396 else
397 {
398 DBG << "Don't know, let's ABORT" << endl;
399 ZYPP_RETHROW ( excp );
400 }
401 } while( user == media::MediaChangeReport::EJECT );
402 }
403
404 // retry or change URL
405 } while( true );
406 }
407
409 bool recursive,
410 unsigned media_nr,
411 ProvideFileOptions options )
412 {
413 OnMediaLocation resource(dir, media_nr);
414 if ( recursive )
415 {
417 provide( std::ref(op), resource, options );
418 return op.result;
419 }
421 provide( std::ref(op), resource, options );
422 return op.result;
423 }
424
426 {
427 if ( _medias.find( medianr ) != _medias.end() )
428 {
429 return _medias[medianr];
430 }
431
432 Url url( medianr > 1 ? rewriteUrl( _url, medianr ) : _url );
433 media::MediaManager media_mgr;
434 media::MediaAccessId id = media_mgr.open( url, _prefAttachPoint );
435 _medias[medianr] = id;
436
437 try
438 {
439 if ( _verifiers.find(medianr) != _verifiers.end() )
440 {
441 // a verifier is set for this media
442 // FIXME check the case where the verifier exists
443 // but we have no access id for the media
444 media_mgr.delVerifier( id );
445 media_mgr.addVerifier( id, _verifiers[medianr] );
446 // remove any saved verifier for this media
447 _verifiers.erase( medianr );
448 }
449 }
450 catch ( const Exception &e )
451 {
452 ZYPP_CAUGHT(e);
453 WAR << "Verifier not found" << endl;
454 }
455
456 return id;
457 }
458
459
460 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
461 {
462 std::string scheme = url_r.getScheme();
463 if (scheme == "cd" || scheme == "dvd")
464 return url_r;
465
466 DBG << "Rewriting url " << url_r << endl;
467
468 if( scheme == "iso")
469 {
470 // TODO the iso parameter will not be required in the future, this
471 // code has to be adapted together with the MediaISO change.
472 // maybe some MediaISOURL interface should be used.
473 std::string isofile = url_r.getQueryParam("iso");
474 str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
475
476 str::smatch what;
477 if(str::regex_match(isofile, what, e))
478 {
479 Url url( url_r);
480 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
481 url.setQueryParam("iso", isofile);
482 DBG << "Url rewrite result: " << url << endl;
483 return url;
484 }
485 }
486 else
487 {
488 std::string pathname = url_r.getPathName();
489 str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
490 str::smatch what;
491 if(str::regex_match(pathname, what, e))
492 {
493 Url url( url_r);
494 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
495 url.setPathName(pathname);
496 DBG << "Url rewrite result: " << url << endl;
497 return url;
498 }
499 }
500 return url_r;
501 }
502
504 {
505 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
506 media::MediaManager manager;
507 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
508 manager.release(m->second, "");
509 }
510
511 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
512 {
513 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
514 return str;
515 }
516
518} // 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: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)