15#include <rpm/rpmcli.h>
16#include <rpm/rpmlog.h>
38#include <zypp-core/base/DtorReset>
44#include <zypp-core/ui/ProgressData>
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" )
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;
278 void deferTrustedKeySync( std::function<
void()> init_r )
281 getZYpp()->keyRing()->setTrustedKeyRingInit( std::move(init_r) );
293 workaroundDUMPPOSTTRANS_BUG_1216091(
true );
297 if ( root_r.
empty() )
305 if ( dbPath_r !=
"/var/lib/rpm" && !
PathInfo( root_r/
"/var/lib/rpm" ).isExist() )
307 WAR <<
"Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
321 if ( root_r ==
_root ) {
329 MIL <<
"Calling initDatabase: " <<
dumpPath( root_r, dbPath_r )
330 << ( doRebuild_r ?
" (rebuilddb)" :
"" ) << endl;
344 MIL <<
"Sync keys with zypp keyring on first use" << endl;
352 librpmDb::dbRelease(
true );
354 MIL <<
"InitDatabase: " << *
this << endl;
373 MIL <<
"closeDatabase: " << *
this << endl;
374 deferTrustedKeySync(
nullptr );
405 MIL <<
"RpmDb::rebuildDatabase" << *
this << endl;
419 opts.push_back(
"--rebuilddb");
420 opts.push_back(
"-vv");
430 tics.
range( hdrTotal );
433 return report->progress( tics_r.
reportValue(), mydbpath );
441 static const std::string debugPrefix {
"D:" };
442 static const std::string progressPrefix {
"D: read h#" };
443 static const std::string ignoreSuffix {
"digest: OK" };
458 WAR <<
"User requested abort." << endl;
482 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
489 : _inRpmKeys( nullptr )
490 , _inZyppKeys( nullptr )
493 void updateIf(
const Edition & rpmKey_r )
495 std::string keyRelease( rpmKey_r.
release() );
496 int comp = _release.compare( keyRelease );
500 _release.swap( keyRelease );
501 _inRpmKeys = &rpmKey_r;
502 _inZyppKeys =
nullptr;
503 if ( !keyRelease.empty() )
504 DBG <<
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
506 else if ( comp == 0 )
510 _inRpmKeys = &rpmKey_r;
514 DBG <<
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
517 void updateIf(
const PublicKeyData & zyppKey_r )
520 int comp = _release.compare( keyRelease );
524 _release.swap( keyRelease );
525 _inRpmKeys =
nullptr;
526 _inZyppKeys = &zyppKey_r;
527 if ( !keyRelease.empty() )
528 DBG <<
"Old key in R: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
530 else if ( comp == 0 )
534 _inZyppKeys = &zyppKey_r;
538 DBG <<
"Old key in Z: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
541 std::string _release;
543 const PublicKeyData * _inZyppKeys;
548 std::map<std::string,Key> _keymap;
550 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
552 _keymap[(*it).version()].updateIf( *it );
555 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
557 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
561 std::set<Edition> rpmKeys;
562 std::list<PublicKeyData> zyppKeys;
563 for_( it, _keymap.begin(), _keymap.end() )
565 DBG <<
"gpg-pubkey-" << (*it).first <<
"-" << (*it).second._release <<
" "
566 << ( (*it).second._inRpmKeys ?
"R" :
"_" )
567 << ( (*it).second._inZyppKeys ?
"Z" :
"_" ) << endl;
568 if ( ! (*it).second._inRpmKeys )
570 zyppKeys.push_back( *(*it).second._inZyppKeys );
572 if ( ! (*it).second._inZyppKeys )
574 rpmKeys.insert( *(*it).second._inRpmKeys );
577 rpmKeys_r.swap( rpmKeys );
578 zyppKeys_r.swap( zyppKeys );
585 MIL <<
"Going to sync trusted keys..." << endl;
586 deferTrustedKeySync(
nullptr );
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;
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() )
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 );
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;
947 found = it.findPackage( name_r );
951 found = it.findPackage( name_r, edition_r );
968bool RpmDb::hasFile(
const std::string & file_r,
const std::string & name_r )
const
974 res = it.findByFile( file_r );
978 res = (it->tag_name() == name_r);
997 if (it.findByFile( file_r ))
999 return it->tag_name();
1015 return it.findByProvides( tag_r );
1029 return it.findByRequiredBy( tag_r );
1043 return it.findByConflicts( tag_r );
1057 return it.findPackage( name_r );
1071 return it.findPackage( name_r, ed_r );
1086 it.findPackage( name_r );
1106 it.findPackage( name_r, ed_r );
1117 struct RpmlogCapture :
public std::vector<std::string>
1121 rpmlogSetCallback( rpmLogCB,
this );
1122 _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
1125 RpmlogCapture(
const RpmlogCapture &) =
delete;
1126 RpmlogCapture(RpmlogCapture &&) =
delete;
1127 RpmlogCapture &operator=(
const RpmlogCapture &) =
delete;
1128 RpmlogCapture &operator=(RpmlogCapture &&) =
delete;
1131 rpmlogSetCallback(
nullptr,
nullptr );
1132 rpmlogSetMask( _oldMask );
1135 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1136 {
return reinterpret_cast<RpmlogCapture*
>(data_r)->rpmLog( rec_r ); }
1138 int rpmLog( rpmlogRec rec_r )
1140 std::string l { ::rpmlogRecMessage( rec_r ) };
1142 push_back( std::move(l) );
1150 std::ostream &
operator<<( std::ostream & str,
const RpmlogCapture & obj )
1153 for (
const auto & l : obj ) {
1154 if ( sep ) str << sep;
else sep =
'\n';
1162 const Pathname & root_r,
1163 bool requireGPGSig_r,
1166 PathInfo file( path_r );
1167 if ( ! file.isFile() )
1169 ERR <<
"Not a file: " << file << endl;
1173 FD_t fd = ::Fopen( file.asString().c_str(),
"r.ufdio" );
1174 if ( fd == 0 || ::Ferror(fd) )
1176 ERR <<
"Can't open file for reading: " << file <<
" (" << ::Fstrerror(fd) <<
")" << endl;
1181 rpmts ts = ::rpmtsCreate();
1182 ::rpmtsSetRootDir( ts, root_r.
c_str() );
1183 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1184#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP
1185 ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
1188 RpmlogCapture vresult;
1189 LocaleGuard guard( LC_ALL,
"C" );
1190 static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0,
sizeof(rpmQVKArguments_s) );
return qva; })();
1191 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
1200 typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
1201 static const ResultMap resultMap {
1209 auto getresult = [](
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1210 auto it = resultMap.find( key );
1215 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1220 SawHeaderSig = (1 << 0),
1221 SawHeaderDigest = (1 << 1),
1222 SawPayloadDigest = (1 << 2),
1224 SawDigest = (1 << 4),
1226 unsigned saw = SawNone;
1228 static const str::regex rx(
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1230 for (
const std::string & line : vresult )
1232 if ( line[0] !=
' ' )
1238 lineres = getresult( resultMap, what[3] );
1242 if ( what[1][0] ==
'H' ) {
1243 saw |= ( what[2][0] ==
'S' ? SawHeaderSig :SawHeaderDigest );
1245 else if ( what[1][0] ==
'P' ) {
1246 if ( what[2][0] ==
'd' ) saw |= SawPayloadDigest;
1249 saw |= ( what[2][0] ==
'S' ? SawSig : SawDigest );
1254 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, line ) );
1276 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1277 if ( not isSigned ) {
1278 std::string message {
" " };
1279 if ( not (saw & SawHeaderSig) )
1280 message +=
_(
"Package header is not signed!");
1282 message +=
_(
"Package payload is not signed!");
1284 detail_r.push_back( RpmDb::CheckPackageDetail::value_type(
RpmDb::CHK_NOSIG, std::move(message) ) );
1285 if ( requireGPGSig_r )
1294 bool didReadHeader =
false;
1295 std::unordered_map< std::string, std::string> fprs;
1298 str::regex rxexpr(
"key ID ([a-fA-F0-9]{8}):" );
1299 for (
auto &detail : detail_r ) {
1300 auto &line = detail.second;
1304 if ( !didReadHeader ) {
1305 didReadHeader =
true;
1311 const auto &addFprs = [&](
auto tag ){
1312 const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
1313 for (
const auto &
id : list1 ) {
1314 if (
id.size() <= 8 )
1318 fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
1322 addFprs( RPMTAG_SIGGPG );
1323 addFprs( RPMTAG_SIGPGP );
1324 addFprs( RPMTAG_RSAHEADER );
1325 addFprs( RPMTAG_DSAHEADER );
1328 ERR <<
"Failed to read package signatures." << std::endl;
1339 if (
const auto &i = fprs.find( keyId ); i != fprs.end() ) {
1346 WAR << path_r <<
" (" << requireGPGSig_r <<
" -> " << ret <<
")" << endl;
1347 WAR << vresult << endl;
1350 DBG << path_r <<
" [0-Signature is OK]" << endl;
1361{
return doCheckPackageSig( path_r,
root(),
false, detail_r ); }
1367{
return doCheckPackageSig( path_r,
root(),
true, detail_r ); }
1382 opts.push_back (
"-V");
1383 opts.push_back (
"--nodeps");
1384 opts.push_back (
"--noscripts");
1385 opts.push_back (
"--nomd5");
1386 opts.push_back (
"--");
1387 opts.push_back (packageName.c_str());
1408 if (line.length() > 12 &&
1409 (line[0] ==
'S' || line[0] ==
's' ||
1410 (line[0] ==
'.' && line[7] ==
'T')))
1413 std::string filename;
1415 filename.assign(line, 11, line.length() - 11);
1455#if defined(WORKAROUNDRPMPWDBUG)
1456 args.push_back(
"#/");
1458 args.push_back(
"rpm");
1459 args.push_back(
"--root");
1460 args.push_back(
_root.asString().c_str());
1461 args.push_back(
"--dbpath");
1462 args.push_back(
_dbPath.asString().c_str());
1464 args.push_back(
"-vv");
1465 const char* argv[args.size() + opts.size() + 1];
1467 const char**
p = argv;
1468 p =
copy (args.begin (), args.end (),
p);
1469 p =
copy (opts.begin (), opts.end (),
p);
1475 librpmDb::dbRelease(
true );
1495 process->setBlocking(
false );
1496 FILE * inputfile =
process->inputFile();
1501 const auto &readResult =
io::receiveUpto( inputfile,
'\n', 5 * 1000,
false );
1502 switch ( readResult.first ) {
1508 line += readResult.second;
1513 line += readResult.second;
1514 if ( line.size() && line.back() ==
'\n')
1519 line += readResult.second;
1521 if ( line.size() && line.back() ==
'\n')
1525 L_DBG(
"RPM_DEBUG") << line << endl;
1569void RpmDb::processConfigFiles(
const std::string& line,
const std::string& name,
const char* typemsg,
const char* difffailmsg,
const char* diffgenmsg)
1571 std::string msg = line.substr(9);
1572 std::string::size_type pos1 = std::string::npos;
1573 std::string::size_type pos2 = std::string::npos;
1574 std::string file1s, file2s;
1578 pos1 = msg.find (typemsg);
1581 if ( pos1 == std::string::npos )
1584 pos2 = pos1 + strlen (typemsg);
1586 if (pos2 >= msg.length() )
1589 file1 = msg.substr (0, pos1);
1590 file2 = msg.substr (pos2);
1597 file1 =
_root + file1;
1598 file2 =
_root + file2;
1608 ERR <<
"Could not create " << file.
asString() << endl;
1612 std::ofstream notify(file.
asString().c_str(), std::ios::out|std::ios::app);
1615 ERR <<
"Could not open " << file << endl;
1621 notify <<
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
1624 ERR <<
"diff failed" << endl;
1626 file1s.c_str(), file2s.c_str()) << endl;
1631 file1s.c_str(), file2s.c_str()) << endl;
1636 if (out.substr(0,4) ==
"--- ")
1638 out.replace(4, file1.
asString().length(), file1s);
1640 std::string::size_type pos = out.find(
"\n+++ ");
1641 if (pos != std::string::npos)
1643 out.replace(pos+5, file2.
asString().length(), file2s);
1646 notify << out << endl;
1649 notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1654 WAR <<
"rpm created " << file2 <<
" but it is not different from " << file2 << endl;
1674 report->start(filename);
1689 report->finish( excpt_r );
1705 MIL <<
"RpmDb::installPackage(" << filename <<
"," << flags <<
")" << endl;
1713 ERR <<
"backup of " << filename.
asString() <<
" failed" << endl;
1716 report->progress( 0 );
1721 if ( postTransCollector_r && (
_root ==
"/" || not workaroundDUMPPOSTTRANS_BUG_1216091() ) ) {
1722 opts.push_back(
"--define");
1723 opts.push_back(
"_dump_posttrans 1");
1726 opts.push_back(
"-i");
1728 opts.push_back(
"-U");
1730 opts.push_back(
"--percent");
1731 opts.push_back(
"--noglob");
1735 opts.push_back(
"--ignorearch");
1738 opts.push_back(
"--nodigest");
1740 opts.push_back(
"--nosignature");
1742 opts.push_back (
"--excludedocs");
1744 opts.push_back (
"--noscripts");
1746 opts.push_back (
"--force");
1748 opts.push_back (
"--nodeps");
1750 opts.push_back (
"--ignoresize");
1752 opts.push_back (
"--justdb");
1754 opts.push_back (
"--test");
1756 opts.push_back (
"--noposttrans");
1758 opts.push_back(
"--");
1761 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
1762 opts.push_back ( quotedFilename.c_str() );
1767 unsigned lineno = 0;
1770 cmdout.
set(
"line", std::cref(line) );
1771 cmdout.
set(
"lineno", lineno );
1775 std::vector<std::string> configwarnings;
1783 sscanf( line.c_str() + 2,
"%d", &percent );
1784 report->progress( percent );
1792 cmdout.
set(
"lineno", lineno );
1793 report->report( cmdout );
1796 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1800 rpmmsg += line+
'\n';
1803 configwarnings.push_back(line);
1806 rpmmsg +=
"[truncated]\n";
1809 if ( postTransCollector_r && rpm_status == 0 ) {
1815 for (std::vector<std::string>::iterator it = configwarnings.begin();
1816 it != configwarnings.end(); ++it)
1820 _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
1822 _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
1825 _(
"rpm created %s as %s, but it was impossible to determine the difference"),
1827 _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
1830 if ( rpm_status != 0 )
1835 std::ostringstream sstr;
1836 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1837 historylog.
comment(sstr.str());
1840 if ( not rpmmsg.empty() )
1841 excpt.addHistory( rpmmsg );
1844 else if ( ! rpmmsg.empty() )
1849 std::ostringstream sstr;
1850 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1851 historylog.
comment(sstr.str());
1855 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
1872 +
"-" + package->edition().version()
1873 +
"-" + package->edition().release()
1874 +
"." + package->arch().asString(), flags, postTransCollector_r );
1881 report->start( name_r );
1896 report->finish( excpt_r );
1912 MIL <<
"RpmDb::doRemovePackage(" << name_r <<
"," << flags <<
")" << endl;
1921 ERR <<
"backup of " << name_r <<
" failed" << endl;
1923 report->progress( 0 );
1927 report->progress( 100 );
1932 if ( postTransCollector_r && (
_root ==
"/" || not workaroundDUMPPOSTTRANS_BUG_1216091() ) ) {
1933 opts.push_back(
"--define");
1934 opts.push_back(
"_dump_posttrans 1");
1936 opts.push_back(
"-e");
1937 opts.push_back(
"--allmatches");
1940 opts.push_back(
"--noscripts");
1942 opts.push_back(
"--nodeps");
1944 opts.push_back(
"--justdb");
1946 opts.push_back (
"--test");
1949 WAR <<
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
1952 opts.push_back(
"--");
1953 opts.push_back(name_r.c_str());
1958 unsigned lineno = 0;
1961 cmdout.
set(
"line", std::cref(line) );
1962 cmdout.
set(
"lineno", lineno );
1973 report->progress( 5 );
1981 cmdout.
set(
"lineno", lineno );
1982 report->report( cmdout );
1985 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1988 rpmmsg += line+
'\n';
1991 rpmmsg +=
"[truncated]\n";
1992 report->progress( 50 );
1994 if ( postTransCollector_r && rpm_status == 0 ) {
2000 if ( rpm_status != 0 )
2003 str::form(
"%s remove failed", name_r.c_str()),
true );
2004 std::ostringstream sstr;
2005 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2006 historylog.
comment(sstr.str());
2009 if ( not rpmmsg.empty() )
2010 excpt.addHistory( rpmmsg );
2013 else if ( ! rpmmsg.empty() )
2016 str::form(
"%s removed ok", name_r.c_str()),
true );
2018 std::ostringstream sstr;
2019 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
2020 historylog.
comment(sstr.str());
2024 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2037 MIL <<
"RpmDb::runposttrans(" << filename_r <<
")" << endl;
2046 opts.push_back(
"--define");
2047 opts.push_back(_tmppath.c_str());
2049 opts.push_back(
"-vv");
2050 opts.push_back(
"--runposttrans");
2051 opts.push_back(filename_r.
c_str());
2058 static const str::regex rx(
"^D: (%.*): (scriptlet start|running .* scriptlet)" );
2059 static const str::regex rx2(
"^Running (%[^)]*[)])$" );
2071 DBG <<
"Verbose RIPOFF:"+what[1] << endl;
2072 output_r(
"RIPOFF:"+what[1] );
2080 DBG <<
"NonVerbose RIPOFF:"+what[1] << endl;
2097 if ( rpm_status != 0 ) {
2098 WAR <<
"rpm --runposttrans returned " << rpm_status << endl;
2133 INT <<
"_backuppath empty" << endl;
2141 ERR <<
"Error while getting changed files for package " <<
2142 packageName << endl;
2148 DBG <<
"package " << packageName <<
" not changed -> no backup" << endl;
2159 time_t currentTime = time(0);
2160 struct tm *currentLocalTime = localtime(¤tTime);
2162 int date = (currentLocalTime->tm_year + 1900) * 10000
2163 + (currentLocalTime->tm_mon + 1) * 100
2164 + currentLocalTime->tm_mday;
2170 +
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2173 while (
PathInfo(backupFilename).isExist() && num++ < 1000);
2178 ERR << filestobackupfile.
asString() <<
" already exists and is no file" << endl;
2182 std::ofstream fp ( filestobackupfile.
asString().c_str(), std::ios::out|std::ios::trunc );
2186 ERR <<
"could not open " << filestobackupfile.
asString() << endl;
2190 for (FileList::const_iterator cit =
fileList.begin();
2193 std::string name = *cit;
2194 if ( name[0] ==
'/' )
2197 name = name.substr( 1 );
2199 DBG <<
"saving file "<< name << endl;
2204 const char*
const argv[] =
2209 _root.asString().c_str(),
2210 "--ignore-failed-read",
2214 filestobackupfile.
asString().c_str(),
2230 int ret = tar.
close();
2234 ERR <<
"tar failed: " << tarmsg << endl;
2239 MIL <<
"tar backup ok" << endl;
2260#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2262 OUTS( CHK_OK,
_(
"Signature is OK") );
2264 OUTS( CHK_NOTFOUND,
_(
"Unknown type of signature") );
2266 OUTS( CHK_FAIL,
_(
"Signature does not verify") );
2268 OUTS( CHK_NOTTRUSTED,
_(
"Signature is OK, but key is not trusted") );
2270 OUTS( CHK_NOKEY,
_(
"Signatures public key is not available") );
2272 OUTS( CHK_ERROR,
_(
"File does not exist or signature can't be checked") );
2274 OUTS( CHK_NOSIG,
_(
"File is unsigned") );
2282 for (
const auto & el : obj )
2283 str << el.second << endl;
#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.
#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]
static int match(const Edition &lhs, const Edition &rhs)
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
static KeyManagerCtx createForOpenPGP()
Creates a new KeyManagerCtx for PGP using a volatile temp.
TraitsType::constPtrType constPtr
static Pathname stripprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r with any root_r dir prefix striped.
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].
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.
static ZYppFactory 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).
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)
nullptr CURL handle void * p
bool regex_match(const char *s, smatch &matches, const regex ®ex) ZYPP_API
Regular expression matching.
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
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)
relates: librpmDb::db_const_iterator stream output
_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.
ZYpp::Ptr getZYpp()
relates: ZYppFactory Convenience to get the Pointer to the ZYpp instance.
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.