libzypp  17.24.1
MediaAccess.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <ctype.h>
14 
15 #include <iostream>
16 #include <map>
17 
18 #include <zypp/base/Logger.h>
19 #include <zypp/ZConfig.h>
20 #include <zypp/PluginScript.h>
21 #include <zypp/ExternalProgram.h>
22 
24 #include <zypp/media/MediaAccess.h>
26 
27 #include <zypp/media/MediaNFS.h>
28 #include <zypp/media/MediaCD.h>
29 #include <zypp/media/MediaDIR.h>
30 #include <zypp/media/MediaDISK.h>
31 #include <zypp/media/MediaCIFS.h>
32 #include <zypp/media/MediaCurl.h>
34 #include <zypp/media/MediaISO.h>
35 #include <zypp/media/MediaPlugin.h>
37 
38 using std::endl;
39 
40 namespace zypp {
41  namespace media {
42 
44 //
45 // CLASS NAME : MediaAccess
46 //
48 
49 const Pathname MediaAccess::_noPath; // empty path
50 
52 // constructor
54  : _handler (0)
55 {
56 }
57 
58 // destructor
60 {
61  try
62  {
63  close(); // !!! make sure handler gets properly deleted.
64  }
65  catch(...) {}
66 }
67 
70 {
71  return _handler ? _handler->attachedMedia()
72  : AttachedMedia();
73 }
74 
75 bool
77 {
78  return _handler ? _handler->isSharedMedia()
79  : false;
80 }
81 
82 void
84 {
86 }
87 
88 bool
90 {
91  return _handler ? _handler->dependsOnParent() : false;
92 }
93 
94 bool
96  bool exactIdMatch) const
97 {
98  return _handler ? _handler->dependsOnParent(parentId, exactIdMatch)
99  : false;
100 }
101 
102 // open URL
103 void
104 MediaAccess::open (const Url& o_url, const Pathname & preferred_attach_point)
105 {
106  if(!o_url.isValid()) {
107  MIL << "Url is not valid" << endl;
109  }
110 
111  close();
112 
113  UrlResolverPlugin::HeaderList custom_headers;
114  Url url = UrlResolverPlugin::resolveUrl(o_url, custom_headers);
115 
116  std::string scheme = url.getScheme();
117  MIL << "Trying scheme '" << scheme << "'" << endl;
118 
119  /*
120  ** WARNING: Don't forget to update MediaAccess::downloads(url)
121  ** if you are adding a new url scheme / handler!
122  */
123  if (scheme == "cd" || scheme == "dvd")
124  _handler = new MediaCD (url,preferred_attach_point);
125  else if (scheme == "nfs" || scheme == "nfs4")
126  _handler = new MediaNFS (url,preferred_attach_point);
127  else if (scheme == "iso")
128  _handler = new MediaISO (url,preferred_attach_point);
129  else if (scheme == "file" || scheme == "dir")
130  _handler = new MediaDIR (url,preferred_attach_point);
131  else if (scheme == "hd")
132  _handler = new MediaDISK (url,preferred_attach_point);
133  else if (scheme == "cifs" || scheme == "smb")
134  _handler = new MediaCIFS (url,preferred_attach_point);
135  else if (scheme == "ftp" || scheme == "tftp" || scheme == "http" || scheme == "https")
136  {
137  bool use_multicurl = true;
138  std::string urlmediahandler ( url.getQueryParam("mediahandler") );
139  if ( urlmediahandler == "multicurl" )
140  {
141  use_multicurl = true;
142  }
143  else if ( urlmediahandler == "curl" )
144  {
145  use_multicurl = false;
146  }
147  else
148  {
149  if ( ! urlmediahandler.empty() )
150  {
151  WAR << "unknown mediahandler set: " << urlmediahandler << endl;
152  }
153  const char *multicurlenv = getenv( "ZYPP_MULTICURL" );
154  // if user disabled it manually
155  if ( use_multicurl && multicurlenv && ( strcmp(multicurlenv, "0" ) == 0 ) )
156  {
157  WAR << "multicurl manually disabled." << endl;
158  use_multicurl = false;
159  }
160  else if ( !use_multicurl && multicurlenv && ( strcmp(multicurlenv, "1" ) == 0 ) )
161  {
162  WAR << "multicurl manually enabled." << endl;
163  use_multicurl = true;
164  }
165  }
166 
167  MediaCurl *curl;
168 
169  if ( use_multicurl )
170  curl = new MediaMultiCurl (url,preferred_attach_point);
171  else
172  curl = new MediaCurl (url,preferred_attach_point);
173 
174  for ( const auto & el : custom_headers ) {
175  std::string header { el.first };
176  header += ": ";
177  header += el.second;
178  MIL << "Added custom header -> " << header << endl;
179  curl->settings().addHeader( std::move(header) );
180  }
181  _handler = curl;
182  }
183  else if (scheme == "plugin" )
184  _handler = new MediaPlugin (url,preferred_attach_point);
185  else
186  {
188  }
189 
190  // check created handler
191  if ( !_handler ){
192  ERR << "Failed to create media handler" << endl;
193  ZYPP_THROW(MediaSystemException(url, "Failed to create media handler"));
194  }
195 
196  MIL << "Opened: " << *this << endl;
197 }
198 
199 // Type of media if open, otherwise NONE.
200 std::string
202 {
203  if ( !_handler )
204  return "unknown";
205 
206  return _handler->protocol();
207 }
208 
209 bool
211 {
212  return _handler ? _handler->downloads() : false;
213 }
214 
216 //
217 //
218 // METHOD NAME : MediaAccess::url
219 // METHOD TYPE : Url
220 //
222 {
223  if ( !_handler )
224  return Url();
225 
226  return _handler->url();
227 }
228 
229 // close handler
230 void
232 {
234  // !!! make shure handler gets properly deleted.
235  // I.e. release attached media before deleting the handler.
237  if ( _handler ) {
238  try {
239  _handler->release();
240  }
241  catch (const MediaException & excpt_r)
242  {
243  ZYPP_CAUGHT(excpt_r);
244  WAR << "Close: " << *this << " (" << excpt_r << ")" << endl;
245  ZYPP_RETHROW(excpt_r);
246  }
247  MIL << "Close: " << *this << " (OK)" << endl;
248  delete _handler;
249  _handler = 0;
250  }
251 }
252 
253 
254 // attach media
255 void MediaAccess::attach (bool next)
256 {
257  if ( !_handler ) {
259  }
260  _handler->attach(next);
261 }
262 
263 // True if media is open and attached.
264 bool
266 {
267  return( _handler && _handler->isAttached() );
268 }
269 
270 
272 {
273  return _handler && _handler->hasMoreDevices();
274 }
275 
276 
277 void
278 MediaAccess::getDetectedDevices(std::vector<std::string> & devices,
279  unsigned int & index) const
280 {
281  if (_handler)
282  {
283  _handler->getDetectedDevices(devices, index);
284  return;
285  }
286 
287  if (!devices.empty())
288  devices.clear();
289  index = 0;
290 }
291 
292 
293 // local directory that corresponds to medias url
294 // If media is not open an empty pathname.
295 Pathname
297 {
298  if ( !_handler )
299  return _noPath;
300 
301  return _handler->localRoot();
302 }
303 
304 // Short for 'localRoot() + pathname', but returns an empty
305 // * pathname if media is not open.
306 Pathname
307 MediaAccess::localPath( const Pathname & pathname ) const
308 {
309  if ( !_handler )
310  return _noPath;
311 
312  return _handler->localPath( pathname );
313 }
314 
315 void
317 {
318  if ( !_handler )
319  ZYPP_THROW(MediaNotOpenException("disconnect"));
320 
321  _handler->disconnect();
322 }
323 
324 
325 void
326 MediaAccess::release( const std::string & ejectDev )
327 {
328  if ( !_handler )
329  return;
330 
331  _handler->release( ejectDev );
332 }
333 
334 // provide file denoted by path to attach dir
335 //
336 // filename is interpreted relative to the attached url
337 // and a path prefix is preserved to destination
338 void
339 MediaAccess::provideFile(const Pathname & filename , const ByteCount &expectedFileSize) const
340 {
341  if ( !_handler ) {
342  ZYPP_THROW(MediaNotOpenException("provideFile(" + filename.asString() + ")"));
343  }
344 
345  _handler->provideFile( filename, expectedFileSize );
346 }
347 
348 void
349 MediaAccess::setDeltafile( const Pathname & filename ) const
350 {
351  if ( !_handler ) {
352  ZYPP_THROW(MediaNotOpenException("setDeltafile(" + filename.asString() + ")"));
353  }
354 
355  _handler->setDeltafile( filename );
356 }
357 
358 void
359 MediaAccess::releaseFile( const Pathname & filename ) const
360 {
361  if ( !_handler )
362  return;
363 
364  _handler->releaseFile( filename );
365 }
366 
367 // provide directory tree denoted by path to attach dir
368 //
369 // dirname is interpreted relative to the attached url
370 // and a path prefix is preserved to destination
371 void
372 MediaAccess::provideDir( const Pathname & dirname ) const
373 {
374  if ( !_handler ) {
375  ZYPP_THROW(MediaNotOpenException("provideDir(" + dirname.asString() + ")"));
376  }
377 
378  _handler->provideDir( dirname );
379 }
380 
381 void
382 MediaAccess::provideDirTree( const Pathname & dirname ) const
383 {
384  if ( !_handler ) {
385  ZYPP_THROW(MediaNotOpenException("provideDirTree(" + dirname.asString() + ")"));
386  }
387 
388  _handler->provideDirTree( dirname );
389 }
390 
391 void
392 MediaAccess::releaseDir( const Pathname & dirname ) const
393 {
394  if ( !_handler )
395  return;
396 
397  _handler->releaseDir( dirname );
398 }
399 
400 void
401 MediaAccess::releasePath( const Pathname & pathname ) const
402 {
403  if ( !_handler )
404  return;
405 
406  _handler->releasePath( pathname );
407 }
408 
409 // Return content of directory on media
410 void
411 MediaAccess::dirInfo( std::list<std::string> & retlist, const Pathname & dirname, bool dots ) const
412 {
413  retlist.clear();
414 
415  if ( !_handler ) {
416  ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
417  }
418 
419  _handler->dirInfo( retlist, dirname, dots );
420 }
421 
422 // Return content of directory on media
423 void
424 MediaAccess::dirInfo( filesystem::DirContent & retlist, const Pathname & dirname, bool dots ) const
425 {
426  retlist.clear();
427 
428  if ( !_handler ) {
429  ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
430  }
431 
432  _handler->dirInfo( retlist, dirname, dots );
433 }
434 
435 // return if a file exists
436 bool
437 MediaAccess::doesFileExist( const Pathname & filename ) const
438 {
439  if ( !_handler ) {
440  ZYPP_THROW(MediaNotOpenException("doesFileExist(" + filename.asString() + ")"));
441  }
442 
443  return _handler->doesFileExist( filename );
444 }
445 
446 std::ostream &
447 MediaAccess::dumpOn( std::ostream & str ) const
448 {
449  if ( !_handler )
450  return str << "MediaAccess( closed )";
451 
452  str << _handler->protocol() << "(" << *_handler << ")";
453  return str;
454 }
455 
456 void MediaAccess::getFile( const Url &from, const Pathname &to )
457 {
458  DBG << "From: " << from << endl << "To: " << to << endl;
459 
460  Pathname path = from.getPathData();
461  Pathname dir = path.dirname();
462  std::string base = path.basename();
463 
464  Url u = from;
465  u.setPathData( dir.asString() );
466 
467  MediaAccess media;
468 
469  try {
470  media.open( u );
471  media.attach();
472  media._handler->provideFileCopy( base, to, 0 );
473  media.release();
474  }
475  catch (const MediaException & excpt_r)
476  {
477  ZYPP_RETHROW(excpt_r);
478  }
479 }
480 
481  std::ostream & operator<<( std::ostream & str, const MediaAccess & obj )
482  { return obj.dumpOn( str ); }
483 
485  } // namespace media
486 } // namespace zypp
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:528
MediaAccess()
constructor
Definition: MediaAccess.cc:53
Implementation class for NFS MediaHandler.
Definition: MediaNFS.h:36
void resetParentId()
Called in case, where the media manager takes over the destruction of the parent id (e...
#define MIL
Definition: Logger.h:79
void open(const Url &url, const Pathname &preferred_attach_point="")
open url.
Definition: MediaAccess.cc:104
void close()
close url
Definition: MediaAccess.cc:231
Pathname localRoot() const
Return the local directory that corresponds to medias url, no matter if media isAttached or not...
Definition: MediaAccess.cc:296
void provideDirTree(const Pathname &dirname) const
Use concrete handler to provide directory tree denoted by path below &#39;attach point&#39; (recursive!!)...
Definition: MediaAccess.cc:382
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Implementation class for CD/DVD MediaHandler.
Definition: MediaCD.h:28
Implementation class for FTP, HTTP and HTTPS MediaHandler.
Definition: MediaCurl.h:32
Handle access to a medium.
Definition: MediaAccess.h:50
void setDeltafile(const Pathname &filename) const
set a deltafile to be used in the next download
Definition: MediaAccess.cc:349
std::string protocol() const
Used Protocol if media is opened, otherwise &#39;unknown&#39;.
Definition: MediaAccess.cc:201
AttachedMedia attachedMedia() const
Returns the attached media.
Store and operate with byte count.
Definition: ByteCount.h:30
static Url resolveUrl(const Url &url, HeaderList &headers)
Resolves an url using the installed plugins If no plugin is found the url is resolved as its current ...
std::string protocol() const
Protocol hint for MediaAccess.
Definition: MediaHandler.h:502
void disconnect()
Use concrete handler to disconnect the media.
Definition: MediaAccess.cc:316
Pathname localPath(const Pathname &pathname) const
Short for &#39;localRoot() + pathname&#39;, but returns an empty pathname if media is not open...
Definition: MediaAccess.cc:307
void release(const std::string &ejectDev="")
Use concrete handler to release the media.
Definition: MediaAccess.cc:326
bool isSharedMedia() const
Definition: MediaAccess.cc:76
void dirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Return content of directory on media via retlist.
Url url() const
Url if media is opened, otherwise empty.
Definition: MediaAccess.cc:221
String related utilities and Regular expression matching.
Implementation class for DISK MediaHandler.
Definition: MediaDISK.h:27
void provideDir(Pathname dirname) const
Use concrete handler to provide directory denoted by path below &#39;localRoot&#39; (not recursive!).
void releasePath(Pathname pathname) const
Remove pathname below localRoot IFF handler downloads files to the local filesystem.
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
void setDeltafile(const Pathname &filename=Pathname()) const
bool doesFileExist(const Pathname &filename) const
check if a file exists
#define ERR
Definition: Logger.h:81
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
void provideFile(const Pathname &filename, const ByteCount &expectedFileSize) const
Use concrete handler to provide file denoted by path below &#39;attach point&#39;.
Definition: MediaAccess.cc:339
Pathname localPath(const Pathname &pathname) const
Files provided will be available at &#39;localPath(filename)&#39;.
std::ostream & operator<<(std::ostream &str, const MediaAccess &obj)
Definition: MediaAccess.cc:481
MediaHandler * _handler
handler for &#39;physical&#39; media == 0 if not open
Definition: MediaAccess.h:64
bool hasMoreDevices() const
Definition: MediaAccess.cc:271
void provideDir(const Pathname &dirname) const
Use concrete handler to provide directory denoted by path below &#39;attach point&#39; (not recursive!)...
Definition: MediaAccess.cc:372
void releaseDir(const Pathname &dirname) const
Remove directory tree below localRoot IFF handler downloads files to the local filesystem.
Definition: MediaHandler.h:627
virtual std::ostream & dumpOn(std::ostream &str) const
Overload to realize std::ostream & operator<<.
Definition: MediaAccess.cc:447
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:400
std::string getPathData() const
Returns the encoded path component of the URL.
Definition: Url.cc:543
Implementation class for CIFS MediaHandler.
Definition: MediaCIFS.h:32
void provideDirTree(Pathname dirname) const
Use concrete handler to provide directory tree denoted by path below &#39;localRoot&#39; (recursive!!).
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
Implementation class for DIR MediaHandler.
Definition: MediaDIR.h:28
A simple structure containing references to a media source and its attach point.
Definition: MediaSource.h:133
virtual ~MediaAccess()
Destructor.
Definition: MediaAccess.cc:59
const std::string & asString() const
String representation.
Definition: Pathname.h:91
Just inherits Exception to separate media exceptions.
void disconnect()
Use concrete handler to isconnect media.
void attach(bool next)
Use concrete handler to attach the media.
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
bool isSharedMedia() const
Returns a hint if the media is shared or not.
#define WAR
Definition: Logger.h:80
void setPathData(const std::string &pathdata)
Set the path data component in the URL.
Definition: Url.cc:701
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
bool downloads() const
Hint if files are downloaded or not.
Definition: MediaAccess.cc:210
void releaseDir(const Pathname &dirname) const
Remove directory tree below attach point IFF handler downloads files to the local filesystem...
Definition: MediaAccess.cc:392
void attach(bool next=false)
Use concrete handler to attach the media.
Definition: MediaAccess.cc:255
static const Pathname _noPath
Definition: MediaAccess.h:58
virtual bool hasMoreDevices()
Check if the media has one more device available for attach(true).
bool isValid() const
Verifies the Url.
Definition: Url.cc:484
void releaseFile(const Pathname &filename) const
Remove filename below attach point IFF handler downloads files to the local filesystem.
Definition: MediaAccess.cc:359
void provideFile(Pathname filename, const ByteCount &expectedFileSize_r) const
Use concrete handler to provide file denoted by path below &#39;localRoot&#39;.
bool doesFileExist(const Pathname &filename) const
check if a file exists
Definition: MediaAccess.cc:437
Pathname localRoot() const
Return the local directory that corresponds to medias url, no matter if media isAttached or not...
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
void releaseFile(const Pathname &filename) const
Remove filename below localRoot IFF handler downloads files to the local filesystem.
Definition: MediaHandler.h:618
bool downloads() const
Hint if files are downloaded or not.
Definition: MediaHandler.h:497
bool dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
Check if the current media handler depends on an another handler specified by media access id...
bool isAttached() const
True if media is attached.
Definition: MediaAccess.cc:265
Url url() const
Url used.
Definition: MediaHandler.h:507
virtual void getDetectedDevices(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 ...
CURL * curl
Definition: MediaCurl.cc:65
void releasePath(const Pathname &pathname) const
Remove pathname below attach point IFF handler downloads files to the local filesystem.
Definition: MediaAccess.cc:401
std::multimap< std::string, std::string > HeaderList
Implementation class for plugin MediaHandler.
Definition: MediaPlugin.h:29
AttachedMedia attachedMedia() const
Definition: MediaAccess.cc:69
virtual void getDetectedDevices(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 ...
Definition: MediaAccess.cc:278
virtual bool isAttached() const
True if media is attached.
Definition: MediaHandler.h:524
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
void release(const std::string &ejectDev="")
Use concrete handler to release the media.
bool dependsOnParent() const
Definition: MediaAccess.cc:89
Implementation class for ISO MediaHandler.
Definition: MediaISO.h:35
void dirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Return content of directory on media via retlist.
Definition: MediaAccess.cc:411
Url manipulation class.
Definition: Url.h:87
#define DBG
Definition: Logger.h:78
void getFile(const Url &from, const Pathname &to)
Get file from location at specified by URL and copy it to destination.
Definition: MediaAccess.cc:456
void provideFileCopy(Pathname srcFilename, Pathname targetFilename, const ByteCount &expectedFileSize_r) const
Call concrete handler to provide a copy of a file under a different place in the file system (usually...