libzypp  11.13.5
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"
33 #include "zypp/media/MediaAria2c.h"
35 #include "zypp/media/MediaISO.h"
36 #include "zypp/media/MediaPlugin.h"
38 
39 using namespace std;
40 
41 namespace zypp {
42  namespace media {
43 
45 //
46 // CLASS NAME : MediaAccess
47 //
49 
50 const Pathname MediaAccess::_noPath; // empty path
51 
53 // constructor
54 MediaAccess::MediaAccess ()
55  : _handler (0)
56 {
57 }
58 
59 // destructor
61 {
62  try
63  {
64  close(); // !!! make sure handler gets properly deleted.
65  }
66  catch(...) {}
67 }
68 
71 {
72  return _handler ? _handler->attachedMedia()
73  : AttachedMedia();
74 }
75 
76 bool
78 {
79  return _handler ? _handler->isSharedMedia()
80  : false;
81 }
82 
83 void
85 {
87 }
88 
89 bool
91 {
92  return _handler ? _handler->dependsOnParent() : false;
93 }
94 
95 bool
97  bool exactIdMatch) const
98 {
99  return _handler ? _handler->dependsOnParent(parentId, exactIdMatch)
100  : false;
101 }
102 
103 // open URL
104 void
105 MediaAccess::open (const Url& o_url, const Pathname & preferred_attach_point)
106 {
107  if(!o_url.isValid()) {
108  MIL << "Url is not valid" << endl;
110  }
111 
112  close();
113 
114  UrlResolverPlugin::HeaderList custom_headers;
115  Url url = UrlResolverPlugin::resolveUrl(o_url, custom_headers);
116 
117  std::string scheme = url.getScheme();
118  MIL << "Trying scheme '" << scheme << "'" << endl;
119 
120  /*
121  ** WARNING: Don't forget to update MediaAccess::downloads(url)
122  ** if you are adding a new url scheme / handler!
123  */
124  if (scheme == "cd" || scheme == "dvd")
125  _handler = new MediaCD (url,preferred_attach_point);
126  else if (scheme == "nfs" || scheme == "nfs4")
127  _handler = new MediaNFS (url,preferred_attach_point);
128  else if (scheme == "iso")
129  _handler = new MediaISO (url,preferred_attach_point);
130  else if (scheme == "file" || scheme == "dir")
131  _handler = new MediaDIR (url,preferred_attach_point);
132  else if (scheme == "hd")
133  _handler = new MediaDISK (url,preferred_attach_point);
134  else if (scheme == "cifs" || scheme == "smb")
135  _handler = new MediaCIFS (url,preferred_attach_point);
136  else if (scheme == "ftp" || scheme == "tftp" || scheme == "http" || scheme == "https")
137  {
138  // Another good idea would be activate MediaAria2c handler via external var
139  bool use_aria = false;
140  bool use_multicurl = true;
141  string urlmediahandler ( url.getQueryParam("mediahandler") );
142  if ( urlmediahandler == "multicurl" )
143  {
144  use_aria = false;
145  use_multicurl = true;
146  }
147  else if ( urlmediahandler == "aria2c" )
148  {
149  use_aria = true;
150  use_multicurl = false;
151  }
152  else if ( urlmediahandler == "curl" )
153  {
154  use_aria = false;
155  use_multicurl = false;
156  }
157  else
158  {
159  if ( ! urlmediahandler.empty() )
160  {
161  WAR << "unknown mediahandler set: " << urlmediahandler << endl;
162  }
163  const char *ariaenv = getenv( "ZYPP_ARIA2C" );
164  const char *multicurlenv = getenv( "ZYPP_MULTICURL" );
165  // if user disabled it manually
166  if ( use_multicurl && multicurlenv && ( strcmp(multicurlenv, "0" ) == 0 ) )
167  {
168  WAR << "multicurl manually disabled." << endl;
169  use_multicurl = false;
170  }
171  else if ( !use_multicurl && multicurlenv && ( strcmp(multicurlenv, "1" ) == 0 ) )
172  {
173  WAR << "multicurl manually enabled." << endl;
174  use_multicurl = true;
175  }
176  // if user disabled it manually
177  if ( use_aria && ariaenv && ( strcmp(ariaenv, "0" ) == 0 ) )
178  {
179  WAR << "aria2c manually disabled. Falling back to curl" << endl;
180  use_aria = false;
181  }
182  else if ( !use_aria && ariaenv && ( strcmp(ariaenv, "1" ) == 0 ) )
183  {
184  // no aria for ftp - no advantage in that over curl
185  if ( url.getScheme() == "ftp" || url.getScheme() == "tftp" )
186  WAR << "no aria2c for FTP, despite ZYPP_ARIA2C=1" << endl;
187  else
188  {
189  WAR << "aria2c manually enabled." << endl;
190  use_aria = true;
191  }
192  }
193  }
194 
195  // disable if it does not exist
196  if ( use_aria && ! MediaAria2c::existsAria2cmd() )
197  {
198  WAR << "aria2c not found. Falling back to curl" << endl;
199  use_aria = false;
200  }
201 
202  MediaCurl *curl;
203 
204  if ( use_aria )
205  curl = new MediaAria2c (url,preferred_attach_point);
206  else if ( use_multicurl )
207  curl = new MediaMultiCurl (url,preferred_attach_point);
208  else
209  curl = new MediaCurl (url,preferred_attach_point);
210 
211  UrlResolverPlugin::HeaderList::const_iterator it;
212  for (it = custom_headers.begin();
213  it != custom_headers.end();
214  ++it) {
215  std::string header = it->first + ": " + it->second;
216  MIL << "Added custom header -> " << header << endl;
217  curl->settings().addHeader(header);
218  }
219  _handler = curl;
220  }
221  else if (scheme == "plugin" )
222  _handler = new MediaPlugin (url,preferred_attach_point);
223  else
224  {
226  }
227 
228  // check created handler
229  if ( !_handler ){
230  ERR << "Failed to create media handler" << endl;
231  ZYPP_THROW(MediaSystemException(url, "Failed to create media handler"));
232  }
233 
234  MIL << "Opened: " << *this << endl;
235 }
236 
237 // Type of media if open, otherwise NONE.
238 std::string
240 {
241  if ( !_handler )
242  return "unknown";
243 
244  return _handler->protocol();
245 }
246 
247 bool
249 {
250  return _handler ? _handler->downloads() : false;
251 }
252 
254 //
255 //
256 // METHOD NAME : MediaAccess::url
257 // METHOD TYPE : Url
258 //
260 {
261  if ( !_handler )
262  return Url();
263 
264  return _handler->url();
265 }
266 
267 // close handler
268 void
270 {
272  // !!! make shure handler gets properly deleted.
273  // I.e. release attached media before deleting the handler.
275  if ( _handler ) {
276  try {
277  _handler->release();
278  }
279  catch (const MediaException & excpt_r)
280  {
281  ZYPP_CAUGHT(excpt_r);
282  WAR << "Close: " << *this << " (" << excpt_r << ")" << endl;
283  ZYPP_RETHROW(excpt_r);
284  }
285  MIL << "Close: " << *this << " (OK)" << endl;
286  delete _handler;
287  _handler = 0;
288  }
289 }
290 
291 
292 // attach media
293 void MediaAccess::attach (bool next)
294 {
295  if ( !_handler ) {
297  }
298  _handler->attach(next);
299 }
300 
301 // True if media is open and attached.
302 bool
304 {
305  return( _handler && _handler->isAttached() );
306 }
307 
308 
310 {
311  return _handler && _handler->hasMoreDevices();
312 }
313 
314 
315 void
316 MediaAccess::getDetectedDevices(std::vector<std::string> & devices,
317  unsigned int & index) const
318 {
319  if (_handler)
320  {
321  _handler->getDetectedDevices(devices, index);
322  return;
323  }
324 
325  if (!devices.empty())
326  devices.clear();
327  index = 0;
328 }
329 
330 
331 // local directory that corresponds to medias url
332 // If media is not open an empty pathname.
333 Pathname
335 {
336  if ( !_handler )
337  return _noPath;
338 
339  return _handler->localRoot();
340 }
341 
342 // Short for 'localRoot() + pathname', but returns an empty
343 // * pathname if media is not open.
344 Pathname
345 MediaAccess::localPath( const Pathname & pathname ) const
346 {
347  if ( !_handler )
348  return _noPath;
349 
350  return _handler->localPath( pathname );
351 }
352 
353 void
355 {
356  if ( !_handler )
357  ZYPP_THROW(MediaNotOpenException("disconnect"));
358 
359  _handler->disconnect();
360 }
361 
362 
363 void
364 MediaAccess::release( const std::string & ejectDev )
365 {
366  if ( !_handler )
367  return;
368 
369  _handler->release( ejectDev );
370 }
371 
372 // provide file denoted by path to attach dir
373 //
374 // filename is interpreted relative to the attached url
375 // and a path prefix is preserved to destination
376 void
377 MediaAccess::provideFile( const Pathname & filename ) const
378 {
379  if ( !_handler ) {
380  ZYPP_THROW(MediaNotOpenException("provideFile(" + filename.asString() + ")"));
381  }
382 
383  _handler->provideFile( filename );
384 }
385 
386 void
387 MediaAccess::setDeltafile( const Pathname & filename ) const
388 {
389  if ( !_handler ) {
390  ZYPP_THROW(MediaNotOpenException("setDeltafile(" + filename.asString() + ")"));
391  }
392 
393  _handler->setDeltafile( filename );
394 }
395 
396 void
397 MediaAccess::releaseFile( const Pathname & filename ) const
398 {
399  if ( !_handler )
400  return;
401 
402  _handler->releaseFile( filename );
403 }
404 
405 // provide directory tree denoted by path to attach dir
406 //
407 // dirname is interpreted relative to the attached url
408 // and a path prefix is preserved to destination
409 void
410 MediaAccess::provideDir( const Pathname & dirname ) const
411 {
412  if ( !_handler ) {
413  ZYPP_THROW(MediaNotOpenException("provideDir(" + dirname.asString() + ")"));
414  }
415 
416  _handler->provideDir( dirname );
417 }
418 
419 void
420 MediaAccess::provideDirTree( const Pathname & dirname ) const
421 {
422  if ( !_handler ) {
423  ZYPP_THROW(MediaNotOpenException("provideDirTree(" + dirname.asString() + ")"));
424  }
425 
426  _handler->provideDirTree( dirname );
427 }
428 
429 void
430 MediaAccess::releaseDir( const Pathname & dirname ) const
431 {
432  if ( !_handler )
433  return;
434 
435  _handler->releaseDir( dirname );
436 }
437 
438 void
439 MediaAccess::releasePath( const Pathname & pathname ) const
440 {
441  if ( !_handler )
442  return;
443 
444  _handler->releasePath( pathname );
445 }
446 
447 // Return content of directory on media
448 void
449 MediaAccess::dirInfo( std::list<std::string> & retlist, const Pathname & dirname, bool dots ) const
450 {
451  retlist.clear();
452 
453  if ( !_handler ) {
454  ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
455  }
456 
457  _handler->dirInfo( retlist, dirname, dots );
458 }
459 
460 // Return content of directory on media
461 void
462 MediaAccess::dirInfo( filesystem::DirContent & retlist, const Pathname & dirname, bool dots ) const
463 {
464  retlist.clear();
465 
466  if ( !_handler ) {
467  ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
468  }
469 
470  _handler->dirInfo( retlist, dirname, dots );
471 }
472 
473 // return if a file exists
474 bool
475 MediaAccess::doesFileExist( const Pathname & filename ) const
476 {
477  if ( !_handler ) {
478  ZYPP_THROW(MediaNotOpenException("doesFileExist(" + filename.asString() + ")"));
479  }
480 
481  return _handler->doesFileExist( filename );
482 }
483 
484 std::ostream &
485 MediaAccess::dumpOn( std::ostream & str ) const
486 {
487  if ( !_handler )
488  return str << "MediaAccess( closed )";
489 
490  str << _handler->protocol() << "(" << *_handler << ")";
491  return str;
492 }
493 
494 void MediaAccess::getFile( const Url &from, const Pathname &to )
495 {
496  DBG << "From: " << from << endl << "To: " << to << endl;
497 
498  Pathname path = from.getPathData();
499  Pathname dir = path.dirname();
500  string base = path.basename();
501 
502  Url u = from;
503  u.setPathData( dir.asString() );
504 
505  MediaAccess media;
506 
507  try {
508  media.open( u );
509  media.attach();
510  media._handler->provideFileCopy( base, to );
511  media.release();
512  }
513  catch (const MediaException & excpt_r)
514  {
515  ZYPP_RETHROW(excpt_r);
516  }
517 }
518 
519  std::ostream & operator<<( std::ostream & str, const MediaAccess & obj )
520  { return obj.dumpOn( str ); }
521 
523  } // namespace media
524 } // namespace zypp