15#include <rpm/rpmcli.h> 
   16#include <rpm/rpmlog.h> 
   38#include <zypp-core/base/DtorReset> 
   43#include <zypp-common/PublicKey.h> 
   44#include <zypp-core/ui/ProgressData> 
   55#include <zypp-common/KeyManager.h> 
   63#define WARNINGMAILPATH         "/var/log/YaST2/" 
   64#define FILEFORBACKUPFILES      "YaSTBackupModifiedFiles" 
   65#define MAXRPMMESSAGELINES      10000 
   67#define WORKAROUNDRPMPWDBUG 
   69#undef ZYPP_BASE_LOGGER_LOGGROUP 
   70#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb" 
   82      static bool val = [](){
 
   83        const char * 
env = getenv(
"ZYPP_RPM_DEBUG");
 
 
   95const char* quoteInFilename_m = 
"\'\"";
 
   96inline std::string rpmQuoteFilename( 
const Pathname & path_r )
 
   98  std::string path( path_r.
asString() );
 
   99  for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m );
 
  100        pos != std::string::npos;
 
  101        pos = path.find_first_of( quoteInFilename_m, pos ) )
 
  103    path.insert( pos, 
"\\" );
 
  114  inline Pathname workaroundRpmPwdBug( Pathname path_r )
 
  116#if defined(WORKAROUNDRPMPWDBUG) 
  120      AutoDispose<char*> cwd( ::get_current_dir_name(), ::free );
 
  122        return Pathname( cwd ) / path_r;
 
  123      WAR << 
"Can't get cwd!" << endl;
 
  133  inline bool workaroundDUMPPOSTTRANS_BUG_1216091( 
bool checkit_r=
false )
 
  135    auto checkit = []()->
bool {
 
  138      if ( it.findPackage( 
"rpm" )
 
  139        && it->tag_edition() == 
Edition(
"4.18.0")
 
  140        && not it->tag_provides().count( Capability(
"rpm_fixed_runposttrans") ) ) {
 
  141        WAR << 
"Workaround broken rpm --runposttrans" << endl;
 
  147    static bool broken = 
false;
 
  169    MIL << 
"trusted key added to zypp Keyring. Importing..." << endl;
 
  170    _rpmdb.importPubkey( key );
 
 
  175    MIL << 
"Trusted key removed from zypp Keyring. Removing..." << endl;
 
  176    _rpmdb.removePubkey( key );
 
 
 
  184unsigned diffFiles(
const std::string& file1, 
const std::string& file2, std::string& out, 
int maxlines)
 
  205    if (maxlines<0?
true:count<maxlines)
 
 
  218#define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); } 
  237  setenv( 
"RPM_IgnoreFailedSymlinks", 
"1", 1 );
 
 
  249  MIL << 
"~RpmDb()" << endl;
 
  252  MIL  << 
"~RpmDb() end" << endl;
 
 
  283  workaroundDUMPPOSTTRANS_BUG_1216091( 
true );
 
  287  if ( root_r.
empty() )
 
  295  if ( dbPath_r != 
"/var/lib/rpm" && ! 
PathInfo( root_r/
"/var/lib/rpm" ).isExist() )
 
  297    WAR << 
"Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
 
  311    if ( root_r == 
_root ) {
 
  319  MIL << 
"Calling initDatabase: " << 
dumpPath( root_r, dbPath_r )
 
  320      << ( doRebuild_r ? 
" (rebuilddb)" : 
"" ) << endl;
 
  334  MIL << 
"Synchronizing keys with zypp keyring" << endl;
 
  342  librpmDb::dbRelease( 
true );
 
  344  MIL << 
"InitDatabase: " << *
this << endl;
 
 
  363  MIL << 
"closeDatabase: " << *
this << endl;
 
 
  394  MIL << 
"RpmDb::rebuildDatabase" << *
this << endl;
 
  408    opts.push_back(
"--rebuilddb");
 
  409    opts.push_back(
"-vv");
 
  419    tics.
range( hdrTotal );
 
  422    return report->progress( tics_r.
reportValue(), mydbpath );
 
  430    static const std::string debugPrefix    { 
"D:" };
 
  431    static const std::string progressPrefix { 
"D:  read h#" };
 
  432    static const std::string ignoreSuffix   { 
"digest: OK" };
 
  447        WAR << 
"User requested abort." << endl;
 
 
  471  void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
 
  478        : _inRpmKeys( nullptr )
 
  479        , _inZyppKeys( nullptr )
 
  482      void updateIf( 
const Edition & rpmKey_r )
 
  484        std::string keyRelease( rpmKey_r.
release() );
 
  485        int comp = _release.compare( keyRelease );
 
  489          _release.swap( keyRelease );
 
  490          _inRpmKeys  = &rpmKey_r;
 
  491          _inZyppKeys = 
nullptr;
 
  492          if ( !keyRelease.empty() )
 
  493            DBG << 
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() << 
"-" <<  keyRelease << endl;
 
  495        else if ( comp == 0 )
 
  499            _inRpmKeys = &rpmKey_r;
 
  503          DBG << 
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() << 
"-" <<  keyRelease << endl;
 
  506      void updateIf( 
const PublicKeyData & zyppKey_r )
 
  508        std::string keyRelease( zyppKey_r.gpgPubkeyRelease() );
 
  509        int comp = _release.compare( keyRelease );
 
  513          _release.swap( keyRelease );
 
  514          _inRpmKeys  = 
nullptr;
 
  515          _inZyppKeys = &zyppKey_r;
 
  516          if ( !keyRelease.empty() )
 
  517            DBG << 
"Old key in R: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << 
"-" << keyRelease << endl;
 
  519        else if ( comp == 0 )
 
  523            _inZyppKeys = &zyppKey_r;
 
  527          DBG << 
"Old key in Z: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << 
"-" << keyRelease << endl;
 
  530      std::string _release;
 
  532      const PublicKeyData * _inZyppKeys;
 
  537    std::map<std::string,Key> _keymap;
 
  539    for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
 
  541      _keymap[(*it).version()].updateIf( *it );
 
  544    for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
 
  546      _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
 
  550    std::set<Edition> rpmKeys;
 
  551    std::list<PublicKeyData> zyppKeys;
 
  552    for_( it, _keymap.begin(), _keymap.end() )
 
  554      DBG << 
"gpg-pubkey-" << (*it).first << 
"-" << (*it).second._release << 
" " 
  555          << ( (*it).second._inRpmKeys  ? 
"R" : 
"_" )
 
  556          << ( (*it).second._inZyppKeys ? 
"Z" : 
"_" ) << endl;
 
  557      if ( ! (*it).second._inRpmKeys )
 
  559        zyppKeys.push_back( *(*it).second._inZyppKeys );
 
  561      if ( ! (*it).second._inZyppKeys )
 
  563        rpmKeys.insert( *(*it).second._inRpmKeys );
 
  566    rpmKeys_r.swap( rpmKeys );
 
  567    zyppKeys_r.swap( zyppKeys );
 
  574  MIL << 
"Going to sync trusted keys..." << endl;
 
  576  std::list<PublicKeyData> zyppKeys( 
getZYpp()->keyRing()->trustedPublicKeyData() );
 
  588    MIL << 
"Removing excess keys in zypp trusted keyring" << std::endl;
 
  592    for ( 
const PublicKeyData & keyData : zyppKeys )
 
  594      if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) )
 
  596        DBG << 
"Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl;
 
  597        getZYpp()->keyRing()->deleteKey( keyData.id(), 
true );
 
  598        if ( !dirty ) dirty = 
true;
 
  602      zyppKeys = 
getZYpp()->keyRing()->trustedPublicKeyData();
 
  605  computeKeyRingSync( rpmKeys, zyppKeys );
 
  606  MIL << (mode_r & 
SYNC_TO_KEYRING   ? 
"" : 
"(skip) ") << 
"Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
 
  607  MIL << (mode_r & 
SYNC_FROM_KEYRING ? 
"" : 
"(skip) ") << 
"Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
 
  613    MIL << 
"Exporting rpm keyring into zypp trusted keyring" <<endl;
 
  620      std::ofstream tmpos( tmpfile.
path().
c_str() );
 
  621      for_( it, rpmKeys.begin(), rpmKeys.end() )
 
  625        getData( 
"gpg-pubkey", *it, result );
 
  626        tmpos << result->tag_description() << endl;
 
  631      getZYpp()->keyRing()->multiKeyImport( tmpfile.
path(), 
true );
 
  635      std::set<Edition> missingKeys;
 
  636      for ( 
const Edition & key : rpmKeys )
 
  638        if ( 
getZYpp()->keyRing()->isKeyTrusted( key.version() ) ) 
 
  640        ERR << 
"Could not import key:" << 
str::Format(
"gpg-pubkey-%s") % key << 
" into zypp keyring (V3 key?)" << endl;
 
  641        missingKeys.insert( key );
 
  643      if ( ! missingKeys.empty() )
 
  649      ERR << 
"Could not import keys into zypp keyring: " << endl;
 
  657    MIL << 
"Importing zypp trusted keyring" << std::endl;
 
  658    for_( it, zyppKeys.begin(), zyppKeys.end() )
 
  670  MIL << 
"Trusted keys synced." << endl;
 
 
  692    WAR << 
"Key " << pubkey_r << 
" can not be imported. (READONLY MODE)" << endl;
 
  697  Edition keyEd( pubkey_r.gpgPubkeyVersion(), pubkey_r.gpgPubkeyRelease() );
 
  699  bool hasOldkeys = 
false;
 
  701  for_( it, rpmKeys.begin(), rpmKeys.end() )
 
  708    if ( keyEd == *it && !pubkey_r.hasSubkeys() ) 
 
  710      MIL << 
"Key " << pubkey_r << 
" is already in the rpm trusted keyring. (skip import)" << endl;
 
  714    if ( keyEd.
version() != (*it).version() )
 
  717    if ( keyEd.
release() < (*it).release() )
 
  719      MIL << 
"Key " << pubkey_r << 
" is older than one in the rpm trusted keyring. (skip import)" << endl;
 
  727  MIL << 
"Key " << pubkey_r << 
" will be imported into the rpm trusted keyring." << (hasOldkeys?
"(update)":
"(new)") << endl;
 
  733    std::string keyName( 
"gpg-pubkey-" + keyEd.
version() );
 
  735    opts.push_back ( 
"-e" );
 
  736    opts.push_back ( 
"--allmatches" );
 
  737    opts.push_back ( 
"--" );
 
  738    opts.push_back ( keyName.c_str() );
 
  749      ERR << 
"Failed to remove key " << pubkey_r << 
" from RPM trusted keyring (ignored)" << endl;
 
  753      MIL << 
"Key " << pubkey_r << 
" has been removed from RPM trusted keyring" << endl;
 
  759  opts.push_back ( 
"--import" );
 
  760  opts.push_back ( 
"--" );
 
  761  std::string pubkeypath( pubkey_r.path().asString() );
 
  762  opts.push_back ( pubkeypath.c_str() );
 
  766  std::vector<std::string> excplines;
 
  772      excplines.push_back( std::move(line) );
 
  788    MIL << 
"Key " << pubkey_r << 
" imported in rpm trusted keyring." << endl;
 
 
  805  std::set<Edition>::const_iterator found_edition = rpm_keys.end();
 
  806  std::string pubkeyVersion( pubkey_r.gpgPubkeyVersion() );
 
  808  for_( it, rpm_keys.begin(), rpm_keys.end() )
 
  810    if ( (*it).version() == pubkeyVersion )
 
  818  if (found_edition == rpm_keys.end())
 
  820      WAR << 
"Key " << pubkey_r.id() << 
" is not in rpm db" << endl;
 
  824  std::string rpm_name(
"gpg-pubkey-" + found_edition->asString());
 
  827  opts.push_back ( 
"-e" );
 
  828  opts.push_back ( 
"--" );
 
  829  opts.push_back ( rpm_name.c_str() );
 
  833  std::vector<std::string> excplines;
 
  839      excplines.push_back( std::move(line) );
 
  855    MIL << 
"Key " << pubkey_r << 
" has been removed from RPM trusted keyring" << endl;
 
 
  867  std::list<PublicKey> ret;
 
  870  for ( it.findByName( 
"gpg-pubkey" ); *it; ++it )
 
  872    Edition edition = it->tag_edition();
 
  877      getData( 
"gpg-pubkey", edition, result );
 
  884        os << result->tag_description();
 
  893      catch ( std::exception & e )
 
  895        ERR << 
"Could not dump key " << edition.
asString() << 
" in tmp file " << file.
path() << endl;
 
 
  905    std::set<Edition> ret;
 
  908    for ( it.findByName( 
"gpg-pubkey" ); *it; ++it )
 
  910      Edition edition = it->tag_edition();
 
  912        ret.insert( edition );
 
 
  929  std::list<FileInfo> result;
 
  935    found = it.findPackage( name_r );
 
  939    found = it.findPackage( name_r, edition_r );
 
 
  956bool RpmDb::hasFile( 
const std::string & file_r, 
const std::string & name_r )
 const 
  962    res = it.findByFile( file_r );
 
  966      res = (it->tag_name() == name_r);
 
 
  985  if (it.findByFile( file_r ))
 
  987    return it->tag_name();
 
 
 1003  return it.findByProvides( tag_r );
 
 
 1017  return it.findByRequiredBy( tag_r );
 
 
 1031  return it.findByConflicts( tag_r );
 
 
 1045  return it.findPackage( name_r );
 
 
 1059  return it.findPackage( name_r, ed_r );
 
 
 1074  it.findPackage( name_r );
 
 
 1094  it.findPackage( name_r, ed_r  );
 
 
 1105  struct RpmlogCapture : 
public std::vector<std::string>
 
 1109      rpmlogSetCallback( rpmLogCB, 
this );
 
 1110      _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
 
 1113    RpmlogCapture(
const RpmlogCapture &) = 
delete;
 
 1114    RpmlogCapture(RpmlogCapture &&) = 
delete;
 
 1115    RpmlogCapture &operator=(
const RpmlogCapture &) = 
delete;
 
 1116    RpmlogCapture &operator=(RpmlogCapture &&) = 
delete;
 
 1119      rpmlogSetCallback( 
nullptr, 
nullptr );
 
 1120      rpmlogSetMask( _oldMask );
 
 1123    static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
 
 1124    { 
return reinterpret_cast<RpmlogCapture*
>(data_r)->rpmLog( rec_r ); }
 
 1126    int rpmLog( rpmlogRec rec_r )
 
 1128      std::string l { ::rpmlogRecMessage( rec_r ) };  
 
 1130      push_back( std::move(l) );
 
 1138  std::ostream & 
operator<<( std::ostream & str, 
const RpmlogCapture & obj )
 
 1141    for ( 
const auto & l : obj ) {
 
 1142      if ( sep ) str << sep; 
else sep = 
'\n';
 
 1150                                               const Pathname & root_r,                 
 
 1151                                               bool  requireGPGSig_r,                   
 
 1154    PathInfo file( path_r );
 
 1155    if ( ! file.isFile() )
 
 1157      ERR << 
"Not a file: " << file << endl;
 
 1161    FD_t fd = ::Fopen( file.asString().c_str(), 
"r.ufdio" );
 
 1162    if ( fd == 0 || ::Ferror(fd) )
 
 1164      ERR << 
"Can't open file for reading: " << file << 
" (" << ::Fstrerror(fd) << 
")" << endl;
 
 1169    rpmts ts = ::rpmtsCreate();
 
 1170    ::rpmtsSetRootDir( ts, root_r.
c_str() );
 
 1171    ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
 
 1172#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP 
 1173    ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
 
 1176    RpmlogCapture vresult;
 
 1177    LocaleGuard guard( LC_ALL, 
"C" );   
 
 1178    static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0, 
sizeof(rpmQVKArguments_s) ); 
return qva; })();
 
 1179    int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
 
 1188    typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
 
 1189    static const ResultMap resultMap {
 
 1197    auto getresult = []( 
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
 
 1198      auto it = resultMap.find( key );
 
 1203    unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
 
 1208      SawHeaderSig     = (1 << 0),  
 
 1209      SawHeaderDigest  = (1 << 1),  
 
 1210      SawPayloadDigest = (1 << 2),  
 
 1212      SawDigest        = (1 << 4),  
 
 1214    unsigned saw = SawNone;
 
 1216    static const str::regex rx( 
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
 
 1218    for ( 
const std::string & line : vresult )
 
 1220      if ( line[0] != 
' ' ) 
 
 1226        lineres = getresult( resultMap, what[3] );
 
 1230        if ( what[1][0] == 
'H' ) {
 
 1231          saw |= ( what[2][0] == 
'S' ? SawHeaderSig :SawHeaderDigest );
 
 1233        else if ( what[1][0] == 
'P' ) {
 
 1234          if ( what[2][0] == 
'd' ) saw |= SawPayloadDigest;
 
 1237          saw |= ( what[2][0] == 
'S' ? SawSig : SawDigest );
 
 1242      detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, line ) );
 
 1264      bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
 
 1265      if ( not isSigned ) {
 
 1266        std::string message { 
"    " };
 
 1267        if ( not (saw & SawHeaderSig) )
 
 1268          message += 
_(
"Package header is not signed!");
 
 1270          message += 
_(
"Package payload is not signed!");
 
 1272        detail_r.push_back( RpmDb::CheckPackageDetail::value_type( 
RpmDb::CHK_NOSIG, std::move(message) ) );
 
 1273        if ( requireGPGSig_r )
 
 1282      bool didReadHeader = 
false;
 
 1283      std::unordered_map< std::string, std::string> fprs;
 
 1286      str::regex rxexpr( 
"key ID ([a-fA-F0-9]{8}):" );
 
 1287      for ( 
auto &detail : detail_r ) {
 
 1288        auto &line = detail.second;
 
 1292          if ( !didReadHeader ) {
 
 1293            didReadHeader = 
true;
 
 1298              auto keyMgr = zypp::KeyManagerCtx::createForOpenPGP();
 
 1299              const auto &addFprs = [&]( 
auto tag ){
 
 1300                const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
 
 1301                for ( 
const auto &
id : list1 ) {
 
 1302                  if ( 
id.size() <= 8 )
 
 1306                  fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
 
 1310              addFprs( RPMTAG_SIGGPG );
 
 1311              addFprs( RPMTAG_SIGPGP );
 
 1312              addFprs( RPMTAG_RSAHEADER );
 
 1313              addFprs( RPMTAG_DSAHEADER );
 
 1316              ERR << 
"Failed to read package signatures." << std::endl;
 
 1327            if ( 
const auto &i = fprs.find( keyId ); i != fprs.end() ) {
 
 1334      WAR << path_r << 
" (" << requireGPGSig_r << 
" -> " << ret << 
")" << endl;
 
 1335      WAR << vresult << endl;
 
 1338      DBG << path_r << 
" [0-Signature is OK]" << endl;
 
 1349{ 
return doCheckPackageSig( path_r, 
root(), 
false, detail_r ); }
 
 
 1355{ 
return doCheckPackageSig( path_r, 
root(), 
true, detail_r ); }
 
 
 1370  opts.push_back (
"-V");
 
 1371  opts.push_back (
"--nodeps");
 
 1372  opts.push_back (
"--noscripts");
 
 1373  opts.push_back (
"--nomd5");
 
 1374  opts.push_back (
"--");
 
 1375  opts.push_back (packageName.c_str());
 
 1396    if (line.length() > 12 &&
 
 1397        (line[0] == 
'S' || line[0] == 
's' ||
 
 1398         (line[0] == 
'.' && line[7] == 
'T')))
 
 1401      std::string filename;
 
 1403      filename.assign(line, 11, line.length() - 11);
 
 
 1443#if defined(WORKAROUNDRPMPWDBUG) 
 1444  args.push_back(
"#/");         
 
 1446  args.push_back(
"rpm");
 
 1447  args.push_back(
"--root");
 
 1448  args.push_back(
_root.asString().c_str());
 
 1449  args.push_back(
"--dbpath");
 
 1450  args.push_back(
_dbPath.asString().c_str());
 
 1452    args.push_back(
"-vv");
 
 1453  const char* argv[args.size() + opts.size() + 1];
 
 1455  const char** p = argv;
 
 1456  p = 
copy (args.begin (), args.end (), p);
 
 1457  p = 
copy (opts.begin (), opts.end (), p);
 
 1463  librpmDb::dbRelease( 
true );
 
 
 1483    process->setBlocking( 
false );
 
 1484    FILE * inputfile = 
process->inputFile();
 
 1489      const auto &readResult = 
io::receiveUpto( inputfile, 
'\n', 5 * 1000, 
false );
 
 1490      switch ( readResult.first ) {
 
 1496          line += readResult.second;
 
 1501          line += readResult.second;
 
 1502          if ( line.size() && line.back() == 
'\n')
 
 1507          line += readResult.second;
 
 1509          if ( line.size() && line.back() == 
'\n')
 
 1513            L_DBG(
"RPM_DEBUG") << line << endl;
 
 
 1557void RpmDb::processConfigFiles(
const std::string& line, 
const std::string& name, 
const char* typemsg, 
const char* difffailmsg, 
const char* diffgenmsg)
 
 1559  std::string msg = line.substr(9);
 
 1560  std::string::size_type pos1 = std::string::npos;
 
 1561  std::string::size_type pos2 = std::string::npos;
 
 1562  std::string file1s, file2s;
 
 1566  pos1 = msg.find (typemsg);
 
 1569    if ( pos1 == std::string::npos )
 
 1572    pos2 = pos1 + strlen (typemsg);
 
 1574    if (pos2 >= msg.length() )
 
 1577    file1 = msg.substr (0, pos1);
 
 1578    file2 = msg.substr (pos2);
 
 1585      file1 = 
_root + file1;
 
 1586      file2 = 
_root + file2;
 
 1596        ERR << 
"Could not create " << file.
asString() << endl;
 
 1600      std::ofstream notify(file.
asString().c_str(), std::ios::out|std::ios::app);
 
 1603        ERR << 
"Could not open " <<  file << endl;
 
 1609      notify << 
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
 
 1612        ERR << 
"diff failed" << endl;
 
 1614                            file1s.c_str(), file2s.c_str()) << endl;
 
 1619                            file1s.c_str(), file2s.c_str()) << endl;
 
 1624          if (out.substr(0,4) == 
"--- ")
 
 1626            out.replace(4, file1.
asString().length(), file1s);
 
 1628          std::string::size_type pos = out.find(
"\n+++ ");
 
 1629          if (pos != std::string::npos)
 
 1631            out.replace(pos+5, file2.
asString().length(), file2s);
 
 1634        notify << out << endl;
 
 1637      notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
 
 1642      WAR << 
"rpm created " << file2 << 
" but it is not different from " << file2 << endl;
 
 
 1662  report->start(filename);
 
 1677        report->finish( excpt_r );
 
 
 1693  MIL << 
"RpmDb::installPackage(" << filename << 
"," << flags << 
")" << endl;
 
 1701      ERR << 
"backup of " << filename.
asString() << 
" failed" << endl;
 
 1704    report->progress( 0 ); 
 
 1709  if ( postTransCollector_r && ( 
_root == 
"/" || not workaroundDUMPPOSTTRANS_BUG_1216091() ) ) {
 
 1710    opts.push_back(
"--define");           
 
 1711    opts.push_back(
"_dump_posttrans 1");  
 
 1714    opts.push_back(
"-i");
 
 1716    opts.push_back(
"-U");
 
 1718  opts.push_back(
"--percent");
 
 1719  opts.push_back(
"--noglob");
 
 1723    opts.push_back(
"--ignorearch");
 
 1726    opts.push_back(
"--nodigest");
 
 1728    opts.push_back(
"--nosignature");
 
 1730    opts.push_back (
"--excludedocs");
 
 1732    opts.push_back (
"--noscripts");
 
 1734    opts.push_back (
"--force");
 
 1736    opts.push_back (
"--nodeps");
 
 1738    opts.push_back (
"--ignoresize");
 
 1740    opts.push_back (
"--justdb");
 
 1742    opts.push_back (
"--test");
 
 1744    opts.push_back (
"--noposttrans");
 
 1746  opts.push_back(
"--");
 
 1749  std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
 
 1750  opts.push_back ( quotedFilename.c_str() );
 
 1755  unsigned    lineno = 0;
 
 1758  cmdout.
set( 
"line",   std::cref(line) );
 
 1759  cmdout.
set( 
"lineno", lineno );
 
 1763  std::vector<std::string> configwarnings;      
 
 1771      sscanf( line.c_str() + 2, 
"%d", &percent );
 
 1772      report->progress( percent );
 
 1780    cmdout.
set( 
"lineno", lineno );
 
 1781    report->report( cmdout );
 
 1784      if ( line.find( 
" scriptlet failed, " ) == std::string::npos )    
 
 1788    rpmmsg += line+
'\n';
 
 1791      configwarnings.push_back(line);
 
 1794    rpmmsg += 
"[truncated]\n";
 
 1797  if ( postTransCollector_r && rpm_status == 0 ) {
 
 1803  for (std::vector<std::string>::iterator it = configwarnings.begin();
 
 1804       it != configwarnings.end(); ++it)
 
 1808                       _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
 
 1810                       _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
 
 1813                       _(
"rpm created %s as %s, but it was impossible to determine the difference"),
 
 1815                       _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
 
 1818  if ( rpm_status != 0 )
 
 1823    std::ostringstream sstr;
 
 1824    sstr << 
"rpm output:" << endl << rpmmsg << endl;
 
 1825    historylog.
comment(sstr.str());
 
 1828    if ( not rpmmsg.empty() )
 
 1829      excpt.addHistory( rpmmsg );
 
 1832  else if ( ! rpmmsg.empty() )
 
 1837    std::ostringstream sstr;
 
 1838    sstr << 
"Additional rpm output:" << endl << rpmmsg << endl;
 
 1839    historylog.
comment(sstr.str());
 
 1843    report->finishInfo(
str::form( 
"%s:\n%s\n", 
_(
"Additional rpm output"),  rpmmsg.c_str() ));
 
 
 1860                 + 
"-" + package->edition().version()
 
 1861                 + 
"-" + package->edition().release()
 
 1862                 + 
"." + package->arch().asString(), flags, postTransCollector_r );
 
 
 1869  report->start( name_r );
 
 1884        report->finish( excpt_r );
 
 
 1900  MIL << 
"RpmDb::doRemovePackage(" << name_r << 
"," << flags << 
")" << endl;
 
 1909      ERR << 
"backup of " << name_r << 
" failed" << endl;
 
 1911    report->progress( 0 );
 
 1915    report->progress( 100 );
 
 1920  if ( postTransCollector_r && ( 
_root == 
"/" || not workaroundDUMPPOSTTRANS_BUG_1216091() ) ) {
 
 1921    opts.push_back(
"--define");           
 
 1922    opts.push_back(
"_dump_posttrans 1");  
 
 1924  opts.push_back(
"-e");
 
 1925  opts.push_back(
"--allmatches");
 
 1928    opts.push_back(
"--noscripts");
 
 1930    opts.push_back(
"--nodeps");
 
 1932    opts.push_back(
"--justdb");
 
 1934    opts.push_back (
"--test");
 
 1937    WAR << 
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
 
 1940  opts.push_back(
"--");
 
 1941  opts.push_back(name_r.c_str());
 
 1946  unsigned    lineno = 0;
 
 1949  cmdout.
set( 
"line",   std::cref(line) );
 
 1950  cmdout.
set( 
"lineno", lineno );
 
 1961  report->progress( 5 );
 
 1969    cmdout.
set( 
"lineno", lineno );
 
 1970    report->report( cmdout );
 
 1973      if ( line.find( 
" scriptlet failed, " ) == std::string::npos )    
 
 1976    rpmmsg += line+
'\n';
 
 1979    rpmmsg += 
"[truncated]\n";
 
 1980  report->progress( 50 );
 
 1982  if ( postTransCollector_r && rpm_status == 0 ) {
 
 1988  if ( rpm_status != 0 )
 
 1991        str::form(
"%s remove failed", name_r.c_str()), 
true );
 
 1992    std::ostringstream sstr;
 
 1993    sstr << 
"rpm output:" << endl << rpmmsg << endl;
 
 1994    historylog.
comment(sstr.str());
 
 1997    if ( not rpmmsg.empty() )
 
 1998      excpt.addHistory( rpmmsg );
 
 2001  else if ( ! rpmmsg.empty() )
 
 2004        str::form(
"%s removed ok", name_r.c_str()), 
true );
 
 2006    std::ostringstream sstr;
 
 2007    sstr << 
"Additional rpm output:" << endl << rpmmsg << endl;
 
 2008    historylog.
comment(sstr.str());
 
 2012    report->finishInfo(
str::form( 
"%s:\n%s\n", 
_(
"Additional rpm output"),  rpmmsg.c_str() ));
 
 
 2025  MIL << 
"RpmDb::runposttrans(" << filename_r << 
")" << endl;
 
 2033  std::string _tmppath { 
"_tmppath " + filename_r.
dirname().
asString() };
 
 2034  opts.push_back(
"--define");
 
 2035  opts.push_back(_tmppath.c_str());
 
 2037  opts.push_back(
"-vv");  
 
 2038  opts.push_back(
"--runposttrans");
 
 2039  opts.push_back(filename_r.
c_str());
 
 2046  static const str::regex rx( 
"^D: (%.*): (scriptlet start|running .* scriptlet)" );
 
 2047  static const str::regex rx2( 
"^Running (%[^)]*[)])$" );
 
 2059        DBG << 
"Verbose RIPOFF:"+what[1] << endl;
 
 2060        output_r( 
"RIPOFF:"+what[1] );
 
 2068      DBG << 
"NonVerbose RIPOFF:"+what[1] << endl;
 
 2085  if ( rpm_status != 0 ) {
 
 2086    WAR << 
"rpm --runposttrans returned " << rpm_status << endl;
 
 
 2121    INT << 
"_backuppath empty" << endl;
 
 2129    ERR << 
"Error while getting changed files for package " <<
 
 2130    packageName << endl;
 
 2136    DBG <<  
"package " <<  packageName << 
" not changed -> no backup" << endl;
 
 2147    time_t currentTime = time(0);
 
 2148    struct tm *currentLocalTime = localtime(¤tTime);
 
 2150    int date = (currentLocalTime->tm_year + 1900) * 10000
 
 2151               + (currentLocalTime->tm_mon + 1) * 100
 
 2152               + currentLocalTime->tm_mday;
 
 2158                       + 
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
 
 2161    while ( 
PathInfo(backupFilename).isExist() && num++ < 1000);
 
 2166      ERR << filestobackupfile.
asString() << 
" already exists and is no file" << endl;
 
 2170    std::ofstream fp ( filestobackupfile.
asString().c_str(), std::ios::out|std::ios::trunc );
 
 2174      ERR << 
"could not open " << filestobackupfile.
asString() << endl;
 
 2178    for (FileList::const_iterator cit = 
fileList.begin();
 
 2181      std::string name = *cit;
 
 2182      if ( name[0] == 
'/' )
 
 2185        name = name.substr( 1 );
 
 2187      DBG << 
"saving file "<< name << endl;
 
 2192    const char* 
const argv[] =
 
 2197        _root.asString().c_str(),
 
 2198        "--ignore-failed-read",
 
 2202        filestobackupfile.
asString().c_str(),
 
 2218    int ret = tar.
close();
 
 2222      ERR << 
"tar failed: " << tarmsg << endl;
 
 2227      MIL << 
"tar backup ok" << endl;
 
 
 2248#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break 
 2250    OUTS( CHK_OK,           
_(
"Signature is OK") );
 
 2252    OUTS( CHK_NOTFOUND,             
_(
"Unknown type of signature") );
 
 2254    OUTS( CHK_FAIL,         
_(
"Signature does not verify") );
 
 2256    OUTS( CHK_NOTTRUSTED,   
_(
"Signature is OK, but key is not trusted") );
 
 2258    OUTS( CHK_NOKEY,                
_(
"Signatures public key is not available") );
 
 2260    OUTS( CHK_ERROR,                
_(
"File does not exist or signature can't be checked") );
 
 2262    OUTS( CHK_NOSIG,                
_(
"File is unsigned") );
 
 
 2270  for ( 
const auto & el : obj )
 
 2271    str << el.second << endl;
 
 
#define MAXRPMMESSAGELINES
#define FAILIFNOTINITIALIZED
#define FILEFORBACKUPFILES
Store and operate on date (time_t).
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
static Date now()
Return the current time.
Assign a vaiable a certain value when going out of scope.
Edition represents [epoch:]version[-release]
std::string version() const
Version.
std::string release() const
Release.
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Base class for Exception.
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
void addHistory(const std::string &msg_r)
Add some message text to the history.
void moveToHistory(TContainer &&msgc_r)
addHistory from string container types (oldest first) moving
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
int close() override
Wait for the progamm to complete.
Stderr_Disposition
Define symbols for different policies on the handling of stderr.
Writing the zypp history file.
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
std::string asString() const
TraitsType::constPtrType constPtr
std::string basename() const
Return the last component of this path.
Maintain [min,max] and counter (value) for progress counting.
value_type reportValue() const
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
bool toMax()
Set counter value to current max value (unless no range).
bool incr(value_type val_r=1)
Increment counter value (default by 1).
bool toMin()
Set counter value to current min value.
void range(value_type max_r)
Set new [0,max].
static ZConfig & instance()
Singleton ctor.
ZYpp::Ptr getZYpp()
Convenience to get the Pointer to the ZYpp instance.
Typesafe passing of user data via callbacks.
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
std::string receiveLine()
Read one line from the input stream.
Wrapper class for stat/lstat.
bool isExist() const
Return whether valid stat info exists.
Pathname dirname() const
Return all but the last component od this path.
const char * c_str() const
String representation.
const std::string & asString() const
String representation.
std::string basename() const
Return the last component of this path.
bool empty() const
Test for an empty path.
bool relative() const
Test for a relative path.
Provide a new empty temporary file and delete it when no longer needed.
Regular expression match result.
Extract and remember posttrans scripts for later execution.
void collectPosttransInfo(const Pathname &rpmPackage_r, const std::vector< std::string > &runposttrans_r)
Extract and remember a packages posttrans script or dump_posttrans lines for later execution.
bool hasPosttransScript(const Pathname &rpmPackage_r)
Test whether a package defines a posttrans script.
Interface to the rpm program.
void getData(const std::string &name_r, RpmHeader::constPtr &result_r) const
Get an installed packages data from rpmdb.
void doRebuildDatabase(callback::SendReport< RebuildDBReport > &report)
bool queryChangedFiles(FileList &fileList, const std::string &packageName)
determine which files of an installed package have been modified.
std::string error_message
Error message from running rpm as external program.
bool hasRequiredBy(const std::string &tag_r) const
Return true if at least one package requires a certain tag.
std::vector< const char * > RpmArgVec
std::string whoOwnsFile(const std::string &file_r) const
Return name of package owning file or empty string if no installed package owns file.
void exportTrustedKeysInZyppKeyRing()
insert all rpm trusted keys into zypp trusted keyring
void importPubkey(const PublicKey &pubkey_r)
Import ascii armored public key in file pubkey_r.
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
Pathname _backuppath
/var/adm/backup
std::ostream & dumpOn(std::ostream &str) const override
Dump debug info.
void run_rpm(const RpmArgVec &options, ExternalProgram::Stderr_Disposition stderr_disp=ExternalProgram::Stderr_To_Stdout)
Run rpm with the specified arguments and handle stderr.
void initDatabase(Pathname root_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database below root_r.
int runposttrans(const Pathname &filename_r, const std::function< void(const std::string &)> &output_r)
Run collected posttrans and transfiletrigger(postun|in) if rpm --runposttrans is supported.
ExternalProgram * process
The connection to the rpm process.
SyncTrustedKeyBits
Sync mode for syncTrustedKeys.
@ SYNC_TO_KEYRING
export rpm trusted keys into zypp trusted keyring
@ SYNC_FROM_KEYRING
import zypp trusted keys into rpm database.
~RpmDb() override
Destructor.
std::list< PublicKey > pubkeys() const
Return the long ids of all installed public keys.
std::set< Edition > pubkeyEditions() const
Return the edition of all installed public keys.
int systemStatus()
Return the exit status of the general rpm process, closing the connection if not already done.
std::set< std::string > FileList
CheckPackageResult checkPackageSignature(const Pathname &path_r, CheckPackageDetail &detail_r)
Check signature of rpm file on disk (strict check returning CHK_NOSIG if file is unsigned).
bool backupPackage(const std::string &packageName)
create tar.gz of all changed files in a Package
bool hasProvides(const std::string &tag_r) const
Return true if at least one package provides a certain tag.
void systemKill()
Forcably kill the system process.
const Pathname & root() const
void removePubkey(const PublicKey &pubkey_r)
Remove a public key from the rpm database.
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
db_const_iterator dbConstIterator() const
std::list< FileInfo > fileList(const std::string &name_r, const Edition &edition_r) const
return complete file list for installed package name_r (in FileInfo.filename) if edition_r !...
const Pathname & dbPath() const
Pathname _dbPath
Directory that contains the rpmdb.
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
void setBackupPath(const Pathname &path)
set path where package backups are stored
bool _packagebackups
create package backups?
CheckPackageResult checkPackage(const Pathname &path_r, CheckPackageDetail &detail_r)
Check signature of rpm file on disk (legacy version returning CHK_OK if file is unsigned,...
void importZyppKeyRingTrustedKeys()
iterates through zypp keyring and import all non-existent keys into rpm keyring
void doInstallPackage(const Pathname &filename, RpmInstFlags flags, RpmPostTransCollector *postTransCollector_r, callback::SendReport< RpmInstallReport > &report)
Pathname _root
Root directory for all operations.
bool hasConflicts(const std::string &tag_r) const
Return true if at least one package conflicts with a certain tag.
int exit_code
The exit code of the rpm process, or -1 if not yet known.
void syncTrustedKeys(SyncTrustedKeyBits mode_r=SYNC_BOTH)
Sync trusted keys stored in rpm database and zypp trusted keyring.
void processConfigFiles(const std::string &line, const std::string &name, const char *typemsg, const char *difffailmsg, const char *diffgenmsg)
handle rpm messages like "/etc/testrc saved as /etc/testrc.rpmorig"
CheckPackageResult
checkPackage result
bool hasPackage(const std::string &name_r) const
Return true if package is installed.
void doRemovePackage(const std::string &name_r, RpmInstFlags flags, RpmPostTransCollector *postTransCollector_r, callback::SendReport< RpmRemoveReport > &report)
bool systemReadLine(std::string &line)
Read a line from the general rpm query.
void rebuildDatabase()
Rebuild the rpm database (rpm –rebuilddb).
bool hasFile(const std::string &file_r, const std::string &name_r="") const
Return true if at least one package owns a certain file (name_r empty) Return true if package name_r ...
Just inherits Exception to separate media exceptions.
Subclass to retrieve rpm database content.
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
static librpmDb::constPtr dbOpenCreate(const Pathname &root_r, const Pathname &dbPath_r=Pathname())
Assert the rpmdb below the system at root_r exists.
static Pathname suggestedDbPath(const Pathname &root_r)
String related utilities and Regular expression matching.
@ Edition
Editions with v-r setparator highlighted.
Namespace intended to collect all environment variables we use.
Types and functions for filesystem operations.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
int copy(const Pathname &file, const Pathname &dest)
Like 'cp file dest'.
Pathname expandlink(const Pathname &path_r)
Recursively follows the symlink pointed to by path_r and returns the Pathname to the real file or dir...
int unlink(const Pathname &path)
Like 'unlink'.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
std::string numstring(char n, int w=0)
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
std::string toLower(const std::string &s)
Return lowercase version of s.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
\relates regex \ingroup ZYPP_STR_REGEX    \relates regex \ingroup ZYPP_STR_REGEX
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
unsigned diffFiles(const std::string &file1, const std::string &file2, std::string &out, int maxlines)
std::ostream & operator<<(std::ostream &str, const librpmDb::db_const_iterator &obj)
_dumpPath dumpPath(const Pathname &root_r, const Pathname &sub_r)
dumpPath iomaip to dump '(root_r)sub_r' output,
static shared_ptr< KeyRingSignalReceiver > sKeyRingReceiver
Easy-to use interface to the ZYPP dependency resolver.
Temporarily connect a ReceiveReport then restore the previous one.
KeyRingSignalReceiver & operator=(const KeyRingSignalReceiver &)=delete
void trustedKeyRemoved(const PublicKey &key) override
KeyRingSignalReceiver & operator=(KeyRingSignalReceiver &&)=delete
KeyRingSignalReceiver(const KeyRingSignalReceiver &)=delete
KeyRingSignalReceiver(RpmDb &rpmdb)
void trustedKeyAdded(const PublicKey &key) override
~KeyRingSignalReceiver() override
KeyRingSignalReceiver(KeyRingSignalReceiver &&)=delete
Detailed rpm signature check log messages A single multiline message if CHK_OK.
Wrapper providing a librpmDb::db_const_iterator for this RpmDb.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.