libzypp  17.38.7
checksumwf.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
10 #include "checksumwf.h"
11 
12 
13 #include <map>
14 #include <utility>
15 
16 #include <zypp-core/CheckSum.h>
17 #include <zypp-core/Date.h>
18 #include <zypp-core/Pathname.h>
19 #include <zypp-core/base/Gettext.h>
20 #include <zypp-core/fs/PathInfo.h>
21 #include <zypp-core/ng/pipelines/Expected>
22 #include <zypp-media/FileCheckException>
23 #include <zypp/Digest.h>
24 #include <zypp/ng/UserRequest>
25 #include <zypp/ng/context.h>
26 #include <zypp/ng/media/provide.h>
27 #include <zypp/ng/reporthelper.h>
28 
30 
31  using namespace zyppng::operators;
32 
34  {
35 
37  using MediaHandle = typename ProvideType::MediaHandle;
38  using ProvideRes = typename ProvideType::Res;
39 
40  CheckSumWorkflowLogic( ContextRef zyppContext, zypp::CheckSum &&checksum, zypp::Pathname file )
41  : _context( std::move(zyppContext) )
42  , _report( _context )
43  , _checksum(std::move( checksum ))
44  , _file(std::move( file ))
45  {}
46 
47  auto execute()
48  {
49 
50  //MIL << "checking " << file << " file against checksum '" << _checksum << "'" << endl;
51  if ( _checksum.empty() ) {
52  MIL << "File " << _file << " has no checksum available." << std::endl;
53  if ( _report.askUserToAcceptNoDigest( _file ) ) {
54  MIL << "User accepted " << _file << " with no checksum." << std::endl;
55  return makeReadyTask( expected<void>::success() );
56  } else {
57  return makeReadyTask( expected<void>::error( ZYPP_EXCPT_PTR(zypp::FileCheckException( _file.basename() + " has no checksum" ) ) ) );
58  }
59 
60  } else {
61 
62  return _context->provider()->checksumForFile ( _file, _checksum.type() )
63  | [] ( expected<zypp::CheckSum> sum ) {
64  if ( !sum )
65  return zypp::CheckSum( );
66  return sum.get();
67  }
68  | [this, _file=_file]( zypp::CheckSum real_checksum ){
69  if ( (real_checksum != _checksum) )
70  {
71  // Remember askUserToAcceptWrongDigest decision for at most 12hrs in memory;
72  // Actually we just want to prevent asking the same question again when the
73  // previously downloaded file is retrieved from the disk cache.
74  static std::map<std::string,std::string> exceptions;
75  static zypp::Date exceptionsAge;
76  zypp::Date now( zypp::Date::now() );
77  if ( !exceptions.empty() && now-exceptionsAge > 12*zypp::Date::hour )
78  exceptions.clear();
79 
80  WAR << "File " << _file << " has wrong checksum " << real_checksum << " (expected " << _checksum << ")" << std::endl;
81  if ( !exceptions.empty() && exceptions[real_checksum.checksum()] == _checksum.checksum() )
82  {
83  WAR << "User accepted " << _file << " with WRONG CHECKSUM. (remembered)" << std::endl;
84  return expected<void>::success();
85  }
86  else if ( _report.askUserToAcceptWrongDigest( _file, _checksum.checksum(), real_checksum.checksum() ) )
87  {
88  WAR << "User accepted " << _file << " with WRONG CHECKSUM." << std::endl;
89  exceptions[real_checksum.checksum()] = _checksum.checksum();
90  exceptionsAge = now;
91  return expected<void>::success();
92  }
93  else
94  {
95  return expected<void>::error( ZYPP_EXCPT_PTR(zypp::FileCheckException( _file.basename() + " has wrong checksum" ) ) );
96  }
97  }
98  return expected<void>::success();
99  };
100  }
101  }
102 
103  protected:
104  ContextRef _context;
108 
109  };
110 
111  MaybeAwaitable<expected<void>> verifyChecksum( ContextRef zyppCtx, zypp::CheckSum checksum, zypp::filesystem::Pathname file )
112  {
113  CheckSumWorkflowLogic impl( std::move(zyppCtx), std::move(checksum), std::move(file) );
114  zypp_co_return zypp_co_await( impl.execute() );
115  }
116 
117  std::function<MaybeAwaitable<expected<ProvideRes> > (ProvideRes &&)> checksumFileChecker( ContextRef zyppCtx, zypp::CheckSum checksum )
118  {
119  using zyppng::operators::operator|;
120  return [ zyppCtx = std::move(zyppCtx), checksum=std::move(checksum) ]( ProvideRes res ) mutable -> MaybeAwaitable<expected<ProvideRes>> {
121  return verifyChecksum( zyppCtx, std::move(checksum), res.file() )
122  | [ res ] ( expected<void> result ) mutable {
123  if ( result )
124  return expected<ProvideRes>::success( std::move(res) );
125  else
126  return expected<ProvideRes>::error( std::move(result.error()) );
127  };
128  };
129  }
130 
131 }
#define MIL
Definition: Logger.h:103
Provide ProvideType
Definition: context.h:34
typename ProvideType::MediaHandle MediaHandle
Definition: checksumwf.cc:37
typename Context::ProvideType ProvideType
Definition: checksumwf.cc:36
Definition: ansi.h:854
std::function< MaybeAwaitable< expected< ProvideRes > >ProvideRes &&)> checksumFileChecker(ContextRef zyppCtx, zypp::CheckSum checksum)
Definition: checksumwf.cc:117
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:137
static expected error(ConsParams &&...params)
Definition: expected.h:189
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition: Exception.h:463
Store and operate on date (time_t).
Definition: Date.h:32
#define WAR
Definition: Logger.h:104
std::unique_ptr< ReportType > _report
Definition: TargetImpl.cc:268
static expected success(ConsParams &&...params)
Definition: expected.h:178
MaybeAwaitable< expected< void > > verifyChecksum(ContextRef zyppCtx, zypp::CheckSum checksum, zypp::filesystem::Pathname file)
Definition: checksumwf.cc:111
static const ValueType hour
Definition: Date.h:43
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:1070
CheckSumWorkflowLogic(ContextRef zyppContext, zypp::CheckSum &&checksum, zypp::Pathname file)
Definition: checksumwf.cc:40
zypp::Pathname _file
Definition: downloadwf.cc:185