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