libzypp  12.16.5
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 
94  void MediaSetAccess::dirInfo( filesystem::DirContent &retlist, const Pathname &dirname,
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  {
110  Pathname result;
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  {
121  Pathname result;
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  {
132  Pathname result;
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  bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
174  {
176  OnMediaLocation resource;
177  resource.setLocation(file, media_nr);
178  provide( boost::ref(op), resource, PROVIDE_DEFAULT, Pathname());
179  return op.result;
180  }
181 
183  const OnMediaLocation &resource,
184  ProvideFileOptions options,
185  const Pathname &deltafile )
186  {
187  Pathname file(resource.filename());
188  unsigned media_nr(resource.medianr());
189 
191  media::MediaManager media_mgr;
192 
193  media::MediaAccessId media;
194 
195  do
196  {
197  // get the mediaId, but don't try to attach it here
198  media = getMediaAccessId( media_nr);
199  bool deltafileset = false;
200 
201  try
202  {
203  DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
204  << " from media number " << media_nr << endl;
205  // try to attach the media
206  if ( ! media_mgr.isAttached(media) )
207  media_mgr.attach(media);
208  media_mgr.setDeltafile(media, deltafile);
209  deltafileset = true;
210  op(media, file);
211  media_mgr.setDeltafile(media, Pathname());
212  break;
213  }
214  catch ( media::MediaException & excp )
215  {
216  ZYPP_CAUGHT(excp);
217  if (deltafileset)
218  media_mgr.setDeltafile(media, Pathname());
220  unsigned int devindex = 0;
221  vector<string> devices;
222  media_mgr.getDetectedDevices(media, devices, devindex);
223 
224  do
225  {
226  if (user != media::MediaChangeReport::EJECT) // no use in calling this again
227  {
228  DBG << "Media couldn't provide file " << file << " , releasing." << endl;
229  try
230  {
231  media_mgr.release(media);
232  }
233  catch (const Exception & excpt_r)
234  {
235  ZYPP_CAUGHT(excpt_r);
236  MIL << "Failed to release media " << media << endl;
237  }
238  }
239 
240  // set up the reason
242 
243  if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
244  typeid(excp) == typeid( media::MediaNotAFileException ) )
245  {
247  }
248  else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
249  typeid(excp) == typeid( media::MediaNotAttachedException) )
250  {
252  }
253  else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
254  typeid(excp) == typeid( media::MediaTemporaryProblemException))
255  {
257  }
258 
259  // Propagate the original error if _no_ callback receiver is connected, or
260  // non_interactive mode (for optional files) is used (except for wrong media).
262  || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
263  {
264  MIL << "Can't provide file. Non-Interactive mode." << endl;
265  ZYPP_RETHROW(excp);
266  }
267  else
268  {
269  // release all media before requesting another (#336881)
270  media_mgr.releaseAll();
271 
272  user = report->requestMedia (
273  _url,
274  media_nr,
275  _label,
276  reason,
277  excp.asUserString(),
278  devices,
279  devindex
280  );
281  }
282 
283  MIL << "ProvideFile exception caught, callback answer: " << user << endl;
284 
285  if( user == media::MediaChangeReport::ABORT )
286  {
287  DBG << "Aborting" << endl;
288  AbortRequestException aexcp("Aborting requested by user");
289  aexcp.remember(excp);
290  ZYPP_THROW(aexcp);
291  }
292  else if ( user == media::MediaChangeReport::IGNORE )
293  {
294  DBG << "Skipping" << endl;
295  SkipRequestException nexcp("User-requested skipping of a file");
296  nexcp.remember(excp);
297  ZYPP_THROW(nexcp);
298  }
299  else if ( user == media::MediaChangeReport::EJECT )
300  {
301  DBG << "Eject: try to release" << endl;
302  media_mgr.releaseAll();
303  // eject
304  media_mgr.release (media,
305  devindex < devices.size() ? devices[devindex] : "");
306  }
307  else if ( user == media::MediaChangeReport::RETRY ||
309  {
310  // retry
311  DBG << "Going to try again" << endl;
312  // invalidate current media access id
313  media_mgr.close(media);
314  _medias.erase(media_nr);
315 
316  // not attaching, media set will do that for us
317  // this could generate uncaught exception (#158620)
318  break;
319  }
320  else
321  {
322  DBG << "Don't know, let's ABORT" << endl;
323  ZYPP_RETHROW ( excp );
324  }
325  } while( user == media::MediaChangeReport::EJECT );
326  }
327 
328  // retry or change URL
329  } while( true );
330  }
331 
332  Pathname MediaSetAccess::provideDir(const Pathname & dir,
333  bool recursive,
334  unsigned media_nr,
335  ProvideFileOptions options )
336  {
337  OnMediaLocation resource;
338  resource.setLocation(dir, media_nr);
339  if ( recursive )
340  {
342  provide( boost::ref(op), resource, options, Pathname());
343  return op.result;
344  }
346  provide( boost::ref(op), resource, options, Pathname());
347  return op.result;
348  }
349 
351  {
352  media::MediaManager media_mgr;
353 
354  if (_medias.find(medianr) != _medias.end())
355  {
356  media::MediaAccessId id = _medias[medianr];
357  return id;
358  }
359  Url url;
360  url = rewriteUrl (_url, medianr);
361  media::MediaAccessId id = media_mgr.open(url, _prefAttachPoint);
362  _medias[medianr] = id;
363 
364  try
365  {
366  if (_verifiers.find(medianr) != _verifiers.end())
367  {
368  // a verifier is set for this media
369  // FIXME check the case where the verifier exists
370  // but we have no access id for the media
371  media::MediaAccessId id = _medias[medianr];
372  media::MediaManager media_mgr;
373  media_mgr.delVerifier(id);
374  media_mgr.addVerifier( id, _verifiers[medianr] );
375  // remove any saved verifier for this media
376  _verifiers.erase(medianr);
377  }
378  }
379  catch ( const Exception &e )
380  {
381  ZYPP_CAUGHT(e);
382  WAR << "Verifier not found" << endl;
383  }
384 
385  return id;
386  }
387 
388 
389  Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
390  {
391  std::string scheme = url_r.getScheme();
392  if (scheme == "cd" || scheme == "dvd")
393  return url_r;
394 
395  DBG << "Rewriting url " << url_r << endl;
396 
397  if( scheme == "iso")
398  {
399  // TODO the iso parameter will not be required in the future, this
400  // code has to be adapted together with the MediaISO change.
401  // maybe some MediaISOURL interface should be used.
402  std::string isofile = url_r.getQueryParam("iso");
403  str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
404 
405  str::smatch what;
406  if(str::regex_match(isofile, what, e))
407  {
408  Url url( url_r);
409  isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
410  url.setQueryParam("iso", isofile);
411  DBG << "Url rewrite result: " << url << endl;
412  return url;
413  }
414  }
415  else
416  {
417  std::string pathname = url_r.getPathName();
418  str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
419  str::smatch what;
420  if(str::regex_match(pathname, what, e))
421  {
422  Url url( url_r);
423  pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
424  url.setPathName(pathname);
425  DBG << "Url rewrite result: " << url << endl;
426  return url;
427  }
428  }
429  return url_r;
430  }
431 
433  {
434  DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
435  media::MediaManager manager;
436  for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
437  manager.release(m->second, "");
438  }
439 
440  std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
441  {
442  str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
443  return str;
444  }
445 
447 } // namespace zypp