libzypp 17.25.10
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
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:400
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
#define DBG
Definition: Logger.h:90
#define MIL
Definition: Logger.h:91
#define ERR
Definition: Logger.h:93
#define WAR
Definition: Logger.h:92
CURL * curl
Definition: MediaCurl.cc:65
Store and operate with byte count.
Definition: ByteCount.h:31
Url manipulation class.
Definition: Url.h:92
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:528
std::string getPathData() const
Returns the encoded path component of the URL.
Definition: Url.cc:543
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
void setPathData(const std::string &pathdata)
Set the path data component in the URL.
Definition: Url.cc:701
bool isValid() const
Verifies the Url.
Definition: Url.cc:484
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
const std::string & asString() const
String representation.
Definition: Pathname.h:91
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
Handle access to a medium.
Definition: MediaAccess.h:51
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
Pathname localPath(const Pathname &pathname) const
Short for 'localRoot() + pathname', but returns an empty pathname if media is not open.
Definition: MediaAccess.cc:307
void releaseFile(const Pathname &filename) const
Remove filename below attach point IFF handler downloads files to the local filesystem.
Definition: MediaAccess.cc:359
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
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 releasePath(const Pathname &pathname) const
Remove pathname below attach point IFF handler downloads files to the local filesystem.
Definition: MediaAccess.cc:401
bool dependsOnParent() const
Definition: MediaAccess.cc:89
void open(const Url &url, const Pathname &preferred_attach_point="")
open url.
Definition: MediaAccess.cc:104
virtual ~MediaAccess()
Destructor.
Definition: MediaAccess.cc:59
void release(const std::string &ejectDev="")
Use concrete handler to release the media.
Definition: MediaAccess.cc:326
static const Pathname _noPath
Definition: MediaAccess.h:58
void provideFile(const Pathname &filename, const ByteCount &expectedFileSize) const
Use concrete handler to provide file denoted by path below 'attach point'.
Definition: MediaAccess.cc:339
void disconnect()
Use concrete handler to disconnect the media.
Definition: MediaAccess.cc:316
void provideDir(const Pathname &dirname) const
Use concrete handler to provide directory denoted by path below 'attach point' (not recursive!...
Definition: MediaAccess.cc:372
void close()
close url
Definition: MediaAccess.cc:231
bool doesFileExist(const Pathname &filename) const
check if a file exists
Definition: MediaAccess.cc:437
void provideDirTree(const Pathname &dirname) const
Use concrete handler to provide directory tree denoted by path below 'attach point' (recursive!...
Definition: MediaAccess.cc:382
void attach(bool next=false)
Use concrete handler to attach the media.
Definition: MediaAccess.cc:255
AttachedMedia attachedMedia() const
Definition: MediaAccess.cc:69
MediaHandler * _handler
handler for 'physical' media == 0 if not open
Definition: MediaAccess.h:64
bool hasMoreDevices() const
Definition: MediaAccess.cc:271
bool isSharedMedia() const
Definition: MediaAccess.cc:76
virtual std::ostream & dumpOn(std::ostream &str) const
Overload to realize std::ostream & operator<<.
Definition: MediaAccess.cc:447
std::string protocol() const
Used Protocol if media is opened, otherwise 'unknown'.
Definition: MediaAccess.cc:201
void setDeltafile(const Pathname &filename) const
set a deltafile to be used in the next download
Definition: MediaAccess.cc:349
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
Pathname localRoot() const
Return the local directory that corresponds to medias url, no matter if media isAttached or not.
Definition: MediaAccess.cc:296
bool isAttached() const
True if media is attached.
Definition: MediaAccess.cc:265
MediaAccess()
constructor
Definition: MediaAccess.cc:53
Url url() const
Url if media is opened, otherwise empty.
Definition: MediaAccess.cc:221
Implementation class for CD/DVD MediaHandler.
Definition: MediaCD.h:28
Implementation class for CIFS MediaHandler.
Definition: MediaCIFS.h:32
Implementation class for FTP, HTTP and HTTPS MediaHandler.
Definition: MediaCurl.h:33
Implementation class for DIR MediaHandler.
Definition: MediaDIR.h:28
Implementation class for DISK MediaHandler.
Definition: MediaDISK.h:27
Just inherits Exception to separate media exceptions.
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 ...
void provideDirTree(Pathname dirname) const
Use concrete handler to provide directory tree denoted by path below 'localRoot' (recursive!...
void disconnect()
Use concrete handler to isconnect media.
void attach(bool next)
Use concrete handler to attach the media.
void resetParentId()
Called in case, where the media manager takes over the destruction of the parent id (e....
virtual bool isAttached() const
True if media is attached.
Definition: MediaHandler.h:524
virtual bool hasMoreDevices()
Check if the media has one more device available for attach(true).
bool downloads() const
Hint if files are downloaded or not.
Definition: MediaHandler.h:497
void dirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Return content of directory on media via retlist.
void releaseDir(const Pathname &dirname) const
Remove directory tree below localRoot IFF handler downloads files to the local filesystem.
Definition: MediaHandler.h:627
bool doesFileExist(const Pathname &filename) const
check if a file exists
void releasePath(Pathname pathname) const
Remove pathname below localRoot IFF handler downloads files to the local filesystem.
bool dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
Check if the current media handler depends on an another handler specified by media access id.
Pathname localPath(const Pathname &pathname) const
Files provided will be available at 'localPath(filename)'.
std::string protocol() const
Protocol hint for MediaAccess.
Definition: MediaHandler.h:502
void release(const std::string &ejectDev="")
Use concrete handler to release the media.
void releaseFile(const Pathname &filename) const
Remove filename below localRoot IFF handler downloads files to the local filesystem.
Definition: MediaHandler.h:618
Pathname localRoot() const
Return the local directory that corresponds to medias url, no matter if media isAttached or not.
void provideDir(Pathname dirname) const
Use concrete handler to provide directory denoted by path below 'localRoot' (not recursive!...
void setDeltafile(const Pathname &filename=Pathname()) const
bool isSharedMedia() const
Returns a hint if the media is shared or not.
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...
void provideFile(Pathname filename, const ByteCount &expectedFileSize_r) const
Use concrete handler to provide file denoted by path below 'localRoot'.
AttachedMedia attachedMedia() const
Returns the attached media.
Implementation class for ISO MediaHandler.
Definition: MediaISO.h:36
Implementation class for NFS MediaHandler.
Definition: MediaNFS.h:36
Implementation class for plugin MediaHandler.
Definition: MediaPlugin.h:30
std::multimap< std::string, std::string > HeaderList
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 ...
String related utilities and Regular expression matching.
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
std::ostream & operator<<(std::ostream &str, const MediaAccess &obj)
Definition: MediaAccess.cc:481
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
A simple structure containing references to a media source and its attach point.
Definition: MediaSource.h:134