libzypp 17.31.32
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
38 : _url(url)
39 , _prefAttachPoint(prefered_attach_point)
40 {}
41
43 const Url &url,
45 : _url(url)
46 , _prefAttachPoint(prefered_attach_point)
47 , _label( label_r )
48 {}
49
51 {
52 try
53 {
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
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
78 }
79 }
80
85
86 void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
87 {
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 {
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 {
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();
133 media_mgr.provideDirTree( media, fName );
134 result = media_mgr.localPath( media, fName );
135 }
136 };
137
139 {
142 {
143 const auto &fName = file.filename();
145 media_mgr.provideDir( media, fName );
146 result = media_mgr.localPath( media, fName );
147 }
148 };
149
151 {
152 bool result;
156
158 {
159 const auto &fName = file.filename();
161 result = media_mgr.doesFileExist( media, fName );
162 }
163 };
164
166 {
168 provide( std::ref(op), resource, options );
169 return op.result;
170 }
171
173 {
174 return provideFile( OnMediaLocation( resource ).setDeltafile( deltafile ), options );
175 }
176
178 {
179 return provideFile( OnMediaLocation( file, media_nr ), options );
180 }
181
183 {
184 try
185 {
186 return provideFile( OnMediaLocation( file, media_nr ).setOptional( true ), PROVIDE_NON_INTERACTIVE );
187 }
189 { ZYPP_CAUGHT( excpt_r ); }
191 { ZYPP_CAUGHT( excpt_r ); }
192 catch ( const media::MediaNotAFileException & excpt_r )
193 { ZYPP_CAUGHT( excpt_r ); }
194 return Pathname();
195 }
196
198 {
199 Url url(file_url);
200 Pathname path(url.getPathName());
201
202 url.setPathName ("/");
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
229
230 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
231 {
234 provide( std::ref(op), resource, PROVIDE_DEFAULT );
235 return op.result;
236 }
237
238 void MediaSetAccess::precacheFiles(const std::vector<OnMediaLocation> &files)
239 {
241
242 for ( const auto &resource : files ) {
243 Pathname file(resource.filename());
244 unsigned media_nr(resource.medianr());
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
259 void MediaSetAccess::provide( ProvideOperation op,
261 ProvideFileOptions options )
262 {
263 const auto &file(resource.filename());
264 unsigned media_nr(resource.medianr());
265
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 {
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) ||
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).
319 {
320 MIL << "Can't provide file. Non-Interactive mode." << endl;
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,
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);
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);
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 {
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 );
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
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;
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
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.
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.
const Pathname & filename() const
The path to the resource on the medium.
Url manipulation class.
Definition Url.h:92
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition Url.cc:604
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,...
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
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.
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)