libzypp  15.28.6
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/source/MediaSetAccessReportReceivers.h"
20 
21 using namespace std;
22 
24 namespace zypp
25 {
26 
27 IMPL_PTR_TYPE(MediaSetAccess);
28 
30 
31  MediaSetAccess::MediaSetAccess(const Url &url,
32  const Pathname & prefered_attach_point)
33  : _url(url)
34  , _prefAttachPoint(prefered_attach_point)
35  {}
36 
37  MediaSetAccess::MediaSetAccess(const std::string & label_r,
38  const Url &url,
39  const Pathname & prefered_attach_point)
40  : _url(url)
41  , _prefAttachPoint(prefered_attach_point)
42  , _label( label_r )
43  {}
44 
46  {
47  try
48  {
49  media::MediaManager manager;
50  for ( const auto & mm : _medias )
51  manager.close( mm.second );
52  }
53  catch(...) {} // don't let exception escape a dtor.
54  }
55 
56 
58  {
59  if (_medias.find(media_nr) != _medias.end())
60  {
61  // the media already exists, set theverifier
62  media::MediaAccessId id = _medias[media_nr];
63  media::MediaManager media_mgr;
64  media_mgr.addVerifier( id, verifier );
65  // remove any saved verifier for this media
66  _verifiers.erase(media_nr);
67  }
68  else
69  {
70  // save the verifier in the map, and set it when
71  // the media number is first attached
72  _verifiers[media_nr] = verifier;
73  }
74  }
75 
76  void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file )
77  {
78  releaseFile( on_media_file.filename(), on_media_file.medianr() );
79  }
80 
81  void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
82  {
83  media::MediaManager media_mgr;
85 
86  media = getMediaAccessId( media_nr);
87  DBG << "Going to release file " << file
88  << " from media number " << media_nr << endl;
89 
90  if ( ! media_mgr.isAttached(media) )
91  return; //disattached media is free
92 
93  media_mgr.releaseFile (media, file);
94  }
95 
96  void MediaSetAccess::dirInfo( filesystem::DirContent &retlist, const Pathname &dirname,
97  bool dots, unsigned media_nr )
98  {
99  media::MediaManager media_mgr;
100  media::MediaAccessId media;
101  media = getMediaAccessId(media_nr);
102 
103  // try to attach the media
104  if ( ! media_mgr.isAttached(media) )
105  media_mgr.attach(media);
106 
107  media_mgr.dirInfo(media, retlist, dirname, dots);
108  }
109 
111  {
112  Pathname result;
114  void operator()( media::MediaAccessId media, const Pathname &file )
115  {
116  media::MediaManager media_mgr;
117  media_mgr.provideFile(media, file, expectedFileSize);
118  result = media_mgr.localPath(media, file);
119  }
120  };
121 
123  {
124  Pathname result;
125  void operator()( media::MediaAccessId media, const Pathname &file )
126  {
127  media::MediaManager media_mgr;
128  media_mgr.provideDirTree(media, file);
129  result = media_mgr.localPath(media, file);
130  }
131  };
132 
134  {
135  Pathname result;
136  void operator()( media::MediaAccessId media, const Pathname &file )
137  {
138  media::MediaManager media_mgr;
139  media_mgr.provideDir(media, file);
140  result = media_mgr.localPath(media, file);
141  }
142  };
143 
145  {
146  bool result;
148  : result(false)
149  {}
150 
151  void operator()( media::MediaAccessId media, const Pathname &file )
152  {
153  media::MediaManager media_mgr;
154  result = media_mgr.doesFileExist(media, file);
155  }
156  };
157 
158 
159 
160  Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
161  {
163  op.expectedFileSize = resource.downloadSize();
164  provide( boost::ref(op), resource, options, deltafile );
165  return op.result;
166  }
167 
168  Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options )
169  {
170  OnMediaLocation resource;
172  resource.setLocation(file, media_nr);
173  provide( boost::ref(op), resource, options, Pathname() );
174  return op.result;
175  }
176 
177  bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
178  {
180  OnMediaLocation resource;
181  resource.setLocation(file, media_nr);
182  provide( boost::ref(op), resource, PROVIDE_DEFAULT, Pathname());
183  return op.result;
184  }
185 
187  const OnMediaLocation &resource,
188  ProvideFileOptions options,
189  const Pathname &deltafile )
190  {
191  Pathname file(resource.filename());
192  unsigned media_nr(resource.medianr());
193 
195  media::MediaManager media_mgr;
196 
197  media::MediaAccessId media;
198 
199  do
200  {
201  // get the mediaId, but don't try to attach it here
202  media = getMediaAccessId( media_nr);
203  bool deltafileset = false;
204 
205  try
206  {
207  DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
208  << " from media number " << media_nr << endl;
209  // try to attach the media
210  if ( ! media_mgr.isAttached(media) )
211  media_mgr.attach(media);
212  media_mgr.setDeltafile(media, deltafile);
213  deltafileset = true;
214  op(media, file);
215  media_mgr.setDeltafile(media, Pathname());
216  break;
217  }
218  catch ( media::MediaException & excp )
219  {
220  ZYPP_CAUGHT(excp);
221  if (deltafileset)
222  media_mgr.setDeltafile(media, Pathname());
224  unsigned int devindex = 0;
225  vector<string> devices;
226  media_mgr.getDetectedDevices(media, devices, devindex);
227 
228  do
229  {
230  if (user != media::MediaChangeReport::EJECT) // no use in calling this again
231  {
232  DBG << "Media couldn't provide file " << file << " , releasing." << endl;
233  try
234  {
235  media_mgr.release(media);
236  }
237  catch (const Exception & excpt_r)
238  {
239  ZYPP_CAUGHT(excpt_r);
240  MIL << "Failed to release media " << media << endl;
241  }
242  }
243 
244  // set up the reason
246 
247  if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
248  typeid(excp) == typeid( media::MediaNotAFileException ) )
249  {
251  }
252  else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
253  typeid(excp) == typeid( media::MediaNotAttachedException) )
254  {
256  }
257  else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
258  typeid(excp) == typeid( media::MediaTemporaryProblemException))
259  {
261  }
262 
263  // Propagate the original error if _no_ callback receiver is connected, or
264  // non_interactive mode (for optional files) is used (except for wrong media).
266  || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
267  {
268  MIL << "Can't provide file. Non-Interactive mode." << endl;
269  ZYPP_RETHROW(excp);
270  }
271  else
272  {
273  // release all media before requesting another (#336881)
274  media_mgr.releaseAll();
275 
276  user = report->requestMedia (
277  _url,
278  media_nr,
279  _label,
280  reason,
281  excp.asUserString(),
282  devices,
283  devindex
284  );
285  }
286 
287  MIL << "ProvideFile exception caught, callback answer: " << user << endl;
288 
289  if( user == media::MediaChangeReport::ABORT )
290  {
291  DBG << "Aborting" << endl;
292  AbortRequestException aexcp("Aborting requested by user");
293  aexcp.remember(excp);
294  ZYPP_THROW(aexcp);
295  }
296  else if ( user == media::MediaChangeReport::IGNORE )
297  {
298  DBG << "Skipping" << endl;
299  SkipRequestException nexcp("User-requested skipping of a file");
300  nexcp.remember(excp);
301  ZYPP_THROW(nexcp);
302  }
303  else if ( user == media::MediaChangeReport::EJECT )
304  {
305  DBG << "Eject: try to release" << endl;
306  try
307  {
308  media_mgr.releaseAll();
309  media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
310  }
311  catch ( const Exception & e)
312  {
313  ZYPP_CAUGHT(e);
314  }
315  }
316  else if ( user == media::MediaChangeReport::RETRY ||
318  {
319  // retry
320  DBG << "Going to try again" << endl;
321  // invalidate current media access id
322  media_mgr.close(media);
323  _medias.erase(media_nr);
324 
325  // not attaching, media set will do that for us
326  // this could generate uncaught exception (#158620)
327  break;
328  }
329  else
330  {
331  DBG << "Don't know, let's ABORT" << endl;
332  ZYPP_RETHROW ( excp );
333  }
334  } while( user == media::MediaChangeReport::EJECT );
335  }
336 
337  // retry or change URL
338  } while( true );
339  }
340 
341  Pathname MediaSetAccess::provideDir(const Pathname & dir,
342  bool recursive,
343  unsigned media_nr,
344  ProvideFileOptions options )
345  {
346  OnMediaLocation resource;
347  resource.setLocation(dir, media_nr);
348  if ( recursive )
349  {
351  provide( boost::ref(op), resource, options, Pathname());
352  return op.result;
353  }
355  provide( boost::ref(op), resource, options, Pathname());
356  return op.result;
357  }
358 
360  {
361  media::MediaManager media_mgr;
362 
363  if (_medias.find(medianr) != _medias.end())
364  {
365  media::MediaAccessId id = _medias[medianr];
366  return id;
367  }
368  Url url;
369  url = rewriteUrl (_url, medianr);
370  media::MediaAccessId id = media_mgr.open(url, _prefAttachPoint);
371  _medias[medianr] = id;
372 
373  try
374  {
375  if (_verifiers.find(medianr) != _verifiers.end())
376  {
377  // a verifier is set for this media
378  // FIXME check the case where the verifier exists
379  // but we have no access id for the media
380  media::MediaAccessId id = _medias[medianr];
381  media::MediaManager media_mgr;
382  media_mgr.delVerifier(id);
383  media_mgr.addVerifier( id, _verifiers[medianr] );
384  // remove any saved verifier for this media
385  _verifiers.erase(medianr);
386  }
387  }
388  catch ( const Exception &e )
389  {
390  ZYPP_CAUGHT(e);
391  WAR << "Verifier not found" << endl;
392  }
393 
394  return id;
395  }
396 
397 
398  Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
399  {
400  std::string scheme = url_r.getScheme();
401  if (scheme == "cd" || scheme == "dvd")
402  return url_r;
403 
404  DBG << "Rewriting url " << url_r << endl;
405 
406  if( scheme == "iso")
407  {
408  // TODO the iso parameter will not be required in the future, this
409  // code has to be adapted together with the MediaISO change.
410  // maybe some MediaISOURL interface should be used.
411  std::string isofile = url_r.getQueryParam("iso");
412  str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
413 
414  str::smatch what;
415  if(str::regex_match(isofile, what, e))
416  {
417  Url url( url_r);
418  isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
419  url.setQueryParam("iso", isofile);
420  DBG << "Url rewrite result: " << url << endl;
421  return url;
422  }
423  }
424  else
425  {
426  std::string pathname = url_r.getPathName();
427  str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
428  str::smatch what;
429  if(str::regex_match(pathname, what, e))
430  {
431  Url url( url_r);
432  pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
433  url.setPathName(pathname);
434  DBG << "Url rewrite result: " << url << endl;
435  return url;
436  }
437  }
438  return url_r;
439  }
440 
442  {
443  DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
444  media::MediaManager manager;
445  for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
446  manager.release(m->second, "");
447  }
448 
449  std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
450  {
451  str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
452  return str;
453  }
454 
456 } // namespace zypp
void releaseFile(MediaAccessId accessId, const Pathname &filename) const
FIXME: see MediaAccess class.
#define MIL
Definition: Logger.h:64
void provideDir(MediaAccessId accessId, const Pathname &dirname) const
FIXME: see MediaAccess class.
void provide(ProvideOperation op, const OnMediaLocation &resource, ProvideFileOptions options, const Pathname &deltafile)
void setQueryParam(const std::string &param, const std::string &value)
Set or add value for the specified query parameter.
Definition: Url.cc:827
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:321
Describes a path on a certain media amongs as the information required to download it...
Regular expression.
Definition: Regex.h:86
MediaMap _medias
Mapping between media number and Media Access ID.
Url _url
Media or media set URL.
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 ...
Store and operate with byte count.
Definition: ByteCount.h:30
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:598
Pathname provideDir(const Pathname &dir, bool recursive, unsigned media_nr=1, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides direcotry dir from media number media_nr.
unsigned medianr() const
media number where the resource is located.
void setDeltafile(MediaAccessId accessId, const Pathname &filename) const
IO error which can happen on worse connection like timeout exceed.
bool doesFileExist(const Pathname &file, unsigned media_nr=1)
Checks if a file exists on the specified media, with user callbacks.
Url url
Definition: MediaCurl.cc:180
Pathname _prefAttachPoint
Prefered mount point.
void release()
Release all attached media of this set.
static Url rewriteUrl(const Url &url_r, const media::MediaNr medianr)
Replaces media number in specified url with given medianr.
void dirInfo(MediaAccessId accessId, std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
FIXME: see MediaAccess class.
virtual std::ostream & dumpOn(std::ostream &str) const
Overload to realize std::ostream & operator<<.
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
void operator()(media::MediaAccessId media, const Pathname &file)
void releaseFile(const OnMediaLocation &resource)
Release file from media.
void release(MediaAccessId accessId, const std::string &ejectDev="")
Release the attached media and optionally eject.
bool doesFileExist(MediaAccessId accessId, const Pathname &filename) const
FIXME: see MediaAccess class.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:329
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:758
Do not differentiate case.
Definition: Regex.h:91
Just inherits Exception to separate media exceptions.
void dirInfo(filesystem::DirContent &retlist, const Pathname &dirname, bool dots=true, unsigned media_nr=1)
Fills retlist with directory information.
Pathname localPath(MediaAccessId accessId, const Pathname &pathname) const
Shortcut for 'localRoot() + pathname', but returns an empty pathname if media is not attached...
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 ...
#define WAR
Definition: Logger.h:65
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
void addVerifier(MediaAccessId accessId, const MediaVerifierRef &verifier)
Add verifier implementation for the specified media id.
void operator()(media::MediaAccessId media, const Pathname &file)
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:654
std::string numstring(char n, int w=0)
Definition: String.h:304
void attach(MediaAccessId accessId)
Attach the media using the concrete handler (checks all devices).
function< void(media::MediaAccessId, const Pathname &)> ProvideOperation
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:325
Regular expression match result.
Definition: Regex.h:145
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees...
Definition: MediaManager.h:473
Base class for Exception.
Definition: Exception.h:143
void operator()(media::MediaAccessId media, const Pathname &file)
void setVerifier(unsigned media_nr, media::MediaVerifierRef verifier)
Sets a MediaVerifier verifier for given media number.
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:184
const Pathname & filename() const
The path to the resource relatve to the url and path.
MediaVerifierRef verifier
Wrapper for const correct access via Smart pointer types.
Definition: PtrTypes.h:285
media::MediaAccessId getMediaAccessId(media::MediaNr medianr)
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Definition: Regex.h:70
void provideDirTree(MediaAccessId accessId, const Pathname &dirname) const
FIXME: see MediaAccess class.
const bool optional() const
whether this is an optional resource.
bool isAttached(MediaAccessId accessId) const
Check if media is attached or not.
void operator()(media::MediaAccessId media, const Pathname &file)
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:527
void releaseAll()
Release all attached media.
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT, const Pathname &deltafile=Pathname())
Provides a file from a media location.
MediaSetAccess(const Url &url, const Pathname &prefered_attach_point="")
Creates a callback enabled media access for specified url.
const ByteCount & downloadSize() const
The size of the resource on the server.
std::string asUserString() const
Translated error message as string suitable for the user.
Definition: Exception.cc:66
MediaAccessId open(const Url &url, const Pathname &preferred_attach_point="")
Opens the media access for specified with the url.
VerifierMap _verifiers
Mapping between media number and corespondent verifier.
Url manipulation class.
Definition: Url.h:87
void delVerifier(MediaAccessId accessId)
Remove verifier for specified media id.
OnMediaLocation & setLocation(const Pathname &val_r, unsigned mediaNumber_r=1)
Set filename and media number (defaults to 1).
#define IMPL_PTR_TYPE(NAME)
unsigned int MediaNr
Definition: MediaManager.h:40
void close(MediaAccessId accessId)
Close the media access with specified id.
#define DBG
Definition: Logger.h:63
The user is not asked anything, and the error exception is just propagated.