libzypp  17.28.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>
17 #include <zypp/ZYppCallbacks.h>
18 #include <zypp/MediaSetAccess.h>
19 #include <zypp/PathInfo.h>
20 #include <zypp/TmpPath.h>
21 //#include <zypp/source/MediaSetAccessReportReceivers.h>
22 
23 #undef ZYPP_BASE_LOGGER_LOGGROUP
24 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::fetcher"
25 
26 using std::endl;
27 
29 namespace zypp
30 {
31 
33 
35 
37  const Pathname & prefered_attach_point)
38  : _url(url)
39  , _prefAttachPoint(prefered_attach_point)
40  {}
41 
42  MediaSetAccess::MediaSetAccess(const std::string & label_r,
43  const Url &url,
44  const Pathname & prefered_attach_point)
45  : _url(url)
46  , _prefAttachPoint(prefered_attach_point)
47  , _label( label_r )
48  {}
49 
51  {
52  try
53  {
54  media::MediaManager manager;
55  for ( const auto & mm : _medias )
56  manager.close( mm.second );
57  }
58  catch(...) {} // don't let exception escape a dtor.
59  }
60 
61 
63  {
64  if (_medias.find(media_nr) != _medias.end())
65  {
66  // the media already exists, set theverifier
67  media::MediaAccessId id = _medias[media_nr];
68  media::MediaManager media_mgr;
69  media_mgr.addVerifier( id, verifier );
70  // remove any saved verifier for this media
71  _verifiers.erase(media_nr);
72  }
73  else
74  {
75  // save the verifier in the map, and set it when
76  // the media number is first attached
77  _verifiers[media_nr] = verifier;
78  }
79  }
80 
81  void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file )
82  {
83  releaseFile( on_media_file.filename(), on_media_file.medianr() );
84  }
85 
86  void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr)
87  {
88  media::MediaManager media_mgr;
90 
91  media = getMediaAccessId( media_nr);
92  DBG << "Going to release file " << file
93  << " from media number " << media_nr << endl;
94 
95  if ( ! media_mgr.isAttached(media) )
96  return; //disattached media is free
97 
98  media_mgr.releaseFile (media, file);
99  }
100 
102  bool dots, unsigned media_nr )
103  {
104  media::MediaManager media_mgr;
105  media::MediaAccessId media;
106  media = getMediaAccessId(media_nr);
107 
108  // try to attach the media
109  if ( ! media_mgr.isAttached(media) )
110  media_mgr.attach(media);
111 
112  media_mgr.dirInfo(media, retlist, dirname, dots);
113  }
114 
116  {
119  {
120  media::MediaManager media_mgr;
121  media_mgr.provideFile( media, file );
122  result = media_mgr.localPath( media, file.filename() );
123  }
124  };
125 
127  {
130  {
131  const auto &fName = file.filename();
132  media::MediaManager media_mgr;
133  media_mgr.provideDirTree( media, fName );
134  result = media_mgr.localPath( media, fName );
135  }
136  };
137 
139  {
142  {
143  const auto &fName = file.filename();
144  media::MediaManager media_mgr;
145  media_mgr.provideDir( media, fName );
146  result = media_mgr.localPath( media, fName );
147  }
148  };
149 
151  {
152  bool result;
154  : result(false)
155  {}
156 
158  {
159  const auto &fName = file.filename();
160  media::MediaManager media_mgr;
161  result = media_mgr.doesFileExist( media, fName );
162  }
163  };
164 
165  Pathname MediaSetAccess::provideFile( const OnMediaLocation &resource, ProvideFileOptions options )
166  {
168  provide( boost::ref(op), resource, options );
169  return op.result;
170  }
171 
172  Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
173  {
174  return provideFile( OnMediaLocation( resource ).setDeltafile( deltafile ), options );
175  }
176 
177  Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options )
178  {
179  return provideFile( OnMediaLocation( file, media_nr ), options );
180  }
181 
182  Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr )
183  {
184  try
185  {
186  if ( doesFileExist( file, media_nr ) )
187  return provideFile( OnMediaLocation( file, media_nr ), PROVIDE_NON_INTERACTIVE );
188  }
189  catch ( const media::MediaFileNotFoundException & excpt_r )
190  { ZYPP_CAUGHT( excpt_r ); }
191  catch ( const media::MediaForbiddenException & excpt_r )
192  { ZYPP_CAUGHT( excpt_r ); }
193  catch ( const media::MediaNotAFileException & excpt_r )
194  { ZYPP_CAUGHT( excpt_r ); }
195  return Pathname();
196  }
197 
198  ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
199  {
200  Url url(file_url);
201  Pathname path(url.getPathName());
202 
203  url.setPathName ("/");
204  MediaSetAccess access(url);
205 
207 
208  Pathname file = access.provideFile( OnMediaLocation(path, 1), options );
209 
210  //prevent the file from being deleted when MediaSetAccess gets out of scope
211  if ( filesystem::hardlinkCopy(file, tmpFile) != 0 )
212  ZYPP_THROW(Exception("Can't copy file from " + file.asString() + " to " + tmpFile->asString() ));
213 
214  return tmpFile;
215  }
216 
218  {
219  try
220  {
221  return provideFileFromUrl( file_url, PROVIDE_NON_INTERACTIVE );
222  }
223  catch ( const media::MediaFileNotFoundException & excpt_r )
224  { ZYPP_CAUGHT( excpt_r ); }
225  catch ( const media::MediaNotAFileException & excpt_r )
226  { ZYPP_CAUGHT( excpt_r ); }
227  return ManagedFile();
228  }
229 
230  bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
231  {
233  OnMediaLocation resource(file, media_nr);
234  provide( boost::ref(op), resource, PROVIDE_DEFAULT );
235  return op.result;
236  }
237 
238  void MediaSetAccess::precacheFiles(const std::vector<OnMediaLocation> &files)
239  {
240  media::MediaManager media_mgr;
241 
242  for ( const auto &resource : files ) {
243  Pathname file(resource.filename());
244  unsigned media_nr(resource.medianr());
245  media::MediaAccessId media = getMediaAccessId( media_nr );
246 
247  if ( !media_mgr.isOpen( media ) ) {
248  MIL << "Skipping precache of file " << resource.filename() << " media is not open";
249  continue;
250  }
251 
252  if ( ! media_mgr.isAttached(media) )
253  media_mgr.attach(media);
254 
255  media_mgr.precacheFiles( media, { resource } );
256  }
257  }
258 
260  const OnMediaLocation &resource,
261  ProvideFileOptions options )
262  {
263  const auto &file(resource.filename());
264  unsigned media_nr(resource.medianr());
265 
267  media::MediaManager media_mgr;
268 
269  media::MediaAccessId media;
270 
271  do
272  {
273  // get the mediaId, but don't try to attach it here
274  media = getMediaAccessId( media_nr);
275 
276  try
277  {
278  DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file
279  << " from media number " << media_nr << endl;
280  // try to attach the media
281  if ( ! media_mgr.isAttached(media) )
282  media_mgr.attach(media);
283  op(media, resource);
284  break;
285  }
286  catch ( media::MediaException & excp )
287  {
288  ZYPP_CAUGHT(excp);
290  unsigned int devindex = 0;
291  std::vector<std::string> devices;
292  media_mgr.getDetectedDevices(media, devices, devindex);
293 
294  do
295  {
296  if (user != media::MediaChangeReport::EJECT) // no use in calling this again
297  {
298  DBG << "Media couldn't provide file " << file << " , releasing." << endl;
299  try
300  {
301  media_mgr.release(media);
302  }
303  catch (const Exception & excpt_r)
304  {
305  ZYPP_CAUGHT(excpt_r);
306  MIL << "Failed to release media " << media << endl;
307  }
308  }
309 
310  // set up the reason
312 
313  if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
314  typeid(excp) == typeid( media::MediaNotAFileException ) )
315  {
317  }
318  else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
319  typeid(excp) == typeid( media::MediaNotAttachedException) )
320  {
322  }
323  else if( typeid(excp) == typeid( media::MediaTimeoutException) ||
324  typeid(excp) == typeid( media::MediaTemporaryProblemException))
325  {
327  }
328 
329  // Propagate the original error if _no_ callback receiver is connected, or
330  // non_interactive mode (for optional files) is used (except for wrong media).
332  || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) )
333  {
334  MIL << "Can't provide file. Non-Interactive mode." << endl;
335  ZYPP_RETHROW(excp);
336  }
337  else
338  {
339  // release all media before requesting another (#336881)
340  media_mgr.releaseAll();
341 
342  user = report->requestMedia (
343  _url,
344  media_nr,
345  _label,
346  reason,
347  excp.asUserHistory(),
348  devices,
349  devindex
350  );
351  }
352 
353  MIL << "ProvideFile exception caught, callback answer: " << user << endl;
354 
355  if( user == media::MediaChangeReport::ABORT )
356  {
357  DBG << "Aborting" << endl;
358  AbortRequestException aexcp("Aborting requested by user");
359  aexcp.remember(excp);
360  ZYPP_THROW(aexcp);
361  }
362  else if ( user == media::MediaChangeReport::IGNORE )
363  {
364  DBG << "Skipping" << endl;
365  SkipRequestException nexcp("User-requested skipping of a file");
366  nexcp.remember(excp);
367  ZYPP_THROW(nexcp);
368  }
369  else if ( user == media::MediaChangeReport::EJECT )
370  {
371  DBG << "Eject: try to release" << endl;
372  try
373  {
374  media_mgr.releaseAll();
375  media_mgr.release (media, devindex < devices.size() ? devices[devindex] : "");
376  }
377  catch ( const Exception & e)
378  {
379  ZYPP_CAUGHT(e);
380  }
381  }
382  else if ( user == media::MediaChangeReport::RETRY ||
384  {
385  // retry
386  DBG << "Going to try again" << endl;
387  // invalidate current media access id
388  media_mgr.close(media);
389  _medias.erase(media_nr);
390 
391  // not attaching, media set will do that for us
392  // this could generate uncaught exception (#158620)
393  break;
394  }
395  else
396  {
397  DBG << "Don't know, let's ABORT" << endl;
398  ZYPP_RETHROW ( excp );
399  }
400  } while( user == media::MediaChangeReport::EJECT );
401  }
402 
403  // retry or change URL
404  } while( true );
405  }
406 
408  bool recursive,
409  unsigned media_nr,
410  ProvideFileOptions options )
411  {
412  OnMediaLocation resource(dir, media_nr);
413  if ( recursive )
414  {
416  provide( boost::ref(op), resource, options );
417  return op.result;
418  }
420  provide( boost::ref(op), resource, options );
421  return op.result;
422  }
423 
425  {
426  if ( _medias.find( medianr ) != _medias.end() )
427  {
428  return _medias[medianr];
429  }
430 
431  Url url( medianr > 1 ? rewriteUrl( _url, medianr ) : _url );
432  media::MediaManager media_mgr;
433  media::MediaAccessId id = media_mgr.open( url, _prefAttachPoint );
434  _medias[medianr] = id;
435 
436  try
437  {
438  if ( _verifiers.find(medianr) != _verifiers.end() )
439  {
440  // a verifier is set for this media
441  // FIXME check the case where the verifier exists
442  // but we have no access id for the media
443  media_mgr.delVerifier( id );
444  media_mgr.addVerifier( id, _verifiers[medianr] );
445  // remove any saved verifier for this media
446  _verifiers.erase( medianr );
447  }
448  }
449  catch ( const Exception &e )
450  {
451  ZYPP_CAUGHT(e);
452  WAR << "Verifier not found" << endl;
453  }
454 
455  return id;
456  }
457 
458 
459  Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
460  {
461  std::string scheme = url_r.getScheme();
462  if (scheme == "cd" || scheme == "dvd")
463  return url_r;
464 
465  DBG << "Rewriting url " << url_r << endl;
466 
467  if( scheme == "iso")
468  {
469  // TODO the iso parameter will not be required in the future, this
470  // code has to be adapted together with the MediaISO change.
471  // maybe some MediaISOURL interface should be used.
472  std::string isofile = url_r.getQueryParam("iso");
473  str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase);
474 
475  str::smatch what;
476  if(str::regex_match(isofile, what, e))
477  {
478  Url url( url_r);
479  isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
480  url.setQueryParam("iso", isofile);
481  DBG << "Url rewrite result: " << url << endl;
482  return url;
483  }
484  }
485  else
486  {
487  std::string pathname = url_r.getPathName();
488  str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase);
489  str::smatch what;
490  if(str::regex_match(pathname, what, e))
491  {
492  Url url( url_r);
493  pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
494  url.setPathName(pathname);
495  DBG << "Url rewrite result: " << url << endl;
496  return url;
497  }
498  }
499  return url_r;
500  }
501 
503  {
504  DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
505  media::MediaManager manager;
506  for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
507  manager.release(m->second, "");
508  }
509 
510  std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
511  {
512  str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
513  return str;
514  }
515 
517 } // 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:96
Pathname deltafile
void provideDirTree(MediaAccessId accessId, const Pathname &dirname) const
FIXME: see MediaAccess class.
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides a file from a media location.
void setQueryParam(const std::string &param, const std::string &value)
Set or add value for the specified query parameter.
Definition: Url.cc:833
void precacheFiles(const std::vector< OnMediaLocation > &files)
Tries to fetch the given files and precaches them.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Describes a resource file located on a medium.
Regular expression.
Definition: Regex.h:94
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.
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.
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
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.
bool isOpen(MediaAccessId accessId) const
Query if the media access is open / exists.
ZYPP_DEPRECATED void provideFile(MediaAccessId accessId, const Pathname &filename, const ByteCount &expectedFileSize) const
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
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
The media number the resource is located on.
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:759
Do not differentiate case.
Definition: Regex.h:99
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
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:97
IMPL_PTR_TYPE(Application)
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:514
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:823
void addVerifier(MediaAccessId accessId, const MediaVerifierRef &verifier)
Add verifier implementation for the specified media id.
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
void precacheFiles(MediaAccessId accessId, const std::vector< OnMediaLocation > &files)
Tries to fetch the given files and precaches them.
const Pathname & filename() const
The path to the resource on the medium.
std::string numstring(char n, int w=0)
Definition: String.h:289
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).
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
Regular expression match result.
Definition: Regex.h:167
Manages access to the &#39;physical&#39; media, e.g CDROM drives, Disk volumes, directory trees...
Definition: MediaManager.h:453
Base class for Exception.
Definition: Exception.h:145
void setVerifier(unsigned media_nr, media::MediaVerifierRef verifier)
Sets a MediaVerifier verifier for given media number.
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
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)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Definition: Regex.h:70
void provide(ProvideOperation op, const OnMediaLocation &resource, ProvideFileOptions options)
bool isAttached(MediaAccessId accessId) const
Check if media is attached or not.
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 ...
void operator()(media::MediaAccessId media, const OnMediaLocation &file)
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
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.
bool optional() const
Whether this is an optional resource.
function< void(media::MediaAccessId, const OnMediaLocation &)> ProvideOperation
VerifierMap _verifiers
Mapping between media number and corespondent verifier.
Url manipulation class.
Definition: Url.h:91
void delVerifier(MediaAccessId accessId)
Remove verifier for specified media id.
void releaseFile(MediaAccessId accessId, const Pathname &filename) const
FIXME: see MediaAccess class.
unsigned int MediaNr
Definition: MediaManager.h:30
void close(MediaAccessId accessId)
Close the media access with specified id.
#define DBG
Definition: Logger.h:95
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.