15#include <rpm/rpmcli.h>
16#include <rpm/rpmlog.h>
32#include <zypp-core/base/StringV.h>
33#include <zypp/base/Logger.h>
34#include <zypp/base/String.h>
35#include <zypp/base/Gettext.h>
37#include <zypp-core/base/DtorReset>
40#include <zypp/Pathname.h>
41#include <zypp/PathInfo.h>
43#include <zypp-core/ui/ProgressData>
52#include <zypp/TmpPath.h>
57#include <zypp/base/IOTools.h>
62#define WARNINGMAILPATH "/var/log/YaST2/"
63#define FILEFORBACKUPFILES "YaSTBackupModifiedFiles"
64#define MAXRPMMESSAGELINES 10000
66#define WORKAROUNDRPMPWDBUG
68#undef ZYPP_BASE_LOGGER_LOGGROUP
69#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb"
73 namespace zypp_readonly_hack
81 static bool val = [](){
82 const char * env = getenv(
"ZYPP_RPM_DEBUG");
98const char* quoteInFilename_m =
"\'\"";
100const char* quoteInFilename_m =
" \t\'\"";
102inline std::string rpmQuoteFilename(
const Pathname & path_r )
104 std::string path( path_r.
asString() );
105 for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m );
106 pos != std::string::npos;
107 pos = path.find_first_of( quoteInFilename_m, pos ) )
109 path.insert( pos,
"\\" );
122#if defined(WORKAROUNDRPMPWDBUG)
129 WAR <<
"Can't get cwd!" << endl;
150 MIL <<
"trusted key added to zypp Keyring. Importing..." << endl;
156 MIL <<
"Trusted key removed from zypp Keyring. Removing..." << endl;
165unsigned diffFiles(
const std::string file1,
const std::string file2, std::string& out,
int maxlines)
186 if (maxlines<0?
true:count<maxlines)
212#define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); }
223 : _backuppath (
"/var/adm/backup")
224 , _packagebackups(false)
231 setenv(
"RPM_IgnoreFailedSymlinks",
"1", 1 );
243 MIL <<
"~RpmDb()" << endl;
246 MIL <<
"~RpmDb() end" << endl;
272 bool quickinit( root_r.
empty() );
274 if ( root_r.
empty() )
282 if ( dbPath_r !=
"/var/lib/rpm" && !
PathInfo( root_r/
"/var/lib/rpm" ).isExist() )
284 WAR <<
"Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
298 if ( root_r ==
_root ) {
306 MIL <<
"Calling initDatabase: " <<
stringPath( root_r, dbPath_r )
307 << ( doRebuild_r ?
" (rebuilddb)" :
"" )
308 << ( quickinit ?
" (quickinit)" :
"" ) << endl;
317 MIL <<
"QUICK initDatabase (no systemRoot set)" << endl;
339 MIL <<
"Synchronizing keys with zypp keyring" << endl;
348 MIL <<
"InitDatabase: " << *
this << endl;
364 MIL <<
"Calling closeDatabase: " << *
this << endl;
376 MIL <<
"closeDatabase: " << *
this << endl;
406 MIL <<
"RpmDb::rebuildDatabase" << *
this << endl;
420 opts.push_back(
"--rebuilddb");
421 opts.push_back(
"-vv");
431 tics.
range( hdrTotal );
434 return report->progress( tics_r.
reportValue(), mydbpath );
442 static const std::string debugPrefix {
"D:" };
443 static const std::string progressPrefix {
"D: read h#" };
444 static const std::string ignoreSuffix {
"digest: OK" };
459 WAR <<
"User requested abort." << endl;
483 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
494 void updateIf(
const Edition & rpmKey_r )
496 std::string keyRelease( rpmKey_r.
release() );
497 int comp = _release.compare( keyRelease );
501 _release.swap( keyRelease );
502 _inRpmKeys = &rpmKey_r;
503 _inZyppKeys =
nullptr;
504 if ( !keyRelease.empty() )
505 DBG <<
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
507 else if ( comp == 0 )
511 _inRpmKeys = &rpmKey_r;
515 DBG <<
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
521 int comp = _release.compare( keyRelease );
525 _release.swap( keyRelease );
526 _inRpmKeys =
nullptr;
527 _inZyppKeys = &zyppKey_r;
528 if ( !keyRelease.empty() )
529 DBG <<
"Old key in R: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
531 else if ( comp == 0 )
535 _inZyppKeys = &zyppKey_r;
539 DBG <<
"Old key in Z: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
542 std::string _release;
549 std::map<std::string,Key> _keymap;
551 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
553 _keymap[(*it).version()].updateIf( *it );
556 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
558 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
562 std::set<Edition> rpmKeys;
563 std::list<PublicKeyData> zyppKeys;
564 for_( it, _keymap.begin(), _keymap.end() )
566 DBG <<
"gpg-pubkey-" << (*it).first <<
"-" << (*it).second._release <<
" "
567 << ( (*it).second._inRpmKeys ?
"R" :
"_" )
568 << ( (*it).second._inZyppKeys ?
"Z" :
"_" ) << endl;
569 if ( ! (*it).second._inRpmKeys )
571 zyppKeys.push_back( *(*it).second._inZyppKeys );
573 if ( ! (*it).second._inZyppKeys )
575 rpmKeys.insert( *(*it).second._inRpmKeys );
578 rpmKeys_r.swap( rpmKeys );
579 zyppKeys_r.swap( zyppKeys );
586 MIL <<
"Going to sync trusted keys..." << endl;
588 std::list<PublicKeyData> zyppKeys( getZYpp()->keyRing()->trustedPublicKeyData() );
600 MIL <<
"Removing excess keys in zypp trusted keyring" << std::endl;
606 if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) )
608 DBG <<
"Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl;
609 getZYpp()->keyRing()->deleteKey( keyData.id(),
true );
610 if ( !dirty ) dirty =
true;
614 zyppKeys = getZYpp()->keyRing()->trustedPublicKeyData();
617 computeKeyRingSync( rpmKeys, zyppKeys );
618 MIL << (mode_r &
SYNC_TO_KEYRING ?
"" :
"(skip) ") <<
"Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
619 MIL << (mode_r &
SYNC_FROM_KEYRING ?
"" :
"(skip) ") <<
"Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
625 MIL <<
"Exporting rpm keyring into zypp trusted keyring" <<endl;
630 TmpFile tmpfile( getZYpp()->tmpPath() );
632 std::ofstream tmpos( tmpfile.
path().
c_str() );
633 for_( it, rpmKeys.begin(), rpmKeys.end() )
637 getData(
"gpg-pubkey", *it, result );
638 tmpos << result->tag_description() << endl;
643 getZYpp()->keyRing()->multiKeyImport( tmpfile.
path(),
true );
647 std::set<Edition> missingKeys;
648 for (
const Edition & key : rpmKeys )
650 if ( getZYpp()->keyRing()->isKeyTrusted( key.version() ) )
652 ERR <<
"Could not import key:" <<
str::Format(
"gpg-pubkey-%s") % key <<
" into zypp keyring (V3 key?)" << endl;
653 missingKeys.insert( key );
655 if ( ! missingKeys.empty() )
661 ERR <<
"Could not import keys into zypp keyring: " << endl;
669 MIL <<
"Importing zypp trusted keyring" << std::endl;
670 for_( it, zyppKeys.begin(), zyppKeys.end() )
674 importPubkey( getZYpp()->keyRing()->exportTrustedPublicKey( *it ) );
682 MIL <<
"Trusted keys synced." << endl;
704 WAR <<
"Key " << pubkey_r <<
" can not be imported. (READONLY MODE)" << endl;
711 bool hasOldkeys =
false;
713 for_( it, rpmKeys.begin(), rpmKeys.end() )
722 MIL <<
"Key " << pubkey_r <<
" is already in the rpm trusted keyring. (skip import)" << endl;
726 if ( keyEd.
version() != (*it).version() )
729 if ( keyEd.
release() < (*it).release() )
731 MIL <<
"Key " << pubkey_r <<
" is older than one in the rpm trusted keyring. (skip import)" << endl;
739 MIL <<
"Key " << pubkey_r <<
" will be imported into the rpm trusted keyring." << (hasOldkeys?
"(update)":
"(new)") << endl;
745 std::string keyName(
"gpg-pubkey-" + keyEd.
version() );
747 opts.push_back (
"-e" );
748 opts.push_back (
"--allmatches" );
749 opts.push_back (
"--" );
750 opts.push_back ( keyName.c_str() );
761 ERR <<
"Failed to remove key " << pubkey_r <<
" from RPM trusted keyring (ignored)" << endl;
765 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
771 opts.push_back (
"--import" );
772 opts.push_back (
"--" );
774 opts.push_back ( pubkeypath.c_str() );
778 std::vector<std::string> excplines;
784 excplines.push_back( std::move(line) );
800 MIL <<
"Key " << pubkey_r <<
" imported in rpm trusted keyring." << endl;
817 std::set<Edition>::const_iterator found_edition = rpm_keys.end();
820 for_( it, rpm_keys.begin(), rpm_keys.end() )
822 if ( (*it).version() == pubkeyVersion )
830 if (found_edition == rpm_keys.end())
832 WAR <<
"Key " << pubkey_r.
id() <<
" is not in rpm db" << endl;
836 std::string rpm_name(
"gpg-pubkey-" + found_edition->asString());
839 opts.push_back (
"-e" );
840 opts.push_back (
"--" );
841 opts.push_back ( rpm_name.c_str() );
845 std::vector<std::string> excplines;
851 excplines.push_back( std::move(line) );
867 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
879 std::list<PublicKey> ret;
882 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
884 Edition edition = it->tag_edition();
889 getData(
"gpg-pubkey", edition, result );
890 TmpFile file(getZYpp()->tmpPath());
896 os << result->tag_description();
905 catch ( std::exception & e )
907 ERR <<
"Could not dump key " << edition.
asString() <<
" in tmp file " << file.
path() << endl;
917 std::set<Edition> ret;
920 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
922 Edition edition = it->tag_edition();
924 ret.insert( edition );
941 std::list<FileInfo> result;
968bool RpmDb::hasFile(
const std::string & file_r,
const std::string & name_r )
const
978 res = (it->tag_name() == name_r);
999 return it->tag_name();
1113 struct RpmlogCapture :
public std::vector<std::string>
1117 rpmlogSetCallback( rpmLogCB,
this );
1118 _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
1123 rpmlogSetCallback(
nullptr,
nullptr );
1124 rpmlogSetMask( _oldMask );
1127 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1128 {
return reinterpret_cast<RpmlogCapture*
>(data_r)->rpmLog( rec_r ); }
1130 int rpmLog( rpmlogRec rec_r )
1132 std::string l { ::rpmlogRecMessage( rec_r ) };
1134 push_back( std::move(l) );
1142 std::ostream &
operator<<( std::ostream &
str,
const RpmlogCapture & obj )
1145 for (
const auto & l : obj ) {
1146 if ( sep )
str << sep;
else sep =
'\n';
1155 bool requireGPGSig_r,
1156 RpmDb::CheckPackageDetail & detail_r )
1159 if ( ! file.isFile() )
1161 ERR <<
"Not a file: " << file << endl;
1165 FD_t fd = ::Fopen( file.asString().c_str(),
"r.ufdio" );
1166 if ( fd == 0 || ::Ferror(fd) )
1168 ERR <<
"Can't open file for reading: " << file <<
" (" << ::Fstrerror(fd) <<
")" << endl;
1173 rpmts ts = ::rpmtsCreate();
1174 ::rpmtsSetRootDir( ts, root_r.
c_str() );
1175 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1176#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP
1177 ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
1180 RpmlogCapture vresult;
1182 static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0,
sizeof(rpmQVKArguments_s) );
return qva; })();
1183 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
1192 typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
1193 static const ResultMap resultMap {
1201 auto getresult = [](
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1202 auto it = resultMap.find( key );
1207 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1212 SawHeaderSig = (1 << 0),
1213 SawHeaderDigest = (1 << 1),
1214 SawPayloadDigest = (1 << 2),
1216 SawDigest = (1 << 4),
1218 unsigned saw = SawNone;
1220 static const str::regex rx(
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1222 for (
const std::string & line : vresult )
1224 if ( line[0] !=
' ' )
1230 lineres = getresult( resultMap, what[3] );
1234 if ( what[1][0] ==
'H' ) {
1235 saw |= ( what[2][0] ==
'S' ? SawHeaderSig :SawHeaderDigest );
1237 else if ( what[1][0] ==
'P' ) {
1238 if ( what[2][0] ==
'd' ) saw |= SawPayloadDigest;
1241 saw |= ( what[2][0] ==
'S' ? SawSig : SawDigest );
1246 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, std::move(line) ) );
1268 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1269 if ( not isSigned ) {
1270 std::string message {
" " };
1271 if ( not (saw & SawHeaderSig) )
1272 message +=
_(
"Package header is not signed!");
1274 message +=
_(
"Package payload is not signed!");
1276 detail_r.push_back( RpmDb::CheckPackageDetail::value_type(
RpmDb::CHK_NOSIG, std::move(message) ) );
1277 if ( requireGPGSig_r )
1286 bool didReadHeader =
false;
1287 std::unordered_map< std::string, std::string> fprs;
1290 str::regex rxexpr(
"key ID ([a-fA-F0-9]{8}):" );
1291 for (
auto &detail : detail_r ) {
1292 auto &line = detail.second;
1296 if ( !didReadHeader ) {
1297 didReadHeader =
true;
1303 const auto &addFprs = [&](
auto tag ){
1304 const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
1305 for (
const auto &
id : list1 ) {
1306 if (
id.size() <= 8 )
1310 fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
1314 addFprs( RPMTAG_SIGGPG );
1315 addFprs( RPMTAG_SIGPGP );
1316 addFprs( RPMTAG_RSAHEADER );
1317 addFprs( RPMTAG_DSAHEADER );
1320 ERR <<
"Failed to read package signatures." << std::endl;
1331 if (
const auto &i = fprs.find( keyId ); i != fprs.end() ) {
1338 WAR << path_r <<
" (" << requireGPGSig_r <<
" -> " << ret <<
")" << endl;
1339 WAR << vresult << endl;
1342 DBG << path_r <<
" [0-Signature is OK]" << endl;
1353{
return doCheckPackageSig( path_r,
root(),
false, detail_r ); }
1359{
return doCheckPackageSig( path_r,
root(),
true, detail_r ); }
1374 opts.push_back (
"-V");
1375 opts.push_back (
"--nodeps");
1376 opts.push_back (
"--noscripts");
1377 opts.push_back (
"--nomd5");
1378 opts.push_back (
"--");
1379 opts.push_back (packageName.c_str());
1400 if (line.length() > 12 &&
1401 (line[0] ==
'S' || line[0] ==
's' ||
1402 (line[0] ==
'.' && line[7] ==
'T')))
1405 std::string filename;
1407 filename.assign(line, 11, line.length() - 11);
1447#if defined(WORKAROUNDRPMPWDBUG)
1448 args.push_back(
"#/");
1450 args.push_back(
"rpm");
1451 args.push_back(
"--root");
1453 args.push_back(
"--dbpath");
1456 args.push_back(
"-vv");
1457 const char* argv[args.size() + opts.size() + 1];
1459 const char** p = argv;
1460 p =
copy (args.begin (), args.end (), p);
1461 p =
copy (opts.begin (), opts.end (), p);
1491 const auto &readResult =
io::receiveUpto( inputfile,
'\n', 5 * 1000,
false );
1492 switch ( readResult.first ) {
1498 line += readResult.second;
1503 line += readResult.second;
1504 if ( line.size() && line.back() ==
'\n')
1509 line += readResult.second;
1511 if ( line.size() && line.back() ==
'\n')
1515 L_DBG(
"RPM_DEBUG") << line << endl;
1559void RpmDb::processConfigFiles(
const std::string& line,
const std::string& name,
const char* typemsg,
const char* difffailmsg,
const char* diffgenmsg)
1561 std::string msg = line.substr(9);
1562 std::string::size_type pos1 = std::string::npos;
1563 std::string::size_type pos2 = std::string::npos;
1564 std::string file1s, file2s;
1568 pos1 = msg.find (typemsg);
1571 if ( pos1 == std::string::npos )
1574 pos2 = pos1 + strlen (typemsg);
1576 if (pos2 >= msg.length() )
1579 file1 = msg.substr (0, pos1);
1580 file2 = msg.substr (pos2);
1587 file1 =
_root + file1;
1588 file2 =
_root + file2;
1598 ERR <<
"Could not create " << file.
asString() << endl;
1602 std::ofstream notify(file.
asString().c_str(), std::ios::out|std::ios::app);
1605 ERR <<
"Could not open " << file << endl;
1611 notify <<
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
1614 ERR <<
"diff failed" << endl;
1616 file1s.c_str(), file2s.c_str()) << endl;
1621 file1s.c_str(), file2s.c_str()) << endl;
1626 if (out.substr(0,4) ==
"--- ")
1628 out.replace(4, file1.
asString().length(), file1s);
1630 std::string::size_type pos = out.find(
"\n+++ ");
1631 if (pos != std::string::npos)
1633 out.replace(pos+5, file2.
asString().length(), file2s);
1636 notify << out << endl;
1639 notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1644 WAR <<
"rpm created " << file2 <<
" but it is not different from " << file2 << endl;
1664 report->start(filename);
1679 report->finish( excpt_r );
1695 MIL <<
"RpmDb::installPackage(" << filename <<
"," << flags <<
")" << endl;
1703 ERR <<
"backup of " << filename.
asString() <<
" failed" << endl;
1706 report->progress( 0 );
1711 if ( postTransCollector_r ) {
1712 opts.push_back(
"--define");
1713 opts.push_back(
"_dump_posttrans 1");
1716 opts.push_back(
"-i");
1718 opts.push_back(
"-U");
1720 opts.push_back(
"--percent");
1721 opts.push_back(
"--noglob");
1725 opts.push_back(
"--ignorearch");
1728 opts.push_back(
"--nodigest");
1730 opts.push_back(
"--nosignature");
1732 opts.push_back (
"--excludedocs");
1734 opts.push_back (
"--noscripts");
1736 opts.push_back (
"--force");
1738 opts.push_back (
"--nodeps");
1740 opts.push_back (
"--ignoresize");
1742 opts.push_back (
"--justdb");
1744 opts.push_back (
"--test");
1746 opts.push_back (
"--noposttrans");
1748 opts.push_back(
"--");
1751 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
1752 opts.push_back ( quotedFilename.c_str() );
1757 unsigned lineno = 0;
1760 cmdout.
set(
"line", std::cref(line) );
1761 cmdout.
set(
"lineno", lineno );
1765 std::vector<std::string> configwarnings;
1773 sscanf( line.c_str() + 2,
"%d", &percent );
1774 report->progress( percent );
1782 cmdout.
set(
"lineno", lineno );
1783 report->report( cmdout );
1786 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1790 rpmmsg += line+
'\n';
1793 configwarnings.push_back(line);
1796 rpmmsg +=
"[truncated]\n";
1799 if ( postTransCollector_r && rpm_status == 0 ) {
1805 for (std::vector<std::string>::iterator it = configwarnings.begin();
1806 it != configwarnings.end(); ++it)
1810 _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
1812 _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
1815 _(
"rpm created %s as %s, but it was impossible to determine the difference"),
1817 _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
1820 if ( rpm_status != 0 )
1825 std::ostringstream sstr;
1826 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1827 historylog.
comment(sstr.str());
1830 if ( not rpmmsg.empty() )
1834 else if ( ! rpmmsg.empty() )
1839 std::ostringstream sstr;
1840 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1841 historylog.
comment(sstr.str());
1845 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
1862 +
"-" + package->edition().version()
1863 +
"-" + package->edition().release()
1864 +
"." + package->arch().asString(), flags, postTransCollector_r );
1871 report->start( name_r );
1886 report->finish( excpt_r );
1902 MIL <<
"RpmDb::doRemovePackage(" << name_r <<
"," << flags <<
")" << endl;
1911 ERR <<
"backup of " << name_r <<
" failed" << endl;
1913 report->progress( 0 );
1917 report->progress( 100 );
1922 if ( postTransCollector_r ) {
1923 opts.push_back(
"--define");
1924 opts.push_back(
"_dump_posttrans 1");
1926 opts.push_back(
"-e");
1927 opts.push_back(
"--allmatches");
1930 opts.push_back(
"--noscripts");
1932 opts.push_back(
"--nodeps");
1934 opts.push_back(
"--justdb");
1936 opts.push_back (
"--test");
1939 WAR <<
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
1942 opts.push_back(
"--");
1943 opts.push_back(name_r.c_str());
1948 unsigned lineno = 0;
1951 cmdout.
set(
"line", std::cref(line) );
1952 cmdout.
set(
"lineno", lineno );
1963 report->progress( 5 );
1971 cmdout.
set(
"lineno", lineno );
1972 report->report( cmdout );
1975 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1978 rpmmsg += line+
'\n';
1981 rpmmsg +=
"[truncated]\n";
1982 report->progress( 50 );
1984 if ( postTransCollector_r && rpm_status == 0 ) {
1990 if ( rpm_status != 0 )
1993 str::form(
"%s remove failed", name_r.c_str()),
true );
1994 std::ostringstream sstr;
1995 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1996 historylog.
comment(sstr.str());
1999 if ( not rpmmsg.empty() )
2003 else if ( ! rpmmsg.empty() )
2006 str::form(
"%s removed ok", name_r.c_str()),
true );
2008 std::ostringstream sstr;
2009 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
2010 historylog.
comment(sstr.str());
2014 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2027 MIL <<
"RpmDb::runposttrans(" << filename_r <<
")" << endl;
2030 opts.push_back(
"-vv");
2031 opts.push_back(
"--runposttrans");
2032 opts.push_back(filename_r.
c_str());
2039 static const str::regex rx(
"^D: (%.*): scriptlet start$" );
2051 output_r(
"RIPOFF:"+what[1] );
2068 if ( rpm_status != 0 ) {
2069 WAR <<
"rpm --runposttrans returned " << rpm_status << endl;
2104 INT <<
"_backuppath empty" << endl;
2112 ERR <<
"Error while getting changed files for package " <<
2113 packageName << endl;
2119 DBG <<
"package " << packageName <<
" not changed -> no backup" << endl;
2130 time_t currentTime = time(0);
2131 struct tm *currentLocalTime = localtime(¤tTime);
2133 int date = (currentLocalTime->tm_year + 1900) * 10000
2134 + (currentLocalTime->tm_mon + 1) * 100
2135 + currentLocalTime->tm_mday;
2141 +
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2144 while (
PathInfo(backupFilename).isExist() && num++ < 1000);
2149 ERR << filestobackupfile.
asString() <<
" already exists and is no file" << endl;
2153 std::ofstream fp ( filestobackupfile.
asString().c_str(), std::ios::out|std::ios::trunc );
2157 ERR <<
"could not open " << filestobackupfile.
asString() << endl;
2161 for (FileList::const_iterator cit =
fileList.begin();
2164 std::string name = *cit;
2165 if ( name[0] ==
'/' )
2168 name = name.substr( 1 );
2170 DBG <<
"saving file "<< name << endl;
2175 const char*
const argv[] =
2181 "--ignore-failed-read",
2185 filestobackupfile.
asString().c_str(),
2201 int ret = tar.
close();
2205 ERR <<
"tar failed: " << tarmsg << endl;
2210 MIL <<
"tar backup ok" << endl;
2231#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2233 OUTS( CHK_OK,
_(
"Signature is OK") );
2235 OUTS( CHK_NOTFOUND,
_(
"Unknown type of signature") );
2237 OUTS( CHK_FAIL,
_(
"Signature does not verify") );
2239 OUTS( CHK_NOTTRUSTED,
_(
"Signature is OK, but key is not trusted") );
2241 OUTS( CHK_NOKEY,
_(
"Signatures public key is not available") );
2243 OUTS( CHK_ERROR,
_(
"File does not exist or signature can't be checked") );
2245 OUTS( CHK_NOSIG,
_(
"File is unsigned") );
2253 for (
const auto & el : obj )
2254 str << el.second << endl;
#define MAXRPMMESSAGELINES
#define FAILIFNOTINITIALIZED
#define FILEFORBACKUPFILES
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Mime type like 'type/subtype' classification of content.
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 ...
bool kill()
Kill the program.
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
bool running()
Return whether program is running.
int close()
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
static KeyManagerCtx createForOpenPGP()
Creates a new KeyManagerCtx for PGP using a volatile temp.
Temorarily change a locale category value.
TraitsType::constPtrType constPtr
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].
Class representing one GPG Public Keys data.
std::string gpgPubkeyRelease() const
Gpg-pubkey release as computed by rpm (hexencoded created)
std::string gpgPubkeyVersion() const
Gpg-pubkey version as computed by rpm (trailing 8 byte id)
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Pathname path() const
File containing the ASCII armored key.
std::string gpgPubkeyRelease() const
std::string asString() const
std::string gpgPubkeyVersion() const
bool hasSubkeys() const
!<
static ZConfig & instance()
Singleton ctor.
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).
void setBlocking(bool mode)
Set the blocking mode of the input stream.
FILE * inputFile() const
Return the input stream.
std::string receiveLine()
Read one line from the input stream.
Wrapper class for stat/lstat.
bool isExist() const
Return whether valid stat info exists.
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.
virtual std::ostream & dumpOn(std::ostream &str) const
Dump debug info.
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
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.
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.
int runposttrans(const Pathname &filename_r, std::function< void(const std::string &)> output_r)
Run collected posttrans and transfiletrigger(postun|in) if rpm --runposttrans is supported.
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.
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
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.
std::vector< const char * > RpmArgVec
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)
std::set< std::string > FileList
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 database content.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
bool findByFile(const std::string &file_r)
Reset to iterate all packages that own a certain file.
bool findByRequiredBy(const std::string &tag_r)
Reset to iterate all packages that require a certain tag.
bool findPackage(const std::string &name_r)
Find package by name.
shared_ptr< RpmException > dbError() const
Return any database error.
bool findByConflicts(const std::string &tag_r)
Reset to iterate all packages that conflict with a certain tag.
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
static std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
static unsigned dbRelease(bool force_r=false)
If there are no outstanding references to the database (e.g.
static void dbAccess()
Access the database at the current default location.
static unsigned blockAccess()
Blocks further access to rpmdb.
static Pathname suggestedDbPath(const Pathname &root_r)
static void unblockAccess()
Allow access to rpmdb e.g.
String related utilities and Regular expression matching.
Types and functions for filesystem operations.
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'.
int copy(const Pathname &file, const Pathname &dest)
Like 'cp file dest'.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
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.
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.
std::string toLower(const std::string &s)
Return lowercase version of s.
std::ostream & operator<<(std::ostream &str, const librpmDb::db_const_iterator &obj)
static shared_ptr< KeyRingSignalReceiver > sKeyRingReceiver
std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
unsigned diffFiles(const std::string file1, const std::string file2, std::string &out, int maxlines)
Easy-to use interface to the ZYPP dependency resolver.
Temporarily connect a ReceiveReport then restore the previous one.
static const UserData::ContentType contentRpmout
"rpmout/installpkg": Additional rpm output (sent immediately).
virtual void trustedKeyRemoved(const PublicKey &key)
virtual void trustedKeyAdded(const PublicKey &key)
KeyRingSignalReceiver(RpmDb &rpmdb)
static const UserData::ContentType contentRpmout
"rpmout/removepkg": Additional rpm output (sent immediately).
Detailed rpm signature check log messages A single multiline message if CHK_OK.
#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.