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