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;
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");
1461 args.push_back(
"--dbpath");
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 );
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[] =
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
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).
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.
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.
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).
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)
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.