libzypp 17.31.32
PluginRepoverification.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
11#include <iostream>
12#include <sstream>
13
15
16#include <zypp/Globals.h>
17#include <zypp/PathInfo.h>
18#include <zypp/ZYppCallbacks.h>
19#include <zypp/ExternalProgram.h>
20#include <zypp/base/LogTools.h>
21#include <zypp/base/WatchFile.h>
22using std::endl;
23
25namespace zypp_private
26{
27 using namespace zypp;
29 namespace repo
30 {
31
32 struct Monitor
33 {
35 using Callback = std::function<bool(std::optional<std::string>)>;
36
40
42 {
43 std::string line;
44 bool goOn = true;
45 prog_r.setBlocking( false );
46 FILE * inputfile = prog_r.inputFile();
47 do {
48 const auto &readResult = io::receiveUpto( inputfile, '\n', _timeout );
49 line += readResult.second; // we always may have received a partial line
50 goOn = true;
51 switch ( readResult.first ) {
52
53 case io::ReceiveUpToResult::Success:
55 line.clear(); // in case the CB did not move it out
56 break;
57
58 case io::ReceiveUpToResult::Timeout:
60 break;
61
62 case io::ReceiveUpToResult::Error:
63 case io::ReceiveUpToResult::EndOfFile:
65 line.clear(); // in case the CB did not move it out
66 goOn = false;
67 break;
68 }
69 } while ( goOn );
70
71 if ( prog_r.running() ) {
72 WAR << "ABORT by callback: pid " << prog_r.getpid() << endl;
73 prog_r.kill();
74 }
75 return prog_r.close();
76 }
77
78 private:
79 bool reportLine( std::string & line_r, Callback & cb_r )
80 {
81 if ( cb_r ) {
82 if ( not line_r.empty() && line_r.back() == '\n' )
83 line_r.pop_back();
84 return cb_r( std::move(line_r) );
85 }
86 return true;
87 }
89 {
90 return cb_r ? cb_r( std::nullopt ) : true;
91 }
93 {
94 if ( cb_r && not line_r.empty() ) // implies an incomplete line (no NL)
95 cb_r( std::move(line_r) );
96 return false;
97 }
98 private:
100 };
101
122
128 {
129 friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
130 friend std::ostream & dumpOn( std::ostream & str, const Impl & obj );
131
132 public:
134 {}
135
137 : _watchPlugindir { std::move(plugindir_r), WatchFile::NO_INIT }
138 , _chroot { std::move(chroot_r) }
139 {}
140
142 {}
143
144 bool isNeeded() const
145 { return _isNeeded; }
146
148 {
149 if ( _watchPlugindir.hasChanged() ) {
150 _isNeeded = false;
151 // check for at least one executable plugin inside..
153 [this]( const Pathname & dir_r, const char *const name_r ) -> bool {
155 if ( pi.isFile() && pi.userMayRX() ) {
156 this->_isNeeded = true;
157 return false;
158 }
159 return true;
160 } );
161 }
162 return _isNeeded;
163 }
164
166 {
167 // Execute the plugins. They will throw if something is wrong...
169 [&,this]( const Pathname & dir_r, const char *const name_r ) -> bool {
171 if ( pi.isFile() && pi.userMayRX() )
172 this->pluginVerify( name_r, file_r, *datap_r );
173 return true;
174 } );
175 }
176
177 private:
179 {
181 if ( not _chroot.emptyOrRoot() ) {
183 // we need to make sure the files are available inside the chroot
184 INT << "chroot PluginRepoverification does not yet work." << endl;
185 return;
186 }
187
189 args.push_back( pluginPath.asString() );
191 args.push_back( "--file" );
192 args.push_back( file_r.asString() );
193 args.push_back( "--fsig" );
194 args.push_back( data_r._sigpathLocal.asString() );
195 args.push_back( "--fkey" );
196 args.push_back( data_r._keypathLocal.asString() );
197 args.push_back( "--ralias" );
198 args.push_back( data_r._repoinfo.alias() );
200
201 // draft: maybe integrate jobReport into Monitor
202 Monitor monitor( 800 );
203 UserDataJobReport jobReport { "cmdout", "monitor" };
204 jobReport.set( "CmdId", unsigned(cmd.getpid()) );
205 jobReport.set( "CmdTag", str::numstring( cmd.getpid() ) );
206 jobReport.set( "CmdName", "Repoverification plugin "+plugin_r );
207 jobReport.set( "RepoInfo", data_r._repoinfo );
208
209 std::optional<std::ostringstream> buffer; // Send output in exception is no one is listening
210 jobReport.debug( "?" ); // someone listening?
211 if ( not jobReport.haskey( "!" ) ) // no
212 buffer = std::ostringstream();
213
214 int ret = monitor( cmd, [&jobReport,&buffer,&cmd]( std::optional<std::string> line_r )->bool {
215 if ( line_r ) {
216 DBG << "["<<cmd.getpid()<<"> " << *line_r << endl;
217 if ( buffer ) (*buffer) << *line_r << endl;
218 return jobReport.data( *line_r );
219 }
220 else {
221 return jobReport.debug( "ping" );
222 }
223 return true;
224 } );
225
226 if ( ret ) {
227 const std::string & msg { str::Format( "Metadata rejected by '%1%' plugin (returned %2%)" ) % plugin_r % ret };
228
229 ExceptionType excp { msg };
230 if ( buffer ) excp.addHistory( buffer->str() );
231 excp.addHistory( str::Format( "%1%%2% returned %3%" ) % (_chroot.emptyOrRoot()?"":"("+_chroot.asString()+")") % pluginPath % ret );
232
233 ZYPP_THROW( std::move(excp) );
234 }
235 }
236
237 const Pathname & plugindir() const
238 { return _watchPlugindir.path(); }
239
240 private:
243 bool _isNeeded = false;
244 };
245
247 inline std::ostream & operator<<( std::ostream & str, const PluginRepoverification::Impl & obj )
248 { return str << "PluginRepoverification::Impl"; }
249
251 inline std::ostream & dumpOn( std::ostream & str, const PluginRepoverification::Impl & obj )
252 { return str << obj; }
253
254
256 //
257 // CLASS NAME : PluginRepoverification
258 //
260
264
266 : _pimpl( new Impl( std::move(plugindir_r), std::move(chroot_r) ) )
267 {}
268
271
272
274 { return _pimpl->isNeeded(); }
275
277 { return _pimpl->checkIfNeeded(); }
278
282
283
284 std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj )
285 { return str << *obj._pimpl; }
286
287 std::ostream & dumpOn( std::ostream & str, const PluginRepoverification & obj )
288 { return dumpOn( str, *obj._pimpl ); }
289
291 { return lhs._pimpl == rhs._pimpl; }
292
294 //
295 // CLASS NAME : PluginRepoverification::Checker
296 //
301
304
306 { _pimpl->_parent->verifyWorkflow( file_r, _pimpl ); }
307
308
309 } // namespace repo
311} // namespace zypp
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:94
shared_ptr< Impl > _pimpl
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::vector< std::string > Arguments
What is known about a repository.
Definition RepoInfo.h:72
Remember a files attributes to detect content changes.
Definition watchfile.h:50
bool hasChanged()
Definition watchfile.h:80
const Pathname & path() const
Definition watchfile.h:65
Wrapper class for stat/lstat.
Definition PathInfo.h:221
static Pathname stripprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r with any root_r dir prefix striped.
Definition Pathname.cc:281
bool emptyOrRoot() const
Test for "" or "/".
Definition Pathname.h:121
const std::string & asString() const
String representation.
Definition Pathname.h:91
Exceptiontype thrown if a plugins verification fails.
Impl(RW_pointer< PluginRepoverification::Impl > parent_r, Pathname sigpathLocal_r, Pathname keypathLocal_r, const RepoInfo &repo_r)
FileChecker checking all repoverification plugins.
void operator()(const Pathname &file_r) const
Check the downloaded master index file.
void pluginVerify(std::string plugin_r, const Pathname &file_r, const PluginRepoverification::Checker::Impl &data_r) const
Impl(Pathname plugindir_r, Pathname chroot_r)
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
std::ostream & operator<<(std::ostream &str, const PluginRepoverification::Impl &obj)
Stream output.
void verifyWorkflow(const Pathname &file_r, RW_pointer< PluginRepoverification::Checker::Impl > datap_r) const
friend std::ostream & dumpOn(std::ostream &str, const Impl &obj)
std::ostream & dumpOn(std::ostream &str, const PluginRepoverification::Impl &obj)
Verbose stream output.
Repository metadata verification beyond GPG.
bool isNeeded() const
Whether the last checkIfNeeded found plugins to execute at all.
Checker getChecker(const Pathname &sigpathLocal_r, const Pathname &keypathLocal_r, const RepoInfo &repo_r) const
FileChecker factory remembering the location of the master index files GPG signature and key.
bool checkIfNeeded()
Checks whether there are plugins to execute at all.
RW_pointer< Impl > _pimpl
Implementation class.
Definition Arch.h:364
String related utilities and Regular expression matching.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
Definition PathInfo.cc:32
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
Definition IOTools.cc:85
static constexpr timeout_type no_timeout
Definition IOTools.h:78
size_t timeout_type
Definition IOTools.h:77
std::ostream & operator<<(std::ostream &str, const DeltaCandidates &obj)
bool operator==(const RepoType &obj1, const RepoType &obj2)
Definition RepoType.h:61
std::string numstring(char n, int w=0)
Definition String.h:289
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & dumpOn(std::ostream &str, const Capability &obj)
JobReport convenience sending this instance of UserData with each message.
Convenient building of std::string with boost::format.
Definition String.h:253
bool reportFinalLineUnlessEmpty(std::string &line_r, Callback &cb_r)
Monitor(io::timeout_type timeout_r=io::no_timeout)
int operator()(ExternalProgram &prog_r, Callback cb_r=Callback())
bool reportLine(std::string &line_r, Callback &cb_r)
std::function< bool(std::optional< std::string >)> Callback
Report a line of output (without trailing NL) otherwise a life ping on timeout.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:428
#define DBG
Definition Logger.h:95
#define WAR
Definition Logger.h:97
#define INT
Definition Logger.h:100