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 );
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;
175 MIL <<
"Trusted key removed from zypp Keyring. Removing..." << endl;
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 )
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;
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;
699 bool hasOldkeys =
false;
701 for_( it, rpmKeys.begin(), rpmKeys.end() )
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 (
"--" );
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();
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;
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");
1449 args.push_back(
"--dbpath");
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 );
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;
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[] =
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 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
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 ...
ExternalProgram()
Start an external program by giving the arguments as an arry of char *pointers.
int close() override
Wait for the progamm to complete.
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.
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).
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.
Pathname()
Default ctor: an empty path.
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.
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.
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.
RpmDbAlreadyOpenException(const Pathname &old_root_r, const Pathname &old_dbpath_r, const Pathname &new_root_r, const Pathname &new_dbpath_r)
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.
RpmSubprocessException(std::string errmsg_r)
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)
std::string asString() const
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.