libzypp 17.32.2
checksumwf.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9
10#include "checksumwf.h"
11#include "logichelpers.h"
12
13#include <zypp-core/Date.h>
14#include <zypp-core/Pathname.h>
15#include <zypp-core/CheckSum.h>
16#include <zypp-core/base/Gettext.h>
17#include <zypp-core/fs/PathInfo.h>
18#include <utility>
19#include <zypp-core/zyppng/pipelines/Expected>
20#include <zypp-media/FileCheckException>
21#include <zypp-media/ng/Provide>
22#include <zypp/Digest.h>
23#include <zypp/ng/Context>
24#include <zypp/ng/UserRequest>
25
26#include <map>
27
29
30 using namespace zyppng::operators;
31
32 template <class Executor, class OpType >
33 struct CheckSumWorkflowLogic : public LogicBase<Executor, OpType>
34 {
35 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
36
38 using ZyppContextType = remove_smart_ptr_t<ZyppContextRefType>;
39 using ProvideType = typename ZyppContextType::ProvideType;
40 using MediaHandle = typename ProvideType::MediaHandle;
41 using ProvideRes = typename ProvideType::Res;
42
44 : _context( std::move(zyppContext) )
45 , _checksum(std::move( checksum ))
46 , _file(std::move( file ))
47 {}
48
49 auto execute()
50 {
51
52 //MIL << "checking " << file << " file against checksum '" << _checksum << "'" << endl;
53 if ( _checksum.empty() ) {
54 MIL << "File " << _file << " has no checksum available." << std::endl;
55 if ( executor()->askUserToAcceptNoDigest( _file ) ) {
56 MIL << "User accepted " << _file << " with no checksum." << std::endl;
57 return makeReadyResult( expected<void>::success() );
58 } else {
59 return makeReadyResult( expected<void>::error( ZYPP_EXCPT_PTR(zypp::FileCheckException( _file.basename() + " has no checksum" ) ) ) );
60 }
61
62 } else {
63
64 return _context->provider()->checksumForFile ( _file, _checksum.type() )
65 | [] ( expected<zypp::CheckSum> sum ) {
66 if ( !sum )
67 return zypp::CheckSum( );
68 return sum.get();
69 }
70 | [this, _file=_file]( zypp::CheckSum real_checksum ){
71 if ( (real_checksum != _checksum) )
72 {
73 // Remember askUserToAcceptWrongDigest decision for at most 12hrs in memory;
74 // Actually we just want to prevent asking the same question again when the
75 // previously downloaded file is retrieved from the disk cache.
76 static std::map<std::string,std::string> exceptions;
77 static zypp::Date exceptionsAge;
79 if ( !exceptions.empty() && now-exceptionsAge > 12*zypp::Date::hour )
80 exceptions.clear();
81
82 WAR << "File " << _file << " has wrong checksum " << real_checksum << " (expected " << _checksum << ")" << std::endl;
83 if ( !exceptions.empty() && exceptions[real_checksum.checksum()] == _checksum.checksum() )
84 {
85 WAR << "User accepted " << _file << " with WRONG CHECKSUM. (remembered)" << std::endl;
86 return expected<void>::success();
87 }
88 else if ( executor()->askUserToAcceptWrongDigest( _file, _checksum.checksum(), real_checksum.checksum() ) )
89 {
90 WAR << "User accepted " << _file << " with WRONG CHECKSUM." << std::endl;
91 exceptions[real_checksum.checksum()] = _checksum.checksum();
92 exceptionsAge = now;
93 return expected<void>::success();
94 }
95 else
96 {
97 return expected<void>::error( ZYPP_EXCPT_PTR(zypp::FileCheckException( _file.basename() + " has wrong checksum" ) ) );
98 }
99 }
100 return expected<void>::success();
101 };
102 }
103 }
104
105 protected:
109
110 };
111
112 struct AsyncCheckSumExecutor : public CheckSumWorkflowLogic< AsyncCheckSumExecutor, AsyncOp<expected<void>> >
113 {
115
117 const auto &label = (zypp::str::Format(_("No digest for file %s.")) % file ).str();
118 auto req = BooleanChoiceRequest::create( label, false, AcceptNoDigestRequest::makeData(file) );
119 _context->sendUserRequest( req );
120 return req->choice ();
121 }
122 bool askUserToAccepUnknownDigest ( const zypp::Pathname &file, const std::string &name ) {
123 const auto &label = (zypp::str::Format(_("Unknown digest %s for file %s.")) %name % file).str();
124 auto req = BooleanChoiceRequest::create( label, false, AcceptUnknownDigestRequest::makeData(file, name) );
125 _context->sendUserRequest( req );
126 return req->choice ();
127 }
128 bool askUserToAcceptWrongDigest ( const zypp::Pathname &file, const std::string &requested, const std::string &found ) {
129 const auto &label = (zypp::str::Format(_("Digest verification failed for file '%s'")) % file).str();
130 auto req = BooleanChoiceRequest::create( label, false, AcceptWrongDigestRequest::makeData(file, requested, found) );
131 _context->sendUserRequest( req );
132 return req->choice ();
133 }
134
135 };
136
137 struct SyncCheckSumExecutor : public CheckSumWorkflowLogic< SyncCheckSumExecutor, SyncOp<expected<void>> >
138 {
140
141 zypp::CheckSum checksumFromFile ( SyncContextRef &, const zypp::Pathname &path, const std::string &checksumType ) {
142 return zypp::CheckSum( checksumType, zypp::filesystem::checksum( path, checksumType ));
143 }
146 return report->askUserToAcceptNoDigest(file);
147 }
148 bool askUserToAccepUnknownDigest ( const zypp::Pathname &file, const std::string &name ) {
150 return report->askUserToAccepUnknownDigest( file, name );
151 }
152 bool askUserToAcceptWrongDigest ( const zypp::Pathname &file, const std::string &requested, const std::string &found ) {
154 return report->askUserToAcceptWrongDigest( file, requested, found );
155 };
156 };
157
158 expected<void> verifyChecksum( SyncContextRef zyppCtx, zypp::CheckSum checksum, zypp::Pathname file )
159 {
160 return SyncCheckSumExecutor::run( std::move(zyppCtx), std::move(checksum), std::move(file) );
161 }
162
163 AsyncOpRef<expected<void> > verifyChecksum( ContextRef zyppCtx, zypp::CheckSum checksum, zypp::filesystem::Pathname file )
164 {
165 return AsyncCheckSumExecutor::run( std::move(zyppCtx), std::move(checksum), std::move(file) );
166 }
167
168 std::function<AsyncOpRef<expected<ProvideRes> > (ProvideRes &&)> checksumFileChecker( ContextRef zyppCtx, zypp::CheckSum checksum )
169 {
170 using zyppng::operators::operator|;
171 return [ zyppCtx, checksum=std::move(checksum) ]( ProvideRes res ) mutable -> AsyncOpRef<expected<ProvideRes>> {
172 return verifyChecksum( zyppCtx, std::move(checksum), res.file() )
173 | [ res ] ( expected<void> result ) mutable {
174 if ( result )
175 return expected<ProvideRes>::success( std::move(res) );
176 else
177 return expected<ProvideRes>::error( std::move(result.error()) );
178 };
179 };
180 }
181
182 std::function<expected<SyncProvideRes> (SyncProvideRes &&)> checksumFileChecker(SyncContextRef zyppCtx, zypp::CheckSum checksum)
183 {
184 using zyppng::operators::operator|;
185 return [ zyppCtx = std::move(zyppCtx), checksum=std::move(checksum) ]( SyncProvideRes res ) mutable -> expected<SyncProvideRes> {
186 return verifyChecksum( zyppCtx, std::move(checksum), res.file() )
187 | [ res ] ( expected<void> result ) mutable {
188 if ( result )
189 return expected<SyncProvideRes>::success( std::move(res) );
190 else
191 return expected<SyncProvideRes>::error( std::move(result.error()) );
192 };
193 };
194 }
195
196}
bool empty() const
Definition CheckSum.cc:173
std::string type() const
Definition CheckSum.cc:167
std::string checksum() const
Definition CheckSum.cc:170
Store and operate on date (time_t).
Definition Date.h:33
static const ValueType hour
Definition Date.h:43
static Date now()
Return the current time.
Definition Date.h:78
std::string basename() const
Return the last component of this path.
Definition Pathname.h:128
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
Definition provideres.h:36
Definition Arch.h:364
String related utilities and Regular expression matching.
std::string checksum(const Pathname &file, const std::string &algorithm)
Compute a files checksum.
Definition PathInfo.cc:1052
UserData makeData(const zypp::Pathname &p)
UserData makeData(const zypp::Pathname &p, const std::string &name)
UserData makeData(const zypp::Pathname &p, const std::string &requested, const std::string &found)
std::function< AsyncOpRef< expected< ProvideRes > >(ProvideRes &&) checksumFileChecker)(ContextRef zyppCtx, zypp::CheckSum checksum)
expected< void > verifyChecksum(SyncContextRef zyppCtx, zypp::CheckSum checksum, zypp::Pathname file)
std::conditional_t< detail::is_async_op_v< OpType >, ContextRef, SyncContextRef > MaybeAsyncContextRef
Convenient building of std::string with boost::format.
Definition String.h:253
bool askUserToAcceptNoDigest(const zypp::Pathname &file)
bool askUserToAcceptWrongDigest(const zypp::Pathname &file, const std::string &requested, const std::string &found)
bool askUserToAccepUnknownDigest(const zypp::Pathname &file, const std::string &name)
typename ZyppContextType::ProvideType ProvideType
Definition checksumwf.cc:39
typename ProvideType::MediaHandle MediaHandle
Definition checksumwf.cc:40
MaybeAsyncContextRef< OpType > ZyppContextRefType
Definition checksumwf.cc:37
remove_smart_ptr_t< ZyppContextRefType > ZyppContextType
Definition checksumwf.cc:38
CheckSumWorkflowLogic(ZyppContextRefType zyppContext, zypp::CheckSum &&checksum, zypp::Pathname file)
Definition checksumwf.cc:43
bool askUserToAcceptNoDigest(const zypp::Pathname &file)
bool askUserToAcceptWrongDigest(const zypp::Pathname &file, const std::string &requested, const std::string &found)
bool askUserToAccepUnknownDigest(const zypp::Pathname &file, const std::string &name)
zypp::CheckSum checksumFromFile(SyncContextRef &, const zypp::Pathname &path, const std::string &checksumType)
Executor * executor()
static std::enable_if_t< detail::is_async_op_v< FOpType >, AsyncOpRef< Result > > run(Args &&...args)
auto makeReadyResult(T &&res)
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:433
#define _(MSG)
Definition Gettext.h:37
#define MIL
Definition Logger.h:96
#define WAR
Definition Logger.h:97