libzypp: zypp/repo/PluginRepoverification.cc Source File

libzypp 17.38.14

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#include <utility>
14
15#include "PluginRepoverification.h"
16
17#include <zypp-core/Globals.h>
18#include <zypp/PathInfo.h>
19#include <zypp/ZYppCallbacks.h>
20#include <zypp-core/ExternalProgram.h>
21#include <zypp-core/base/LogTools.h>
22#include <zypp-core/fs/WatchFile>
23using std::endl;
24
26 namespace zypp_private
27{
28 using namespace zypp;
30 namespace repo
31 {
32
33 struct Monitor
34 {
36 using Callback = std::function<bool(std::optional<std::string>)>;
37
38 Monitor( io::timeout_type timeout_r = io::no_timeout )
39 : _timeout { timeout_r }
40 {}
41
42 int operator()( ExternalProgram & prog_r, Callback cb_r = Callback() )
43 {
44 std::string line;
45 bool goOn = true;
46 prog_r.setBlocking( false );
47 FILE * inputfile = prog_r.inputFile();
48 do {
49 const auto &readResult = io::receiveUpto( inputfile, '\n', _timeout );
50 line += readResult.second; // we always may have received a partial line
51 goOn = true;
52 switch ( readResult.first ) {
53
54 case io::ReceiveUpToResult::Success:
55 goOn = reportLine( line, cb_r );
56 line.clear(); // in case the CB did not move it out
57 break;
58
59 case io::ReceiveUpToResult::Timeout:
60 goOn = reportTimeout( cb_r );
61 break;
62
63 case io::ReceiveUpToResult::Error:
64 case io::ReceiveUpToResult::EndOfFile:
65 reportFinalLineUnlessEmpty( line, cb_r );
66 line.clear(); // in case the CB did not move it out
67 goOn = false;
68 break;
69 }
70 } while ( goOn );
71
72 if ( prog_r.running() ) {
73 WAR << "ABORT by callback: pid " << prog_r.getpid() << endl;
74 prog_r.kill();
75 }
76 return prog_r.close();
77 }
78
79 private:
80 bool reportLine( std::string & line_r, Callback & cb_r )
81 {
82 if ( cb_r ) {
83 if ( not line_r.empty() && line_r.back() == '\n' )
84 line_r.pop_back();
85 return cb_r( std::move(line_r) );
86 }
87 return true;
88 }
89 bool reportTimeout( Callback & cb_r )
90 {
91 return cb_r ? cb_r( std::nullopt ) : true;
92 }
93 bool reportFinalLineUnlessEmpty( std::string & line_r, Callback & cb_r )
94 {
95 if ( cb_r && not line_r.empty() ) // implies an incomplete line (no NL)
96 cb_r( std::move(line_r) );
97 return false;
98 }
99 private:
100 io::timeout_type _timeout = io::no_timeout;
101 };
102
107 class PluginRepoverification::Checker::Impl
108 {
109 public:
110 Impl( RW_pointer<PluginRepoverification::Impl> parent_r,
111 Pathname &&sigpathLocal_r, Pathname &&keypathLocal_r, RepoInfo &&repo_r )
112 : _parent { std::move( parent_r ) }
113 , _sigpathLocal { std::move(sigpathLocal_r) }
114 , _keypathLocal { std::move(keypathLocal_r) }
115 , _repoinfo { std::move(repo_r) }
116 {}
117
118 RW_pointer<PluginRepoverification::Impl> _parent;
119 Pathname _sigpathLocal;
120 Pathname _keypathLocal;
121 RepoInfo _repoinfo;
122 };
123
128 class PluginRepoverification::Impl
129 {
130 friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
131 friend std::ostream & dumpOn( std::ostream & str, const Impl & obj );
132
133 public:
134 Impl()
135 {}
136
137 Impl(const Impl &) = delete;
138 Impl(Impl &&) = delete;
139 Impl &operator=(const Impl &) = delete;
140 Impl &operator=(Impl &&) = delete;
141
142 Impl(Pathname &&plugindir_r, Pathname &&chroot_r)
143 : _watchPlugindir{std::move(plugindir_r), WatchFile::NO_INIT},
144 _chroot{std::move(chroot_r)} {}
145
146 ~Impl()
147 {}
148
149 bool isNeeded() const
150 { return _isNeeded; }
151
152 bool checkIfNeeded()
153 {
154 if ( _watchPlugindir.hasChanged() ) {
155 _isNeeded = false;
156 // check for at least one executable plugin inside..
157 filesystem::dirForEach( plugindir(),
158 [this]( const Pathname & dir_r, const char *const name_r ) -> bool {
159 PathInfo pi ( dir_r/name_r );
160 if ( pi.isFile() && pi.userMayRX() ) {
161 this->_isNeeded = true;
162 return false;
163 }
164 return true;
165 } );
166 }
167 return _isNeeded;
168 }
169
170 void verifyWorkflow( const Pathname & file_r, RW_pointer<PluginRepoverification::Checker::Impl> datap_r ) const
171 {
172 // Execute the plugins. They will throw if something is wrong...
173 filesystem::dirForEach( plugindir(),
174 [&,this]( const Pathname & dir_r, const char *const name_r ) -> bool {
175 PathInfo pi ( dir_r/name_r );
176 if ( pi.isFile() && pi.userMayRX() )
177 this->pluginVerify( name_r, file_r, *datap_r );
178 return true;
179 } );
180 }
181
182 private:
183 void pluginVerify( std::string plugin_r, const Pathname & file_r, const PluginRepoverification::Checker::Impl & data_r ) const
184 {
185 Pathname pluginPath { plugindir()/plugin_r };
186 if ( not _chroot.emptyOrRoot() ) {
187 pluginPath = Pathname::stripprefix( _chroot, pluginPath );
188 // we need to make sure the files are available inside the chroot
189 INT << "chroot PluginRepoverification does not yet work." << endl;
190 return;
191 }
192
193 ExternalProgram::Arguments args;
194 args.push_back( pluginPath.asString() );
196 args.push_back( "--file" );
197 args.push_back( file_r.asString() );
198 args.push_back( "--fsig" );
199 args.push_back( data_r._sigpathLocal.asString() );
200 args.push_back( "--fkey" );
201 args.push_back( data_r._keypathLocal.asString() );
202 args.push_back( "--ralias" );
203 args.push_back( data_r._repoinfo.alias() );
204 ExternalProgram cmd { args, ExternalProgram::Stderr_To_Stdout, false, -1, false, _chroot };
205
206 // draft: maybe integrate jobReport into Monitor
207 Monitor monitor( 800 );
208 UserDataJobReport jobReport { "cmdout", "monitor" };
209 jobReport.set( "CmdId", unsigned(cmd.getpid()) );
210 jobReport.set( "CmdTag", str::numstring( cmd.getpid() ) );
211 jobReport.set( "CmdName", "Repoverification plugin "+plugin_r );
212 jobReport.set( "RepoInfo", data_r._repoinfo );
213
214 std::optional<std::ostringstream> buffer; // Send output in exception is no one is listening
215 jobReport.debug( "?" ); // someone listening?
216 if ( not jobReport.haskey( "!" ) ) // no
217 buffer = std::ostringstream();
218
219 int ret = monitor( cmd, [&jobReport,&buffer,&cmd]( std::optional<std::string> line_r )->bool {
220 if ( line_r ) {
221 DBG << "["<<cmd.getpid()<<"> " << *line_r << endl;
222 if ( buffer ) (*buffer) << *line_r << endl;
223 return jobReport.data( *line_r );
224 }
225 else {
226 return jobReport.debug( "ping" );
227 }
228 return true;
229 } );
230
231 if ( ret ) {
232 const std::string & msg { str::Format( "Metadata rejected by '%1%' plugin (returned %2%)" ) % plugin_r % ret };
233
234 ExceptionType excp { msg };
235 if ( buffer ) excp.addHistory( buffer->str() );
236 excp.addHistory( str::Format( "%1%%2% returned %3%" ) % (_chroot.emptyOrRoot()?"":"("+_chroot.asString()+")") % pluginPath % ret );
237
238 ZYPP_THROW( excp );
239 }
240 }
241
242 const Pathname & plugindir() const
243 { return _watchPlugindir.path(); }
244
245 private:
246 WatchFile _watchPlugindir;
247 Pathname _chroot;
248 bool _isNeeded = false;
249 };
250
252 inline std::ostream & operator<<( std::ostream & str, const PluginRepoverification::Impl & obj )
253 { return str << "PluginRepoverification(" << obj.plugindir() << ", " << obj.isNeeded() << ")"; }
254
256 inline std::ostream & dumpOn( std::ostream & str, const PluginRepoverification::Impl & obj )
257 { return str << obj; }
258
259
261 //
262 // CLASS NAME : PluginRepoverification
263 //
265
266 PluginRepoverification::PluginRepoverification()
267 : _pimpl( new Impl )
268 {}
269
270 PluginRepoverification::PluginRepoverification( Pathname plugindir_r, Pathname chroot_r )
271 : _pimpl( new Impl( std::move(plugindir_r), std::move(chroot_r) ) )
272 {}
273
274 PluginRepoverification::~PluginRepoverification()
275 {}
276
277
278 bool PluginRepoverification::isNeeded() const
279 { return _pimpl->isNeeded(); }
280
281 bool PluginRepoverification::checkIfNeeded()
282 { return _pimpl->checkIfNeeded(); }
283
284 PluginRepoverification::Checker PluginRepoverification::getChecker( Pathname sigpathLocal_r, Pathname keypathLocal_r, RepoInfo repo_r ) const
285 { return Checker( new Checker::Impl( _pimpl, std::move(sigpathLocal_r), std::move(keypathLocal_r), std::move(repo_r) ) ); }
286
287
288 std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj )
289 { return str << *obj._pimpl; }
290
291 std::ostream & dumpOn( std::ostream & str, const PluginRepoverification & obj )
292 { return dumpOn( str, *obj._pimpl ); }
293
294 bool operator==( const PluginRepoverification & lhs, const PluginRepoverification & rhs )
295 { return lhs._pimpl == rhs._pimpl; }
296
298 //
299 // CLASS NAME : PluginRepoverification::Checker
300 //
302 PluginRepoverification::Checker::Checker( Impl* pimpl_r )
303 : _pimpl { pimpl_r }
304 {}
305
306 PluginRepoverification::Checker::~Checker()
307 {}
308
309 void PluginRepoverification::Checker::operator()( const Pathname & file_r ) const
310 { _pimpl->_parent->verifyWorkflow( file_r, _pimpl ); }
311
312
313 } // namespace repo
314
315} // namespace zypp
316
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
ExternalProgram.h
Globals.h
Provides API related macros.
LogTools.h
DBG
#define DBG
Definition Logger.h:102
WAR
#define WAR
Definition Logger.h:104
INT
#define INT
Definition Logger.h:107
PluginRepoverification.h
ZYppCallbacks.h
bool
zypp::Exception::addHistory
void addHistory(const std::string &msg_r)
Add some message text to the history.
Definition Exception.cc:189
zypp::ExternalProgram
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
Definition ExternalProgram.h:64
zypp::ExternalProgram::close
int close() override
Wait for the progamm to complete.
Definition ExternalProgram.cc:357
zypp::ExternalProgram::Arguments
std::vector< std::string > Arguments
Definition ExternalProgram.h:68
zypp::ExternalProgram::kill
bool kill()
Kill the program.
Definition ExternalProgram.cc:425
zypp::ExternalProgram::getpid
pid_t getpid()
return pid
Definition ExternalProgram.cc:464
zypp::ExternalProgram::running
bool running()
Return whether program is running.
Definition ExternalProgram.cc:451
zypp::ExternalProgram::Stderr_To_Stdout
@ Stderr_To_Stdout
Definition ExternalProgram.h:77
zypp::RepoInfo
What is known about a repository.
Definition RepoInfo.h:72
zypp::WatchFile
Remember a files attributes to detect content changes.
Definition watchfile.h:50
zypp::WatchFile::hasChanged
bool hasChanged()
Definition watchfile.h:80
zypp::WatchFile::path
const Pathname & path() const
Definition watchfile.h:65
zypp::callback::UserData::set
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
Definition UserData.h:119
zypp::callback::UserData::haskey
bool haskey(const std::string &key_r) const
Whether key_r is in data.
Definition UserData.h:98
zypp::externalprogram::ExternalDataSource::setBlocking
void setBlocking(bool mode)
Set the blocking mode of the input stream.
Definition ExternalDataSource.cc:110
zypp::externalprogram::ExternalDataSource::inputFile
FILE * inputFile() const
Return the input stream.
Definition ExternalDataSource.h:118
zypp::filesystem::PathInfo
Wrapper class for stat/lstat.
Definition PathInfo.h:226
zypp::filesystem::PathInfo::userMayRX
bool userMayRX() const
Definition PathInfo.h:358
zypp::filesystem::PathInfo::isFile
bool isFile() const
Definition PathInfo.h:295
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zypp::filesystem::Pathname::stripprefix
static Pathname stripprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r with any root_r dir prefix striped.
Definition Pathname.cc:293
zypp::filesystem::Pathname::emptyOrRoot
bool emptyOrRoot() const
Test for "" or "/".
Definition Pathname.h:127
zypp::filesystem::Pathname::asString
const std::string & asString() const
String representation.
Definition Pathname.h:94
zypp::repo::RepoInfoBase::alias
std::string alias() const
unique identifier for this source.
Definition RepoInfoBase.cc:110
zypp_private::repo::PluginRepoverification::Checker::Impl
PluginRepoverification::Checker data storage.
Definition PluginRepoverification.cc:108
zypp_private::repo::PluginRepoverification::Checker::Impl::Impl
Impl(RW_pointer< PluginRepoverification::Impl > parent_r, Pathname &&sigpathLocal_r, Pathname &&keypathLocal_r, RepoInfo &&repo_r)
Definition PluginRepoverification.cc:110
zypp_private::repo::PluginRepoverification::Checker::Impl::_parent
RW_pointer< PluginRepoverification::Impl > _parent
Definition PluginRepoverification.cc:118
zypp_private::repo::PluginRepoverification::Checker::Impl::_repoinfo
RepoInfo _repoinfo
Definition PluginRepoverification.cc:121
zypp_private::repo::PluginRepoverification::Checker::Impl::_sigpathLocal
Pathname _sigpathLocal
Definition PluginRepoverification.cc:119
zypp_private::repo::PluginRepoverification::Checker::Impl::_keypathLocal
Pathname _keypathLocal
Definition PluginRepoverification.cc:120
zypp_private::repo::PluginRepoverification::Checker
FileChecker checking all repoverification plugins.
Definition PluginRepoverification.h:83
zypp_private::repo::PluginRepoverification::Checker::~Checker
~Checker()
Definition PluginRepoverification.cc:306
zypp_private::repo::PluginRepoverification::Checker::operator()
void operator()(const Pathname &file_r) const
Check the downloaded master index file.
Definition PluginRepoverification.cc:309
zypp_private::repo::PluginRepoverification::Checker::Checker
Checker(Impl *pimpl)
Definition PluginRepoverification.cc:302
zypp_private::repo::PluginRepoverification::Checker::_pimpl
RW_pointer< Impl > _pimpl
Pointer to implementation (ref).
Definition PluginRepoverification.h:98
zypp_private::repo::PluginRepoverification::Impl
PluginRepoverification implementation.
Definition PluginRepoverification.cc:129
zypp_private::repo::PluginRepoverification::Impl::pluginVerify
void pluginVerify(std::string plugin_r, const Pathname &file_r, const PluginRepoverification::Checker::Impl &data_r) const
Definition PluginRepoverification.cc:183
zypp_private::repo::PluginRepoverification::Impl::checkIfNeeded
bool checkIfNeeded()
Definition PluginRepoverification.cc:152
zypp_private::repo::PluginRepoverification::Impl::isNeeded
bool isNeeded() const
Definition PluginRepoverification.cc:149
zypp_private::repo::PluginRepoverification::Impl::plugindir
const Pathname & plugindir() const
Definition PluginRepoverification.cc:242
zypp_private::repo::PluginRepoverification::Impl::operator=
Impl & operator=(Impl &&)=delete
zypp_private::repo::PluginRepoverification::Impl::Impl
Impl(Impl &&)=delete
zypp_private::repo::PluginRepoverification::Impl::operator<<
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
relates: PluginRepoverification::Impl Stream output
Definition PluginRepoverification.cc:252
zypp_private::repo::PluginRepoverification::Impl::Impl
Impl(Pathname &&plugindir_r, Pathname &&chroot_r)
Definition PluginRepoverification.cc:142
zypp_private::repo::PluginRepoverification::Impl::_chroot
Pathname _chroot
Definition PluginRepoverification.cc:247
zypp_private::repo::PluginRepoverification::Impl::Impl
Impl(const Impl &)=delete
zypp_private::repo::PluginRepoverification::Impl::_isNeeded
bool _isNeeded
Definition PluginRepoverification.cc:248
zypp_private::repo::PluginRepoverification::Impl::verifyWorkflow
void verifyWorkflow(const Pathname &file_r, RW_pointer< PluginRepoverification::Checker::Impl > datap_r) const
Definition PluginRepoverification.cc:170
zypp_private::repo::PluginRepoverification::Impl::_watchPlugindir
WatchFile _watchPlugindir
Definition PluginRepoverification.cc:246
zypp_private::repo::PluginRepoverification::Impl::operator=
Impl & operator=(const Impl &)=delete
zypp_private::repo::PluginRepoverification::Impl::dumpOn
friend std::ostream & dumpOn(std::ostream &str, const Impl &obj)
relates: PluginRepoverification::Impl Verbose stream output
Definition PluginRepoverification.cc:256
zypp_private::repo::PluginRepoverification::Impl::~Impl
~Impl()
Definition PluginRepoverification.cc:146
zypp_private::repo::PluginRepoverification::Impl::Impl
Impl()
Definition PluginRepoverification.cc:134
zypp_private::repo::PluginRepoverification::PluginRepoverification
PluginRepoverification()
Default ctor, do nothing.
Definition PluginRepoverification.cc:266
zypp_private::repo::PluginRepoverification::operator==
friend bool operator==(const PluginRepoverification &lhs, const PluginRepoverification &rhs)
relates: PluginRepoverification
Definition PluginRepoverification.cc:294
zypp_private::repo::PluginRepoverification::isNeeded
bool isNeeded() const
Whether the last checkIfNeeded found plugins to execute at all.
Definition PluginRepoverification.cc:278
zypp_private::repo::PluginRepoverification::operator<<
friend std::ostream & operator<<(std::ostream &str, const PluginRepoverification &obj)
relates: PluginRepoverification Stream output
Definition PluginRepoverification.cc:288
zypp_private::repo::PluginRepoverification::dumpOn
friend std::ostream & dumpOn(std::ostream &str, const PluginRepoverification &obj)
Definition PluginRepoverification.cc:291
zypp_private::repo::PluginRepoverification::checkIfNeeded
bool checkIfNeeded()
Checks whether there are plugins to execute at all.
Definition PluginRepoverification.cc:281
zypp_private::repo::PluginRepoverification::getChecker
Checker getChecker(Pathname sigpathLocal_r, Pathname keypathLocal_r, RepoInfo repo_r) const
FileChecker factory remembering the location of the master index files GPG signature and key.
Definition PluginRepoverification.cc:284
zypp_private::repo::PluginRepoverification::_pimpl
RW_pointer< Impl > _pimpl
Implementation class.
Definition PluginRepoverification.h:108
zypp_private::repo::PluginRepoverification::ExceptionType
PluginRepoverificationCheckException ExceptionType
Definition PluginRepoverification.h:58
zypp_private::repo::PluginRepoverification::~PluginRepoverification
~PluginRepoverification()
Dtor.
Definition PluginRepoverification.cc:274
std
Definition ansi.h:855
str
String related utilities and Regular expression matching.
zypp::filesystem::dirForEach
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
Definition PathInfo.cc:32
zypp::io::receiveUpto
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
Definition IOTools.cc:85
zypp::io::Timeout
@ Timeout
Definition IOTools.h:72
zypp::io::Success
@ Success
Definition IOTools.h:71
zypp::io::Error
@ Error
Definition IOTools.h:74
zypp::io::EndOfFile
@ EndOfFile
Definition IOTools.h:73
zypp::io::timeout_type
size_t timeout_type
Definition IOTools.h:77
zypp::repo
Definition DeltaCandidates.cc:30
zypp::str::numstring
std::string numstring(char n, int w=0)
Definition String.h:290
zypp_private
Definition PluginRepoverification.cc:27
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zypp::RW_pointer
Wrapper for const correct access via Smart pointer types.
Definition PtrTypes.h:293
zypp::UserDataJobReport
JobReport convenience sending this instance of UserData with each message.
Definition ZYppCallbacks.h:1125
zypp::UserDataJobReport::data
bool data(const std::string &msg_r)
Definition ZYppCallbacks.h:1133
zypp::UserDataJobReport::debug
bool debug(const std::string &msg_r)
Definition ZYppCallbacks.h:1128
zypp::str::Format
Convenient building of std::string with boost::format.
Definition String.h:254
zypp_private::repo::Monitor
Definition PluginRepoverification.cc:34
zypp_private::repo::Monitor::reportFinalLineUnlessEmpty
bool reportFinalLineUnlessEmpty(std::string &line_r, Callback &cb_r)
Definition PluginRepoverification.cc:93
zypp_private::repo::Monitor::Monitor
Monitor(io::timeout_type timeout_r=io::no_timeout)
Definition PluginRepoverification.cc:38
zypp_private::repo::Monitor::reportTimeout
bool reportTimeout(Callback &cb_r)
Definition PluginRepoverification.cc:89
zypp_private::repo::Monitor::operator()
int operator()(ExternalProgram &prog_r, Callback cb_r=Callback())
Definition PluginRepoverification.cc:42
zypp_private::repo::Monitor::reportLine
bool reportLine(std::string &line_r, Callback &cb_r)
Definition PluginRepoverification.cc:80
zypp_private::repo::Monitor::_timeout
io::timeout_type _timeout
Definition PluginRepoverification.cc:100
zypp_private::repo::Monitor::Callback
std::function< bool(std::optional< std::string >)> Callback
Report a line of output (without trailing NL) otherwise a life ping on timeout.
Definition PluginRepoverification.cc:36
PathInfo.h