libzypp 17.25.7
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>
16#include <zypp/ZYppCallbacks.h>
17#include <zypp/MediaSetAccess.h>
18#include <zypp/PathInfo.h>
19#include <zypp/TmpPath.h>
20//#include <zypp/source/MediaSetAccessReportReceivers.h>
21
22using std::endl;
23
25namespace zypp
26{
27
29
31
33 const Pathname & prefered_attach_point)
34 : _url(url)
35 , _prefAttachPoint(prefered_attach_point)
36 {}
37
38 MediaSetAccess::MediaSetAccess(const std::string & label_r,
39 const Url &url,
40 const Pathname & prefered_attach_point)
41 : _url(url)
42 , _prefAttachPoint(prefered_attach_point)
43 , _label( label_r )
44 {}
45
47 {
48 try
49 {
50 media::MediaManager manager;
51 for ( const auto & mm : _medias )
52 manager.close( mm.second );
53 }
54 catch(...) {} // don't let exception escape a dtor.
55 }
56
57
59 {
60 if (_medias.find(media_nr) != _medias.end())
61 {
62 // the media already exists, set theverifier
63 media::MediaAccessId id = _medias[media_nr];
64 media::MediaManager media_mgr;
65 media_mgr.addVerifier( id, verifier );
66 // remove any saved verifier for this media
67 _verifiers.erase(media_nr);
68 }
69 else
70 {
71 // save the verifier in the map, and set it when
72 // the media number is first attached
73 _verifiers[media_nr] = verifier;
74 }
75 }
76
77 void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file )
78 {
79 releaseFile( on_media_file.filename(), on_media_file.medianr() );
80 }
81
82 void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
83 {
84 media::MediaManager media_mgr;
86
87 media = getMediaAccessId( media_nr);
88 DBG << "Going to release file " << file
89 << " from media number " << media_nr << endl;
90
91 if ( ! media_mgr.isAttached(media) )
92 return; //disattached media is free
93
94 media_mgr.releaseFile (media, file);
95 }
96
98 bool dots, unsigned media_nr )
99 {
100 media::MediaManager media_mgr;
102 media = getMediaAccessId(media_nr);
103
104 // try to attach the media
105 if ( ! media_mgr.isAttached(media) )
106 media_mgr.attach(media);
107
108 media_mgr.dirInfo(media, retlist, dirname, dots);
109 }
110
112 {
115 void operator()( media::MediaAccessId media, const Pathname &file )
116 {
117 media::MediaManager media_mgr;
118 media_mgr.provideFile(media, file, expectedFileSize);
119 result = media_mgr.localPath(media, file);
120 }
121 };
122
124 {
126 void operator()( media::MediaAccessId media, const Pathname &file )
127 {
128 media::MediaManager media_mgr;
129 media_mgr.provideDirTree(media, file);
130 result = media_mgr.localPath(media, file);
131 }
132 };
133
135 {
137 void operator()( media::MediaAccessId media, const Pathname &file )
138 {
139 media::MediaManager media_mgr;
140 media_mgr.provideDir(media, file);
141 result = media_mgr.localPath(media, file);
142 }
143 };
144
146 {
147 bool result;
149 : result(false)
150 {}
151
152 void operator()( media::MediaAccessId media, const Pathname &file )
153 {
154 media::MediaManager media_mgr;
155 result = media_mgr.doesFileExist(media, file);
156 }
157 };
158
159
160
161 Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
162 {
164 op.expectedFileSize = resource.downloadSize();
165 provide( boost::ref(op), resource, options, deltafile );
166 return op.result;
167 }
168
169 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options )
170 {
171 OnMediaLocation resource;
173 resource.setLocation(file, media_nr);
174 provide( boost::ref(op), resource, options, Pathname() );
175 return op.result;
176 }
177
178 Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr )
179 {
180 try
181 {
182 if ( doesFileExist( file, media_nr ) )
183 return provideFile( file, media_nr, PROVIDE_NON_INTERACTIVE );
184 }
185 catch ( const media::MediaFileNotFoundException & excpt_r )
186 { ZYPP_CAUGHT( excpt_r ); }
187 catch ( const media::MediaNotAFileException & excpt_r )
188 { ZYPP_CAUGHT( excpt_r ); }
189 return Pathname();
190 }
191
192 ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
193 {
194 Url url(file_url);
195 Pathname path(url.getPathName());
196 url.setPathName ("/");
197 MediaSetAccess access(url);
198
200
201 Pathname file = access.provideFile(path, 1, options);
202
203 //prevent the file from being deleted when MediaSetAccess gets out of scope
204 if ( filesystem::hardlinkCopy(file, tmpFile) != 0 )
205 ZYPP_THROW(Exception("Can't copy file from " + file.asString() + " to " + tmpFile->asString() ));
206
207 return tmpFile;
208 }
209
211 {
212 try
213 {
215 }
216 catch ( const media::MediaFileNotFoundException & excpt_r )
217 { ZYPP_CAUGHT( excpt_r ); }
218 catch ( const media::MediaNotAFileException & excpt_r )
219 { ZYPP_CAUGHT( excpt_r ); }
220 return ManagedFile();
221 }
222
223 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
224 {
226 OnMediaLocation resource;
227 resource.setLocation(file, media_nr);
228 provide( boost::ref(op), resource, PROVIDE_DEFAULT, Pathname());
229 return op.result;
230 }
231
233 const OnMediaLocation &resource,
234 ProvideFileOptions options,
235 const Pathname &deltafile )
236 {
237 Pathname file(resource.filename());
238 unsigned media_nr(resource.medianr());
239
241 media::MediaManager media_mgr;
242
244
245 do
246 {
247 // get the mediaId, but don't try to attach it here
248 media = getMediaAccessId( media_nr);
249 bool deltafileset = false;
250
251 try
252 {
253 DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
254 << " from media number " << media_nr << endl;
255 // try to attach the media
256 if ( ! media_mgr.isAttached(media) )
257 media_mgr.attach(media);
258 media_mgr.setDeltafile(media, deltafile);
259 deltafileset = true;
260 op(media, file);
261 media_mgr.setDeltafile(media, Pathname());
262 break;
263 }
264 catch ( media::MediaException & excp )
265 {
266 ZYPP_CAUGHT(excp);
267 if (deltafileset)
268 media_mgr.setDeltafile(media, Pathname());
270 unsigned int devindex = 0;
271 std::vector<std::string> devices;
272 media_mgr.getDetectedDevices(media, devices, devindex);
273
274 do
275 {
276 if (user != media::MediaChangeReport::EJECT) // no use in calling this again
277 {
278 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
279 try
280 {
281 media_mgr.release(media);
282 }
283 catch (const Exception & excpt_r)
284 {
285 ZYPP_CAUGHT(excpt_r);
286 MIL << "Failed to release media " << media << endl;
287 }
288 }
289
290 // set up the reason
292
293 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
294 typeid(excp) == typeid( media::MediaNotAFileException ) )
295 {
297 }
298 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
299 typeid(excp) == typeid( media::MediaNotAttachedException) )
300 {
302 }
303 else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
304 typeid(excp) == typeid( media::MediaTemporaryProblemException))
305 {
307 }
308
309 // Propagate the original error if _no_ callback receiver is connected, or
310 // non_interactive mode (for optional files) is used (except for wrong media).
312 || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
313 {
314 MIL << "Can't provide file. Non-Interactive mode." << endl;
315 ZYPP_RETHROW(excp);
316 }
317 else
318 {
319 // release all media before requesting another (#336881)
320 media_mgr.releaseAll();
321
322 user = report->requestMedia (
323 _url,
324 media_nr,
325 _label,
326 reason,
327 excp.asUserHistory(),
328 devices,
329 devindex
330 );
331 }
332
333 MIL << "ProvideFile exception caught, callback answer: " << user << endl;
334
336 {
337 DBG << "Aborting" << endl;
338 AbortRequestException aexcp("Aborting requested by user");
339 aexcp.remember(excp);
340 ZYPP_THROW(aexcp);
341 }
342 else if ( user == media::MediaChangeReport::IGNORE )
343 {
344 DBG << "Skipping" << endl;
345 SkipRequestException nexcp("User-requested skipping of a file");
346 nexcp.remember(excp);
347 ZYPP_THROW(nexcp);
348 }
349 else if ( user == media::MediaChangeReport::EJECT )
350 {
351 DBG << "Eject: try to release" << endl;
352 try
353 {
354 media_mgr.releaseAll();
355 media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
356 }
357 catch ( const Exception & e)
358 {
359 ZYPP_CAUGHT(e);
360 }
361 }
362 else if ( user == media::MediaChangeReport::RETRY ||
364 {
365 // retry
366 DBG << "Going to try again" << endl;
367 // invalidate current media access id
368 media_mgr.close(media);
369 _medias.erase(media_nr);
370
371 // not attaching, media set will do that for us
372 // this could generate uncaught exception (#158620)
373 break;
374 }
375 else
376 {
377 DBG << "Don't know, let's ABORT" << endl;
378 ZYPP_RETHROW ( excp );
379 }
380 } while( user == media::MediaChangeReport::EJECT );
381 }
382
383 // retry or change URL
384 } while( true );
385 }
386
388 bool recursive,
389 unsigned media_nr,
390 ProvideFileOptions options )
391 {
392 OnMediaLocation resource;
393 resource.setLocation(dir, media_nr);
394 if ( recursive )
395 {
397 provide( boost::ref(op), resource, options, Pathname());
398 return op.result;
399 }
401 provide( boost::ref(op), resource, options, Pathname());
402 return op.result;
403 }
404
406 {
407 if ( _medias.find( medianr ) != _medias.end() )
408 {
409 return _medias[medianr];
410 }
411
412 Url url( medianr > 1 ? rewriteUrl( _url, medianr ) : _url );
413 media::MediaManager media_mgr;
415 _medias[medianr] = id;
416
417 try
418 {
419 if ( _verifiers.find(medianr) != _verifiers.end() )
420 {
421 // a verifier is set for this media
422 // FIXME check the case where the verifier exists
423 // but we have no access id for the media
424 media_mgr.delVerifier( id );
425 media_mgr.addVerifier( id, _verifiers[medianr] );
426 // remove any saved verifier for this media
427 _verifiers.erase( medianr );
428 }
429 }
430 catch ( const Exception &e )
431 {
432 ZYPP_CAUGHT(e);
433 WAR << "Verifier not found" << endl;
434 }
435
436 return id;
437 }
438
439
440 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
441 {
442 std::string scheme = url_r.getScheme();
443 if (scheme == "cd" || scheme == "dvd")
444 return url_r;
445
446 DBG << "Rewriting url " << url_r << endl;
447
448 if( scheme == "iso")
449 {
450 // TODO the iso parameter will not be required in the future, this
451 // code has to be adapted together with the MediaISO change.
452 // maybe some MediaISOURL interface should be used.
453 std::string isofile = url_r.getQueryParam("iso");
454 str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
455
456 str::smatch what;
457 if(str::regex_match(isofile, what, e))
458 {
459 Url url( url_r);
460 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
461 url.setQueryParam("iso", isofile);
462 DBG << "Url rewrite result: " << url << endl;
463 return url;
464 }
465 }
466 else
467 {
468 std::string pathname = url_r.getPathName();
469 str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
470 str::smatch what;
471 if(str::regex_match(pathname, what, e))
472 {
473 Url url( url_r);
474 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
475 url.setPathName(pathname);
476 DBG << "Url rewrite result: " << url << endl;
477 return url;
478 }
479 }
480 return url_r;
481 }
482
484 {
485 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
486 media::MediaManager manager;
487 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
488 manager.release(m->second, "");
489 }
490
491 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
492 {
493 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
494 return str;
495 }
496
498} // namespace zypp
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:400
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
#define DBG
Definition: Logger.h:78
#define MIL
Definition: Logger.h:79
#define WAR
Definition: Logger.h:80
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:70
Url url
Definition: MediaCurl.cc:66
MediaVerifierRef verifier
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:93
Store and operate with byte count.
Definition: ByteCount.h:31
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...
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT, const Pathname &deltafile=Pathname())
Provides a file from a media location.
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<<.
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.
function< void(media::MediaAccessId, const Pathname &)> ProvideOperation
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.
void provide(ProvideOperation op, const OnMediaLocation &resource, ProvideFileOptions options, const Pathname &deltafile)
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.
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 ByteCount & downloadSize() const
The size of the resource on the server.
const Pathname & filename() const
The path to the resource on the medium.
unsigned medianr() const
The media number the resource is located on.
OnMediaLocation & setLocation(Pathname filename_r, unsigned medianr_r=1)
Set filename_r and medianr_r (defaults to 1).
Url manipulation class.
Definition: Url.h:92
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:528
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:599
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:655
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:471
void setDeltafile(MediaAccessId accessId, const Pathname &filename) const
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).
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.
void provideFile(MediaAccessId accessId, const Pathname &filename, const ByteCount &expectedFileSize) const
Provide provide file denoted by relative path below of the 'attach point' of the specified media and ...
void release(MediaAccessId accessId, const std::string &ejectDev="")
Release the attached media and optionally eject.
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:163
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:845
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
unsigned int MediaNr
Definition: MediaManager.h:40
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
std::string numstring(char n, int w=0)
Definition: String.h:286
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 Pathname &file)
void operator()(media::MediaAccessId media, const Pathname &file)
void operator()(media::MediaAccessId media, const Pathname &file)
void operator()(media::MediaAccessId media, const Pathname &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.