- implement "does file exist" using curl command line in the aria backend
[platform/upstream/libzypp.git] / zypp / media / MediaAccess.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaAccess.cc
10  *
11 */
12
13 #include <ctype.h>
14
15 #include <iostream>
16
17 #include "zypp/base/Logger.h"
18 #include "zypp/ExternalProgram.h"
19
20 #include "zypp/media/MediaException.h"
21 #include "zypp/media/MediaAccess.h"
22 #include "zypp/media/MediaHandler.h"
23
24 #include "zypp/media/MediaNFS.h"
25 #include "zypp/media/MediaCD.h"
26 #include "zypp/media/MediaDIR.h"
27 #include "zypp/media/MediaDISK.h"
28 #include "zypp/media/MediaSMB.h"
29 #include "zypp/media/MediaCIFS.h"
30 #include "zypp/media/MediaCurl.h"
31 #include "zypp/media/MediaAria2c.h"
32 #include "zypp/media/MediaISO.h"
33
34 using namespace std;
35
36 namespace zypp {
37   namespace media {
38
39 ///////////////////////////////////////////////////////////////////
40 //
41 //      CLASS NAME : MediaAccess
42 //
43 ///////////////////////////////////////////////////////////////////
44
45 const Pathname MediaAccess::_noPath; // empty path
46
47 ///////////////////////////////////////////////////////////////////
48 // constructor
49 MediaAccess::MediaAccess ()
50     : _handler (0)
51 {
52 }
53
54 // destructor
55 MediaAccess::~MediaAccess()
56 {
57   try
58     {
59       close(); // !!! make sure handler gets properly deleted.
60     }
61   catch(...) {}
62 }
63
64 AttachedMedia
65 MediaAccess::attachedMedia() const
66 {
67         return _handler ? _handler->attachedMedia()
68                         : AttachedMedia();
69 }
70
71 bool
72 MediaAccess::isSharedMedia() const
73 {
74         return _handler ? _handler->isSharedMedia()
75                         : false;
76 }
77
78 void
79 MediaAccess::resetParentId()
80 {
81         if( _handler) _handler->resetParentId();
82 }
83
84 bool
85 MediaAccess::dependsOnParent() const
86 {
87         return _handler ? _handler->dependsOnParent() : false;
88 }
89
90 bool
91 MediaAccess::dependsOnParent(MediaAccessId parentId,
92                              bool exactIdMatch) const
93 {
94         return _handler ? _handler->dependsOnParent(parentId, exactIdMatch)
95                         : false;
96 }
97
98 // open URL
99 void
100 MediaAccess::open (const Url& url, const Pathname & preferred_attach_point)
101 {
102     if(!url.isValid()) {
103         MIL << "Url is not valid" << endl;
104         ZYPP_THROW(MediaBadUrlException(url));
105     }
106
107     close();
108
109     std::string scheme = url.getScheme();
110
111     MIL << "Trying scheme '" << scheme << "'" << endl;
112     /*
113     ** WARNING: Don't forget to update MediaAccess::downloads(url)
114     **          if you are adding a new url scheme / handler!
115     */
116     if (scheme == "cd" || scheme == "dvd")
117         _handler = new MediaCD (url,preferred_attach_point);
118     else if (scheme == "nfs")
119         _handler = new MediaNFS (url,preferred_attach_point);
120     else if (scheme == "iso")
121         _handler = new MediaISO (url,preferred_attach_point);
122     else if (scheme == "file" || scheme == "dir")
123         _handler = new MediaDIR (url,preferred_attach_point);
124     else if (scheme == "hd")
125         _handler = new MediaDISK (url,preferred_attach_point);
126     else if (scheme == "smb")
127         _handler = new MediaSMB (url,preferred_attach_point);
128     else if (scheme == "cifs")
129         _handler = new MediaCIFS (url,preferred_attach_point);
130     else if (scheme == "ftp" || scheme == "http" || scheme == "https")
131     {
132         // Another good idea would be activate MediaAria2c handler via external var
133         bool use_aria = true;
134         const char *ariaenv = getenv( "ZYPP_ARIA2C" );
135         // if user disabled it manually
136         if ( ariaenv && ( strcmp(ariaenv, "0" ) == 0 ) )
137         {
138             WAR << "aria2c manually disabled. Falling back to curl";
139             use_aria = false;
140         }
141         
142         // disable if it does not exist
143         if ( ! MediaAria2c::existsAria2cmd() )
144         {
145             WAR << "aria2c not found. Falling back to curl";
146             use_aria = false;
147         }
148         
149         if ( use_aria )
150             _handler = new MediaAria2c (url,preferred_attach_point);
151         else
152             _handler = new MediaCurl (url,preferred_attach_point);
153     }
154     else
155     {
156         ZYPP_THROW(MediaUnsupportedUrlSchemeException(url));
157     }
158
159     // check created handler
160     if ( !_handler ){
161       ERR << "Failed to create media handler" << endl;
162       ZYPP_THROW(MediaSystemException(url, "Failed to create media handler"));
163     }
164
165     MIL << "Opened: " << *this << endl;
166 }
167
168 // STATIC
169 bool
170 MediaAccess::downloads(const Url &url)
171 {
172     std::string scheme( url.getScheme());
173     return (scheme == "ftp" || scheme == "http" || scheme == "https");
174 }
175
176 // STATIC
177 bool
178 MediaAccess::canBeVolatile(const Url &url)
179 {
180     std::string scheme( url.getScheme());
181     return ! (scheme == "cd" || scheme == "dvd");
182 }
183
184 // Type of media if open, otherwise NONE.
185 std::string
186 MediaAccess::protocol() const
187 {
188   if ( !_handler )
189     return "unknown";
190
191   return _handler->protocol();
192 }
193
194 bool
195 MediaAccess::downloads() const
196 {
197         return _handler ? _handler->downloads() : false;
198 }
199
200 ///////////////////////////////////////////////////////////////////
201 //
202 //
203 //      METHOD NAME : MediaAccess::url
204 //      METHOD TYPE : Url
205 //
206 Url MediaAccess::url() const
207 {
208   if ( !_handler )
209     return Url();
210
211   return _handler->url();
212 }
213
214 // close handler
215 void
216 MediaAccess::close ()
217 {
218   ///////////////////////////////////////////////////////////////////
219   // !!! make shure handler gets properly deleted.
220   // I.e. release attached media before deleting the handler.
221   ///////////////////////////////////////////////////////////////////
222   if ( _handler ) {
223     try {
224       _handler->release();
225     }
226     catch (const MediaException & excpt_r)
227     {
228       ZYPP_CAUGHT(excpt_r);
229       WAR << "Close: " << *this << " (" << excpt_r << ")" << endl;
230       ZYPP_RETHROW(excpt_r);
231     }
232     MIL << "Close: " << *this << " (OK)" << endl;
233     delete _handler;
234     _handler = 0;
235   }
236 }
237
238
239 // attach media
240 void MediaAccess::attach (bool next)
241 {
242   if ( !_handler ) {
243     ZYPP_THROW(MediaNotOpenException("attach"));
244   }
245   _handler->attach(next);
246 }
247
248 // True if media is open and attached.
249 bool
250 MediaAccess::isAttached() const
251 {
252   return( _handler && _handler->isAttached() );
253 }
254
255
256 bool MediaAccess::hasMoreDevices() const
257 {
258   return _handler && _handler->hasMoreDevices();
259 }
260
261
262 void
263 MediaAccess::getDetectedDevices(std::vector<std::string> & devices,
264                                 unsigned int & index) const
265 {
266   if (_handler)
267   {
268     _handler->getDetectedDevices(devices, index);
269     return;
270   }
271
272   if (!devices.empty())
273     devices.clear();
274   index = 0;
275 }
276
277
278 // local directory that corresponds to medias url
279 // If media is not open an empty pathname.
280 Pathname
281 MediaAccess::localRoot() const
282 {
283   if ( !_handler )
284     return _noPath;
285
286   return _handler->localRoot();
287 }
288
289 // Short for 'localRoot() + pathname', but returns an empty
290 // * pathname if media is not open.
291 Pathname
292 MediaAccess::localPath( const Pathname & pathname ) const
293 {
294   if ( !_handler )
295     return _noPath;
296
297   return _handler->localPath( pathname );
298 }
299
300 void
301 MediaAccess::disconnect()
302 {
303   if ( !_handler )
304     ZYPP_THROW(MediaNotOpenException("disconnect"));
305
306   _handler->disconnect();
307 }
308
309
310 void
311 MediaAccess::release( const std::string & ejectDev )
312 {
313   if ( !_handler )
314     return;
315
316   _handler->release( ejectDev );
317 }
318
319 // provide file denoted by path to attach dir
320 //
321 // filename is interpreted relative to the attached url
322 // and a path prefix is preserved to destination
323 void
324 MediaAccess::provideFile( const Pathname & filename, bool cached, bool checkonly) const
325 {
326   if ( cached ) {
327     PathInfo pi( localPath( filename ) );
328     if ( pi.isExist() )
329       return;
330   }
331
332   if(checkonly)
333     ZYPP_THROW(MediaFileNotFoundException(url(), filename));
334
335   if ( !_handler ) {
336     ZYPP_THROW(MediaNotOpenException("provideFile(" + filename.asString() + ")"));
337   }
338
339   _handler->provideFile( filename );
340 }
341
342 void
343 MediaAccess::releaseFile( const Pathname & filename ) const
344 {
345   if ( !_handler )
346     return;
347
348   _handler->releaseFile( filename );
349 }
350
351 // provide directory tree denoted by path to attach dir
352 //
353 // dirname is interpreted relative to the attached url
354 // and a path prefix is preserved to destination
355 void
356 MediaAccess::provideDir( const Pathname & dirname ) const
357 {
358   if ( !_handler ) {
359     ZYPP_THROW(MediaNotOpenException("provideDir(" + dirname.asString() + ")"));
360   }
361
362   _handler->provideDir( dirname );
363 }
364
365 void
366 MediaAccess::provideDirTree( const Pathname & dirname ) const
367 {
368   if ( !_handler ) {
369     ZYPP_THROW(MediaNotOpenException("provideDirTree(" + dirname.asString() + ")"));
370   }
371
372   _handler->provideDirTree( dirname );
373 }
374
375 void
376 MediaAccess::releaseDir( const Pathname & dirname ) const
377 {
378   if ( !_handler )
379     return;
380
381   _handler->releaseDir( dirname );
382 }
383
384 void
385 MediaAccess::releasePath( const Pathname & pathname ) const
386 {
387   if ( !_handler )
388     return;
389
390   _handler->releasePath( pathname );
391 }
392
393 // Return content of directory on media
394 void
395 MediaAccess::dirInfo( std::list<std::string> & retlist, const Pathname & dirname, bool dots ) const
396 {
397   retlist.clear();
398
399   if ( !_handler ) {
400     ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
401   }
402
403   _handler->dirInfo( retlist, dirname, dots );
404 }
405
406 // Return content of directory on media
407 void
408 MediaAccess::dirInfo( filesystem::DirContent & retlist, const Pathname & dirname, bool dots ) const
409 {
410   retlist.clear();
411
412   if ( !_handler ) {
413     ZYPP_THROW(MediaNotOpenException("dirInfo(" + dirname.asString() + ")"));
414   }
415
416   _handler->dirInfo( retlist, dirname, dots );
417 }
418
419 // return if a file exists
420 bool
421 MediaAccess::doesFileExist( const Pathname & filename ) const
422 {
423   if ( !_handler ) {
424     ZYPP_THROW(MediaNotOpenException("doesFileExist(" + filename.asString() + ")"));
425   }
426
427   return _handler->doesFileExist( filename );
428 }
429
430 std::ostream &
431 MediaAccess::dumpOn( std::ostream & str ) const
432 {
433   if ( !_handler )
434     return str << "MediaAccess( closed )";
435
436   str << _handler->protocol() << "(" << *_handler << ")";
437   return str;
438 }
439
440 void MediaAccess::getFile( const Url &from, const Pathname &to )
441 {
442   DBG << "From: " << from << endl << "To: " << to << endl;
443
444   Pathname path = from.getPathData();
445   Pathname dir = path.dirname();
446   string base = path.basename();
447
448   Url u = from;
449   u.setPathData( dir.asString() );
450
451   MediaAccess media;
452
453   try {
454     media.open( u );
455     media.attach();
456     media._handler->provideFileCopy( base, to );
457     media.release();
458   }
459   catch (const MediaException & excpt_r)
460   {
461     ZYPP_RETHROW(excpt_r);
462   }
463 }
464
465     std::ostream & operator<<( std::ostream & str, const MediaAccess & obj )
466     { return obj.dumpOn( str ); }
467
468 ///////////////////////////////////////////////////////////////////
469   } // namespace media
470 } // namespace zypp