Imported Upstream version 17.10.1
[platform/upstream/libzypp.git] / zypp / repo / ServiceRepos.cc
1 #include <iostream>
2 #include <sstream>
3 #include "zypp/base/Logger.h"
4 #include "zypp/repo/ServiceRepos.h"
5 #include "zypp/repo/RepoException.h"
6 #include "zypp/media/MediaException.h"
7 #include "zypp/parser/RepoFileReader.h"
8 #include "zypp/media/MediaManager.h"
9 #include "zypp/parser/RepoindexFileReader.h"
10 #include "zypp/ExternalProgram.h"
11
12 using std::stringstream;
13 using std::endl;
14
15 ///////////////////////////////////////////////////////////////////
16 namespace zypp
17 {
18   ///////////////////////////////////////////////////////////////////
19   namespace repo
20   {
21     struct ServiceRepos::Impl
22     { virtual ~Impl() {} };
23
24     ///////////////////////////////////////////////////////////////////
25
26     struct RIMServiceRepos : public ServiceRepos::Impl
27     {
28       RIMServiceRepos( const Pathname & /*root_r*/,
29                        const ServiceInfo & service,
30                        const ServiceRepos::ProcessRepo & callback,
31                        const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() )
32       {
33         // repoindex.xml must be fetched always without using cookies (bnc #573897)
34         Url serviceUrl( service.url() );
35         serviceUrl.setQueryParam( "cookies", "0" );
36
37         // download the repo index file
38         media::MediaManager mediamanager;
39         media::MediaAccessId mid = mediamanager.open( serviceUrl );
40         mediamanager.attach( mid );
41         mediamanager.provideFile( mid, "repo/repoindex.xml" );
42         Pathname path = mediamanager.localPath(mid, "repo/repoindex.xml" );
43         try {
44           parser::RepoindexFileReader reader(path, callback);
45           service.setProbedTtl( reader.ttl() ); // hack! Modifying the const Service to set parsed TTL
46           mediamanager.release( mid );
47           mediamanager.close( mid );
48         } catch ( const Exception &e ) {
49           //Reader throws a bare exception, we need to translate it into something our calling
50           //code expects and handles (bnc#1116840)
51           ZYPP_CAUGHT ( e );
52           ServicePluginInformalException ex ( e.msg() );
53           ex.remember( e );
54           ZYPP_THROW( ex );
55         }
56       }
57     };
58
59     ///////////////////////////////////////////////////////////////////
60
61     struct PluginServiceRepos : public ServiceRepos::Impl
62     {
63       PluginServiceRepos( const Pathname & root_r,
64                           const ServiceInfo & service,
65                           const ServiceRepos::ProcessRepo & callback,
66                           const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() )
67       {
68         // bsc#1080693: Service script needs to be executed chrooted to the RepoManagers rootDir.
69         // The service is not aware of the rootDir, so it's explicitly passed and needs to be
70         // stripped from the URLs path.
71         stringstream buffer;
72
73         ExternalProgram::Arguments args;
74         args.reserve( 3 );
75         args.push_back( "/bin/sh" );
76         args.push_back( "-c" );
77         args.push_back( Pathname::stripprefix( root_r, service.url().getPathName() ).asString() );
78         ExternalProgramWithStderr prog( args, root_r );
79         prog >> buffer;
80
81         if ( prog.close() != 0 )
82         {
83           // ServicePluginInformalException:
84           // Ignore this error but we'd like to report it somehow...
85           std::string errbuffer;
86           prog.stderrGetUpTo( errbuffer, '\0' );
87           ERR << "Capture plugin error:[" << endl << errbuffer << endl << ']' << endl;
88           ZYPP_THROW( repo::ServicePluginInformalException( service, errbuffer ) );
89         }
90         parser::RepoFileReader parser( buffer, callback );
91       }
92     };
93
94     ///////////////////////////////////////////////////////////////////
95
96     ServiceRepos::ServiceRepos( const Pathname & root_r,
97                                 const ServiceInfo & service,
98                                 const ServiceRepos::ProcessRepo & callback,
99                                 const ProgressData::ReceiverFnc &progress )
100     : _impl( ( service.type() == ServiceType::PLUGIN )
101     ? static_cast<ServiceRepos::Impl*>( new PluginServiceRepos( root_r, service, callback, progress ) )
102     : static_cast<ServiceRepos::Impl*>( new RIMServiceRepos( root_r, service, callback, progress ) ) )
103     {}
104
105     ServiceRepos::~ServiceRepos()
106     {}
107
108   } // namespace repo
109   ///////////////////////////////////////////////////////////////////
110 } //namespace zypp
111 ///////////////////////////////////////////////////////////////////