libzypp  17.34.1
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 
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;
58  } else {
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;
78  zypp::Date now( zypp::Date::now() );
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 
159  {
160  return SyncCheckSumExecutor::run( std::move(zyppCtx), std::move(checksum), std::move(file) );
161  }
162 
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 }
#define MIL
Definition: Logger.h:98
#define _(MSG)
Definition: Gettext.h:39
bool askUserToAcceptNoDigest(const zypp::Pathname &file)
Definition: checksumwf.cc:144
std::function< AsyncOpRef< expected< ProvideRes > >ProvideRes &&)> checksumFileChecker(ContextRef zyppCtx, zypp::CheckSum checksum)
Definition: checksumwf.cc:168
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
Definition: provideres.h:35
UserData makeData(const zypp::Pathname &p, const std::string &name)
Definition: userrequest.cc:19
String related utilities and Regular expression matching.
Definition: Arch.h:363
zypp::CheckSum checksumFromFile(SyncContextRef &, const zypp::Pathname &path, const std::string &checksumType)
Definition: checksumwf.cc:141
Convenient building of std::string with boost::format.
Definition: String.h:252
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:130
static expected error(ConsParams &&...params)
Definition: expected.h:126
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition: Exception.h:433
bool askUserToAcceptWrongDigest(const zypp::Pathname &file, const std::string &requested, const std::string &found)
Definition: checksumwf.cc:128
static std::enable_if_t< detail::is_async_op_v< FOpType >, AsyncOpRef< Result > > run(Args &&...args)
Definition: logichelpers.h:137
Store and operate on date (time_t).
Definition: Date.h:32
bool askUserToAccepUnknownDigest(const zypp::Pathname &file, const std::string &name)
Definition: checksumwf.cc:148
#define WAR
Definition: Logger.h:99
#define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType)
Definition: logichelpers.h:199
bool askUserToAcceptNoDigest(const zypp::Pathname &file)
Definition: checksumwf.cc:116
std::conditional_t< isAsync, AsyncOpRef< T >, T > makeReadyResult(T &&result)
Definition: asyncop.h:297
static expected success(ConsParams &&...params)
Definition: expected.h:115
bool askUserToAcceptWrongDigest(const zypp::Pathname &file, const std::string &requested, const std::string &found)
Definition: checksumwf.cc:152
static const ValueType hour
Definition: Date.h:43
std::shared_ptr< AsyncOp< T > > AsyncOpRef
Definition: asyncop.h:255
bool askUserToAccepUnknownDigest(const zypp::Pathname &file, const std::string &name)
Definition: checksumwf.cc:122
static Date now()
Return the current time.
Definition: Date.h:78
std::string checksum(const Pathname &file, const std::string &algorithm)
Compute a files checksum.
Definition: PathInfo.cc:1056
expected< void > verifyChecksum(SyncContextRef zyppCtx, zypp::CheckSum checksum, zypp::Pathname file)
Definition: checksumwf.cc:158
UserData makeData(const zypp::Pathname &p)
Definition: userrequest.cc:13
std::conditional_t< detail::is_async_op_v< OpType >, ContextRef, SyncContextRef > MaybeAsyncContextRef
Definition: contextfacade.h:45
zypp::Pathname _file
Definition: downloadwf.cc:202
typename remove_smart_ptr< T >::type remove_smart_ptr_t
Definition: type_traits.h:128
UserData makeData(const zypp::Pathname &p, const std::string &requested, const std::string &found)
Definition: userrequest.cc:26
CheckSumWorkflowLogic(ZyppContextRefType zyppContext, zypp::CheckSum &&checksum, zypp::Pathname file)
Definition: checksumwf.cc:43