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
71#define WORKAROUNDDUMPPOSTTRANSBUG
73#undef ZYPP_BASE_LOGGER_LOGGROUP
74#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb"
78 namespace zypp_readonly_hack
86 static bool val = [](){
87 const char *
env = getenv(
"ZYPP_RPM_DEBUG");
102const char* quoteInFilename_m =
"\'\"";
103inline std::string rpmQuoteFilename(
const Pathname & path_r )
105 std::string path( path_r.
asString() );
106 for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m );
107 pos != std::string::npos;
108 pos = path.find_first_of( quoteInFilename_m, pos ) )
110 path.insert( pos,
"\\" );
123#if defined(WORKAROUNDRPMPWDBUG)
130 WAR <<
"Can't get cwd!" << endl;
152 MIL <<
"trusted key added to zypp Keyring. Importing..." << endl;
158 MIL <<
"Trusted key removed from zypp Keyring. Removing..." << endl;
167unsigned diffFiles(
const std::string& file1,
const std::string& file2, std::string& out,
int maxlines)
188 if (maxlines<0?
true:count<maxlines)
201#define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); }
212 : _backuppath (
"/var/adm/backup")
213 , _packagebackups(false)
220 setenv(
"RPM_IgnoreFailedSymlinks",
"1", 1 );
232 MIL <<
"~RpmDb()" << endl;
235 MIL <<
"~RpmDb() end" << endl;
269 if ( root_r.
empty() )
277 if ( dbPath_r !=
"/var/lib/rpm" && !
PathInfo( root_r/
"/var/lib/rpm" ).isExist() )
279 WAR <<
"Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
293 if ( root_r ==
_root ) {
301 MIL <<
"Calling initDatabase: " <<
dumpPath( root_r, dbPath_r )
302 << ( doRebuild_r ?
" (rebuilddb)" :
"" ) << endl;
316 MIL <<
"Synchronizing keys with zypp keyring" << endl;
324 librpmDb::dbRelease(
true );
326 MIL <<
"InitDatabase: " << *
this << endl;
345 MIL <<
"closeDatabase: " << *
this << endl;
376 MIL <<
"RpmDb::rebuildDatabase" << *
this << endl;
390 opts.push_back(
"--rebuilddb");
391 opts.push_back(
"-vv");
401 tics.
range( hdrTotal );
404 return report->progress( tics_r.
reportValue(), mydbpath );
412 static const std::string debugPrefix {
"D:" };
413 static const std::string progressPrefix {
"D: read h#" };
414 static const std::string ignoreSuffix {
"digest: OK" };
429 WAR <<
"User requested abort." << endl;
453 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
460 : _inRpmKeys( nullptr )
461 , _inZyppKeys( nullptr )
464 void updateIf(
const Edition & rpmKey_r )
466 std::string keyRelease( rpmKey_r.
release() );
467 int comp = _release.compare( keyRelease );
471 _release.swap( keyRelease );
472 _inRpmKeys = &rpmKey_r;
473 _inZyppKeys =
nullptr;
474 if ( !keyRelease.empty() )
475 DBG <<
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
477 else if ( comp == 0 )
481 _inRpmKeys = &rpmKey_r;
485 DBG <<
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
491 int comp = _release.compare( keyRelease );
495 _release.swap( keyRelease );
496 _inRpmKeys =
nullptr;
497 _inZyppKeys = &zyppKey_r;
498 if ( !keyRelease.empty() )
499 DBG <<
"Old key in R: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
501 else if ( comp == 0 )
505 _inZyppKeys = &zyppKey_r;
509 DBG <<
"Old key in Z: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
512 std::string _release;
513 const Edition * _inRpmKeys;
519 std::map<std::string,Key> _keymap;
521 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
523 _keymap[(*it).version()].updateIf( *it );
526 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
528 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
532 std::set<Edition> rpmKeys;
533 std::list<PublicKeyData> zyppKeys;
534 for_( it, _keymap.begin(), _keymap.end() )
536 DBG <<
"gpg-pubkey-" << (*it).first <<
"-" << (*it).second._release <<
" "
537 << ( (*it).second._inRpmKeys ?
"R" :
"_" )
538 << ( (*it).second._inZyppKeys ?
"Z" :
"_" ) << endl;
539 if ( ! (*it).second._inRpmKeys )
541 zyppKeys.push_back( *(*it).second._inZyppKeys );
543 if ( ! (*it).second._inZyppKeys )
545 rpmKeys.insert( *(*it).second._inRpmKeys );
548 rpmKeys_r.swap( rpmKeys );
549 zyppKeys_r.swap( zyppKeys );
556 MIL <<
"Going to sync trusted keys..." << endl;
558 std::list<PublicKeyData> zyppKeys(
getZYpp()->keyRing()->trustedPublicKeyData() );
570 MIL <<
"Removing excess keys in zypp trusted keyring" << std::endl;
576 if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) )
578 DBG <<
"Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl;
579 getZYpp()->keyRing()->deleteKey( keyData.id(),
true );
580 if ( !dirty ) dirty =
true;
584 zyppKeys =
getZYpp()->keyRing()->trustedPublicKeyData();
587 computeKeyRingSync( rpmKeys, zyppKeys );
588 MIL << (mode_r &
SYNC_TO_KEYRING ?
"" :
"(skip) ") <<
"Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
589 MIL << (mode_r &
SYNC_FROM_KEYRING ?
"" :
"(skip) ") <<
"Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
595 MIL <<
"Exporting rpm keyring into zypp trusted keyring" <<endl;
602 std::ofstream tmpos( tmpfile.
path().
c_str() );
603 for_( it, rpmKeys.begin(), rpmKeys.end() )
607 getData(
"gpg-pubkey", *it, result );
608 tmpos << result->tag_description() << endl;
613 getZYpp()->keyRing()->multiKeyImport( tmpfile.
path(),
true );
617 std::set<Edition> missingKeys;
618 for (
const Edition & key : rpmKeys )
620 if (
getZYpp()->keyRing()->isKeyTrusted( key.version() ) )
622 ERR <<
"Could not import key:" <<
str::Format(
"gpg-pubkey-%s") % key <<
" into zypp keyring (V3 key?)" << endl;
623 missingKeys.insert( key );
625 if ( ! missingKeys.empty() )
631 ERR <<
"Could not import keys into zypp keyring: " << endl;
639 MIL <<
"Importing zypp trusted keyring" << std::endl;
640 for_( it, zyppKeys.begin(), zyppKeys.end() )
652 MIL <<
"Trusted keys synced." << endl;
674 WAR <<
"Key " << pubkey_r <<
" can not be imported. (READONLY MODE)" << endl;
681 bool hasOldkeys =
false;
683 for_( it, rpmKeys.begin(), rpmKeys.end() )
692 MIL <<
"Key " << pubkey_r <<
" is already in the rpm trusted keyring. (skip import)" << endl;
696 if ( keyEd.
version() != (*it).version() )
699 if ( keyEd.
release() < (*it).release() )
701 MIL <<
"Key " << pubkey_r <<
" is older than one in the rpm trusted keyring. (skip import)" << endl;
709 MIL <<
"Key " << pubkey_r <<
" will be imported into the rpm trusted keyring." << (hasOldkeys?
"(update)":
"(new)") << endl;
715 std::string keyName(
"gpg-pubkey-" + keyEd.
version() );
717 opts.push_back (
"-e" );
718 opts.push_back (
"--allmatches" );
719 opts.push_back (
"--" );
720 opts.push_back ( keyName.c_str() );
731 ERR <<
"Failed to remove key " << pubkey_r <<
" from RPM trusted keyring (ignored)" << endl;
735 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
741 opts.push_back (
"--import" );
742 opts.push_back (
"--" );
744 opts.push_back ( pubkeypath.c_str() );
748 std::vector<std::string> excplines;
754 excplines.push_back( std::move(line) );
770 MIL <<
"Key " << pubkey_r <<
" imported in rpm trusted keyring." << endl;
787 std::set<Edition>::const_iterator found_edition = rpm_keys.end();
790 for_( it, rpm_keys.begin(), rpm_keys.end() )
792 if ( (*it).version() == pubkeyVersion )
800 if (found_edition == rpm_keys.end())
802 WAR <<
"Key " << pubkey_r.
id() <<
" is not in rpm db" << endl;
806 std::string rpm_name(
"gpg-pubkey-" + found_edition->asString());
809 opts.push_back (
"-e" );
810 opts.push_back (
"--" );
811 opts.push_back ( rpm_name.c_str() );
815 std::vector<std::string> excplines;
821 excplines.push_back( std::move(line) );
837 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
849 std::list<PublicKey> ret;
852 for ( it.findByName(
"gpg-pubkey" ); *it; ++it )
854 Edition edition = it->tag_edition();
859 getData(
"gpg-pubkey", edition, result );
866 os << result->tag_description();
875 catch ( std::exception & e )
877 ERR <<
"Could not dump key " << edition.
asString() <<
" in tmp file " << file.
path() << endl;
887 std::set<Edition> ret;
890 for ( it.findByName(
"gpg-pubkey" ); *it; ++it )
892 Edition edition = it->tag_edition();
894 ret.insert( edition );
911 std::list<FileInfo> result;
917 found = it.findPackage( name_r );
921 found = it.findPackage( name_r, edition_r );
938bool RpmDb::hasFile(
const std::string & file_r,
const std::string & name_r )
const
944 res = it.findByFile( file_r );
948 res = (it->tag_name() == name_r);
967 if (it.findByFile( file_r ))
969 return it->tag_name();
985 return it.findByProvides( tag_r );
999 return it.findByRequiredBy( tag_r );
1013 return it.findByConflicts( tag_r );
1027 return it.findPackage( name_r );
1041 return it.findPackage( name_r, ed_r );
1056 it.findPackage( name_r );
1076 it.findPackage( name_r, ed_r );
1087 struct RpmlogCapture :
public std::vector<std::string>
1091 rpmlogSetCallback( rpmLogCB,
this );
1092 _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
1095 RpmlogCapture(
const RpmlogCapture &) =
delete;
1096 RpmlogCapture(RpmlogCapture &&) =
delete;
1097 RpmlogCapture &operator=(
const RpmlogCapture &) =
delete;
1098 RpmlogCapture &operator=(RpmlogCapture &&) =
delete;
1101 rpmlogSetCallback(
nullptr,
nullptr );
1102 rpmlogSetMask( _oldMask );
1105 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1106 {
return reinterpret_cast<RpmlogCapture*
>(data_r)->rpmLog( rec_r ); }
1108 int rpmLog( rpmlogRec rec_r )
1110 std::string l { ::rpmlogRecMessage( rec_r ) };
1112 push_back( std::move(l) );
1120 std::ostream &
operator<<( std::ostream &
str,
const RpmlogCapture & obj )
1123 for (
const auto & l : obj ) {
1124 if ( sep )
str << sep;
else sep =
'\n';
1133 bool requireGPGSig_r,
1134 RpmDb::CheckPackageDetail & detail_r )
1137 if ( ! file.isFile() )
1139 ERR <<
"Not a file: " << file << endl;
1143 FD_t fd = ::Fopen( file.asString().c_str(),
"r.ufdio" );
1144 if ( fd == 0 || ::Ferror(fd) )
1146 ERR <<
"Can't open file for reading: " << file <<
" (" << ::Fstrerror(fd) <<
")" << endl;
1151 rpmts ts = ::rpmtsCreate();
1152 ::rpmtsSetRootDir( ts, root_r.
c_str() );
1153 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1154#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP
1155 ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
1158 RpmlogCapture vresult;
1160 static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0,
sizeof(rpmQVKArguments_s) );
return qva; })();
1161 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
1170 typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
1171 static const ResultMap resultMap {
1179 auto getresult = [](
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1180 auto it = resultMap.find( key );
1185 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1190 SawHeaderSig = (1 << 0),
1191 SawHeaderDigest = (1 << 1),
1192 SawPayloadDigest = (1 << 2),
1194 SawDigest = (1 << 4),
1196 unsigned saw = SawNone;
1198 static const str::regex rx(
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1200 for (
const std::string & line : vresult )
1202 if ( line[0] !=
' ' )
1208 lineres = getresult( resultMap, what[3] );
1212 if ( what[1][0] ==
'H' ) {
1213 saw |= ( what[2][0] ==
'S' ? SawHeaderSig :SawHeaderDigest );
1215 else if ( what[1][0] ==
'P' ) {
1216 if ( what[2][0] ==
'd' ) saw |= SawPayloadDigest;
1219 saw |= ( what[2][0] ==
'S' ? SawSig : SawDigest );
1224 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, line ) );
1246 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1247 if ( not isSigned ) {
1248 std::string message {
" " };
1249 if ( not (saw & SawHeaderSig) )
1250 message +=
_(
"Package header is not signed!");
1252 message +=
_(
"Package payload is not signed!");
1254 detail_r.push_back( RpmDb::CheckPackageDetail::value_type(
RpmDb::CHK_NOSIG, std::move(message) ) );
1255 if ( requireGPGSig_r )
1264 bool didReadHeader =
false;
1265 std::unordered_map< std::string, std::string> fprs;
1268 str::regex rxexpr(
"key ID ([a-fA-F0-9]{8}):" );
1269 for (
auto &detail : detail_r ) {
1270 auto &line = detail.second;
1274 if ( !didReadHeader ) {
1275 didReadHeader =
true;
1281 const auto &addFprs = [&](
auto tag ){
1282 const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
1283 for (
const auto &
id : list1 ) {
1284 if (
id.size() <= 8 )
1288 fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
1292 addFprs( RPMTAG_SIGGPG );
1293 addFprs( RPMTAG_SIGPGP );
1294 addFprs( RPMTAG_RSAHEADER );
1295 addFprs( RPMTAG_DSAHEADER );
1298 ERR <<
"Failed to read package signatures." << std::endl;
1309 if (
const auto &i = fprs.find( keyId ); i != fprs.end() ) {
1316 WAR << path_r <<
" (" << requireGPGSig_r <<
" -> " << ret <<
")" << endl;
1317 WAR << vresult << endl;
1320 DBG << path_r <<
" [0-Signature is OK]" << endl;
1331{
return doCheckPackageSig( path_r,
root(),
false, detail_r ); }
1337{
return doCheckPackageSig( path_r,
root(),
true, detail_r ); }
1352 opts.push_back (
"-V");
1353 opts.push_back (
"--nodeps");
1354 opts.push_back (
"--noscripts");
1355 opts.push_back (
"--nomd5");
1356 opts.push_back (
"--");
1357 opts.push_back (packageName.c_str());
1378 if (line.length() > 12 &&
1379 (line[0] ==
'S' || line[0] ==
's' ||
1380 (line[0] ==
'.' && line[7] ==
'T')))
1383 std::string filename;
1385 filename.assign(line, 11, line.length() - 11);
1425#if defined(WORKAROUNDRPMPWDBUG)
1426 args.push_back(
"#/");
1428 args.push_back(
"rpm");
1429 args.push_back(
"--root");
1431 args.push_back(
"--dbpath");
1434 args.push_back(
"-vv");
1435 const char* argv[args.size() + opts.size() + 1];
1437 const char** p = argv;
1438 p =
copy (args.begin (), args.end (), p);
1439 p =
copy (opts.begin (), opts.end (), p);
1445 librpmDb::dbRelease(
true );
1471 const auto &readResult =
io::receiveUpto( inputfile,
'\n', 5 * 1000,
false );
1472 switch ( readResult.first ) {
1478 line += readResult.second;
1483 line += readResult.second;
1484 if ( line.size() && line.back() ==
'\n')
1489 line += readResult.second;
1491 if ( line.size() && line.back() ==
'\n')
1495 L_DBG(
"RPM_DEBUG") << line << endl;
1539void RpmDb::processConfigFiles(
const std::string& line,
const std::string& name,
const char* typemsg,
const char* difffailmsg,
const char* diffgenmsg)
1541 std::string msg = line.substr(9);
1542 std::string::size_type pos1 = std::string::npos;
1543 std::string::size_type pos2 = std::string::npos;
1544 std::string file1s, file2s;
1548 pos1 = msg.find (typemsg);
1551 if ( pos1 == std::string::npos )
1554 pos2 = pos1 + strlen (typemsg);
1556 if (pos2 >= msg.length() )
1559 file1 = msg.substr (0, pos1);
1560 file2 = msg.substr (pos2);
1567 file1 =
_root + file1;
1568 file2 =
_root + file2;
1578 ERR <<
"Could not create " << file.
asString() << endl;
1582 std::ofstream notify(file.
asString().c_str(), std::ios::out|std::ios::app);
1585 ERR <<
"Could not open " << file << endl;
1591 notify <<
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
1594 ERR <<
"diff failed" << endl;
1596 file1s.c_str(), file2s.c_str()) << endl;
1601 file1s.c_str(), file2s.c_str()) << endl;
1606 if (out.substr(0,4) ==
"--- ")
1608 out.replace(4, file1.
asString().length(), file1s);
1610 std::string::size_type pos = out.find(
"\n+++ ");
1611 if (pos != std::string::npos)
1613 out.replace(pos+5, file2.
asString().length(), file2s);
1616 notify << out << endl;
1619 notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1624 WAR <<
"rpm created " << file2 <<
" but it is not different from " << file2 << endl;
1644 report->start(filename);
1659 report->finish( excpt_r );
1675 MIL <<
"RpmDb::installPackage(" << filename <<
"," << flags <<
")" << endl;
1683 ERR <<
"backup of " << filename.
asString() <<
" failed" << endl;
1686 report->progress( 0 );
1691#if defined(WORKAROUNDDUMPPOSTTRANSBUG)
1692 if ( postTransCollector_r &&
_root ==
"/" ) {
1694 if ( postTransCollector_r ) {
1696 opts.push_back(
"--define");
1697 opts.push_back(
"_dump_posttrans 1");
1700 opts.push_back(
"-i");
1702 opts.push_back(
"-U");
1704 opts.push_back(
"--percent");
1705 opts.push_back(
"--noglob");
1709 opts.push_back(
"--ignorearch");
1712 opts.push_back(
"--nodigest");
1714 opts.push_back(
"--nosignature");
1716 opts.push_back (
"--excludedocs");
1718 opts.push_back (
"--noscripts");
1720 opts.push_back (
"--force");
1722 opts.push_back (
"--nodeps");
1724 opts.push_back (
"--ignoresize");
1726 opts.push_back (
"--justdb");
1728 opts.push_back (
"--test");
1730 opts.push_back (
"--noposttrans");
1732 opts.push_back(
"--");
1735 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
1736 opts.push_back ( quotedFilename.c_str() );
1741 unsigned lineno = 0;
1744 cmdout.
set(
"line", std::cref(line) );
1745 cmdout.
set(
"lineno", lineno );
1749 std::vector<std::string> configwarnings;
1757 sscanf( line.c_str() + 2,
"%d", &percent );
1758 report->progress( percent );
1766 cmdout.
set(
"lineno", lineno );
1767 report->report( cmdout );
1770 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1774 rpmmsg += line+
'\n';
1777 configwarnings.push_back(line);
1780 rpmmsg +=
"[truncated]\n";
1783 if ( postTransCollector_r && rpm_status == 0 ) {
1789 for (std::vector<std::string>::iterator it = configwarnings.begin();
1790 it != configwarnings.end(); ++it)
1794 _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
1796 _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
1799 _(
"rpm created %s as %s, but it was impossible to determine the difference"),
1801 _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
1804 if ( rpm_status != 0 )
1809 std::ostringstream sstr;
1810 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1811 historylog.
comment(sstr.str());
1814 if ( not rpmmsg.empty() )
1815 excpt.addHistory( rpmmsg );
1818 else if ( ! rpmmsg.empty() )
1823 std::ostringstream sstr;
1824 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1825 historylog.
comment(sstr.str());
1829 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
1846 +
"-" + package->edition().version()
1847 +
"-" + package->edition().release()
1848 +
"." + package->arch().asString(), flags, postTransCollector_r );
1855 report->start( name_r );
1870 report->finish( excpt_r );
1886 MIL <<
"RpmDb::doRemovePackage(" << name_r <<
"," << flags <<
")" << endl;
1895 ERR <<
"backup of " << name_r <<
" failed" << endl;
1897 report->progress( 0 );
1901 report->progress( 100 );
1906#if defined(WORKAROUNDDUMPPOSTTRANSBUG)
1907 if ( postTransCollector_r &&
_root ==
"/" ) {
1909 if ( postTransCollector_r ) {
1911 opts.push_back(
"--define");
1912 opts.push_back(
"_dump_posttrans 1");
1914 opts.push_back(
"-e");
1915 opts.push_back(
"--allmatches");
1918 opts.push_back(
"--noscripts");
1920 opts.push_back(
"--nodeps");
1922 opts.push_back(
"--justdb");
1924 opts.push_back (
"--test");
1927 WAR <<
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
1930 opts.push_back(
"--");
1931 opts.push_back(name_r.c_str());
1936 unsigned lineno = 0;
1939 cmdout.
set(
"line", std::cref(line) );
1940 cmdout.
set(
"lineno", lineno );
1951 report->progress( 5 );
1959 cmdout.
set(
"lineno", lineno );
1960 report->report( cmdout );
1963 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1966 rpmmsg += line+
'\n';
1969 rpmmsg +=
"[truncated]\n";
1970 report->progress( 50 );
1972 if ( postTransCollector_r && rpm_status == 0 ) {
1978 if ( rpm_status != 0 )
1981 str::form(
"%s remove failed", name_r.c_str()),
true );
1982 std::ostringstream sstr;
1983 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1984 historylog.
comment(sstr.str());
1987 if ( not rpmmsg.empty() )
1988 excpt.addHistory( rpmmsg );
1991 else if ( ! rpmmsg.empty() )
1994 str::form(
"%s removed ok", name_r.c_str()),
true );
1996 std::ostringstream sstr;
1997 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1998 historylog.
comment(sstr.str());
2002 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2015 MIL <<
"RpmDb::runposttrans(" << filename_r <<
")" << endl;
2018 opts.push_back(
"-vv");
2019 opts.push_back(
"--runposttrans");
2020 opts.push_back(filename_r.
c_str());
2027 static const str::regex rx(
"^D: (%.*): scriptlet start$" );
2039 output_r(
"RIPOFF:"+what[1] );
2056 if ( rpm_status != 0 ) {
2057 WAR <<
"rpm --runposttrans returned " << rpm_status << endl;
2092 INT <<
"_backuppath empty" << endl;
2100 ERR <<
"Error while getting changed files for package " <<
2101 packageName << endl;
2107 DBG <<
"package " << packageName <<
" not changed -> no backup" << endl;
2118 time_t currentTime = time(0);
2119 struct tm *currentLocalTime = localtime(¤tTime);
2121 int date = (currentLocalTime->tm_year + 1900) * 10000
2122 + (currentLocalTime->tm_mon + 1) * 100
2123 + currentLocalTime->tm_mday;
2129 +
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2132 while (
PathInfo(backupFilename).isExist() && num++ < 1000);
2137 ERR << filestobackupfile.
asString() <<
" already exists and is no file" << endl;
2141 std::ofstream fp ( filestobackupfile.
asString().c_str(), std::ios::out|std::ios::trunc );
2145 ERR <<
"could not open " << filestobackupfile.
asString() << endl;
2149 for (FileList::const_iterator cit =
fileList.begin();
2152 std::string name = *cit;
2153 if ( name[0] ==
'/' )
2156 name = name.substr( 1 );
2158 DBG <<
"saving file "<< name << endl;
2163 const char*
const argv[] =
2169 "--ignore-failed-read",
2173 filestobackupfile.
asString().c_str(),
2189 int ret = tar.
close();
2193 ERR <<
"tar failed: " << tarmsg << endl;
2198 MIL <<
"tar backup ok" << endl;
2219#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2231 OUTS(
CHK_ERROR,
_(
"File does not exist or signature can't be checked") );
2241 for (
const auto & el : obj )
2242 str << el.second << endl;
#define MAXRPMMESSAGELINES
#define FAILIFNOTINITIALIZED
#define FILEFORBACKUPFILES
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Mime type like 'type/subtype' classification of content.
Store and operate on date (time_t).
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
static Date now()
Return the current time.
Assign a vaiable a certain value when going out of scope.
Edition represents [epoch:]version[-release]
std::string version() const
Version.
std::string release() const
Release.
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Base class for Exception.
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
void addHistory(const std::string &msg_r)
Add some message text to the history.
void moveToHistory(TContainer &&msgc_r)
addHistory from string container types (oldest first) moving
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
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.
Temorarily change a locale category value.
TraitsType::constPtrType constPtr
Maintain [min,max] and counter (value) for progress counting.
value_type reportValue() const
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
bool toMax()
Set counter value to current max value (unless no range).
bool incr(value_type val_r=1)
Increment counter value (default by 1).
bool toMin()
Set counter value to current min value.
void range(value_type max_r)
Set new [0,max].
Class representing one GPG Public Keys data.
std::string gpgPubkeyRelease() const
Gpg-pubkey release as computed by rpm (hexencoded created)
std::string gpgPubkeyVersion() const
Gpg-pubkey version as computed by rpm (trailing 8 byte id)
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
Pathname path() const
File containing the ASCII armored key.
std::string gpgPubkeyRelease() const
std::string asString() const
std::string gpgPubkeyVersion() const
bool hasSubkeys() const
!<
static ZConfig & instance()
Singleton ctor.
ZYpp::Ptr getZYpp()
Convenience to get the Pointer to the ZYpp instance.
friend std::ostream & operator<<(std::ostream &str, const ReferenceCounted &obj)
Stream output via dumpOn.
Typesafe passing of user data via callbacks.
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
void setBlocking(bool mode)
Set the blocking mode of the input stream.
FILE * inputFile() const
Return the input stream.
std::string receiveLine()
Read one line from the input stream.
Wrapper class for stat/lstat.
bool isExist() const
Return whether valid stat info exists.
const char * c_str() const
String representation.
const std::string & asString() const
String representation.
std::string basename() const
Return the last component of this path.
bool empty() const
Test for an empty path.
bool relative() const
Test for a relative path.
Provide a new empty temporary file and delete it when no longer needed.
Regular expression match result.
Extract and remember posttrans scripts for later execution.
void collectPosttransInfo(const Pathname &rpmPackage_r, const std::vector< std::string > &runposttrans_r)
Extract and remember a packages posttrans script or dump_posttrans lines for later execution.
bool hasPosttransScript(const Pathname &rpmPackage_r)
Test whether a package defines a posttrans script.
Interface to the rpm program.
void getData(const std::string &name_r, RpmHeader::constPtr &result_r) const
Get an installed packages data from rpmdb.
void doRebuildDatabase(callback::SendReport< RebuildDBReport > &report)
bool queryChangedFiles(FileList &fileList, const std::string &packageName)
determine which files of an installed package have been modified.
std::string error_message
Error message from running rpm as external program.
bool hasRequiredBy(const std::string &tag_r) const
Return true if at least one package requires a certain tag.
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.
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
static librpmDb::constPtr dbOpenCreate(const Pathname &root_r, const Pathname &dbPath_r=Pathname())
Assert the rpmdb below the system at root_r exists.
static Pathname suggestedDbPath(const Pathname &root_r)
String related utilities and Regular expression matching.
Namespace intended to collect all environment variables we use.
Types and functions for filesystem operations.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
int copy(const Pathname &file, const Pathname &dest)
Like 'cp file dest'.
Pathname expandlink(const Pathname &path_r)
Recursively follows the symlink pointed to by path_r and returns the Pathname to the real file or dir...
int unlink(const Pathname &path)
Like 'unlink'.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
std::string numstring(char n, int w=0)
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
std::string toLower(const std::string &s)
Return lowercase version of s.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
unsigned diffFiles(const std::string &file1, const std::string &file2, std::string &out, int maxlines)
std::ostream & operator<<(std::ostream &str, const librpmDb::db_const_iterator &obj)
_dumpPath dumpPath(const Pathname &root_r, const Pathname &sub_r)
dumpPath iomaip to dump '(root_r)sub_r' output,
static shared_ptr< KeyRingSignalReceiver > sKeyRingReceiver
Easy-to use interface to the ZYPP dependency resolver.
Temporarily connect a ReceiveReport then restore the previous one.
KeyRingSignalReceiver & operator=(const KeyRingSignalReceiver &)=delete
void trustedKeyRemoved(const PublicKey &key) override
KeyRingSignalReceiver & operator=(KeyRingSignalReceiver &&)=delete
KeyRingSignalReceiver(const KeyRingSignalReceiver &)=delete
KeyRingSignalReceiver(RpmDb &rpmdb)
void trustedKeyAdded(const PublicKey &key) override
~KeyRingSignalReceiver() override
KeyRingSignalReceiver(KeyRingSignalReceiver &&)=delete
Detailed rpm signature check log messages A single multiline message if CHK_OK.
Wrapper providing a librpmDb::db_const_iterator for this RpmDb.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.