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"
74 namespace zypp_readonly_hack
82 static bool val = [](){
83 const char *
env = getenv(
"ZYPP_RPM_DEBUG");
98const char* quoteInFilename_m =
"\'\"";
99inline std::string rpmQuoteFilename(
const Pathname & path_r )
101 std::string path( path_r.
asString() );
102 for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m );
103 pos != std::string::npos;
104 pos = path.find_first_of( quoteInFilename_m, pos ) )
106 path.insert( pos,
"\\" );
119#if defined(WORKAROUNDRPMPWDBUG)
126 WAR <<
"Can't get cwd!" << endl;
148 MIL <<
"trusted key added to zypp Keyring. Importing..." << endl;
154 MIL <<
"Trusted key removed from zypp Keyring. Removing..." << endl;
163unsigned diffFiles(
const std::string& file1,
const std::string& file2, std::string& out,
int maxlines)
184 if (maxlines<0?
true:count<maxlines)
197#define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); }
208 : _backuppath (
"/var/adm/backup")
209 , _packagebackups(false)
216 setenv(
"RPM_IgnoreFailedSymlinks",
"1", 1 );
228 MIL <<
"~RpmDb()" << endl;
231 MIL <<
"~RpmDb() end" << endl;
265 if ( root_r.
empty() )
273 if ( dbPath_r !=
"/var/lib/rpm" && !
PathInfo( root_r/
"/var/lib/rpm" ).isExist() )
275 WAR <<
"Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
289 if ( root_r ==
_root ) {
297 MIL <<
"Calling initDatabase: " <<
dumpPath( root_r, dbPath_r )
298 << ( doRebuild_r ?
" (rebuilddb)" :
"" ) << endl;
312 MIL <<
"Synchronizing keys with zypp keyring" << endl;
320 librpmDb::dbRelease(
true );
322 MIL <<
"InitDatabase: " << *
this << endl;
341 MIL <<
"closeDatabase: " << *
this << endl;
372 MIL <<
"RpmDb::rebuildDatabase" << *
this << endl;
386 opts.push_back(
"--rebuilddb");
387 opts.push_back(
"-vv");
397 tics.
range( hdrTotal );
400 return report->progress( tics_r.
reportValue(), mydbpath );
408 static const std::string debugPrefix {
"D:" };
409 static const std::string progressPrefix {
"D: read h#" };
410 static const std::string ignoreSuffix {
"digest: OK" };
425 WAR <<
"User requested abort." << endl;
449 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
456 : _inRpmKeys( nullptr )
457 , _inZyppKeys( nullptr )
460 void updateIf(
const Edition & rpmKey_r )
462 std::string keyRelease( rpmKey_r.
release() );
463 int comp = _release.compare( keyRelease );
467 _release.swap( keyRelease );
468 _inRpmKeys = &rpmKey_r;
469 _inZyppKeys =
nullptr;
470 if ( !keyRelease.empty() )
471 DBG <<
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
473 else if ( comp == 0 )
477 _inRpmKeys = &rpmKey_r;
481 DBG <<
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
487 int comp = _release.compare( keyRelease );
491 _release.swap( keyRelease );
492 _inRpmKeys =
nullptr;
493 _inZyppKeys = &zyppKey_r;
494 if ( !keyRelease.empty() )
495 DBG <<
"Old key in R: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
497 else if ( comp == 0 )
501 _inZyppKeys = &zyppKey_r;
505 DBG <<
"Old key in Z: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
508 std::string _release;
509 const Edition * _inRpmKeys;
515 std::map<std::string,Key> _keymap;
517 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
519 _keymap[(*it).version()].updateIf( *it );
522 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
524 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
528 std::set<Edition> rpmKeys;
529 std::list<PublicKeyData> zyppKeys;
530 for_( it, _keymap.begin(), _keymap.end() )
532 DBG <<
"gpg-pubkey-" << (*it).first <<
"-" << (*it).second._release <<
" "
533 << ( (*it).second._inRpmKeys ?
"R" :
"_" )
534 << ( (*it).second._inZyppKeys ?
"Z" :
"_" ) << endl;
535 if ( ! (*it).second._inRpmKeys )
537 zyppKeys.push_back( *(*it).second._inZyppKeys );
539 if ( ! (*it).second._inZyppKeys )
541 rpmKeys.insert( *(*it).second._inRpmKeys );
544 rpmKeys_r.swap( rpmKeys );
545 zyppKeys_r.swap( zyppKeys );
552 MIL <<
"Going to sync trusted keys..." << endl;
554 std::list<PublicKeyData> zyppKeys(
getZYpp()->keyRing()->trustedPublicKeyData() );
566 MIL <<
"Removing excess keys in zypp trusted keyring" << std::endl;
572 if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) )
574 DBG <<
"Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl;
575 getZYpp()->keyRing()->deleteKey( keyData.id(),
true );
576 if ( !dirty ) dirty =
true;
580 zyppKeys =
getZYpp()->keyRing()->trustedPublicKeyData();
583 computeKeyRingSync( rpmKeys, zyppKeys );
584 MIL << (mode_r &
SYNC_TO_KEYRING ?
"" :
"(skip) ") <<
"Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
585 MIL << (mode_r &
SYNC_FROM_KEYRING ?
"" :
"(skip) ") <<
"Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
591 MIL <<
"Exporting rpm keyring into zypp trusted keyring" <<endl;
598 std::ofstream tmpos( tmpfile.
path().
c_str() );
599 for_( it, rpmKeys.begin(), rpmKeys.end() )
603 getData(
"gpg-pubkey", *it, result );
604 tmpos << result->tag_description() << endl;
609 getZYpp()->keyRing()->multiKeyImport( tmpfile.
path(),
true );
613 std::set<Edition> missingKeys;
614 for (
const Edition & key : rpmKeys )
616 if (
getZYpp()->keyRing()->isKeyTrusted( key.version() ) )
618 ERR <<
"Could not import key:" <<
str::Format(
"gpg-pubkey-%s") % key <<
" into zypp keyring (V3 key?)" << endl;
619 missingKeys.insert( key );
621 if ( ! missingKeys.empty() )
627 ERR <<
"Could not import keys into zypp keyring: " << endl;
635 MIL <<
"Importing zypp trusted keyring" << std::endl;
636 for_( it, zyppKeys.begin(), zyppKeys.end() )
648 MIL <<
"Trusted keys synced." << endl;
670 WAR <<
"Key " << pubkey_r <<
" can not be imported. (READONLY MODE)" << endl;
677 bool hasOldkeys =
false;
679 for_( it, rpmKeys.begin(), rpmKeys.end() )
688 MIL <<
"Key " << pubkey_r <<
" is already in the rpm trusted keyring. (skip import)" << endl;
692 if ( keyEd.
version() != (*it).version() )
695 if ( keyEd.
release() < (*it).release() )
697 MIL <<
"Key " << pubkey_r <<
" is older than one in the rpm trusted keyring. (skip import)" << endl;
705 MIL <<
"Key " << pubkey_r <<
" will be imported into the rpm trusted keyring." << (hasOldkeys?
"(update)":
"(new)") << endl;
711 std::string keyName(
"gpg-pubkey-" + keyEd.
version() );
713 opts.push_back (
"-e" );
714 opts.push_back (
"--allmatches" );
715 opts.push_back (
"--" );
716 opts.push_back ( keyName.c_str() );
727 ERR <<
"Failed to remove key " << pubkey_r <<
" from RPM trusted keyring (ignored)" << endl;
731 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
737 opts.push_back (
"--import" );
738 opts.push_back (
"--" );
740 opts.push_back ( pubkeypath.c_str() );
744 std::vector<std::string> excplines;
750 excplines.push_back( std::move(line) );
766 MIL <<
"Key " << pubkey_r <<
" imported in rpm trusted keyring." << endl;
783 std::set<Edition>::const_iterator found_edition = rpm_keys.end();
786 for_( it, rpm_keys.begin(), rpm_keys.end() )
788 if ( (*it).version() == pubkeyVersion )
796 if (found_edition == rpm_keys.end())
798 WAR <<
"Key " << pubkey_r.
id() <<
" is not in rpm db" << endl;
802 std::string rpm_name(
"gpg-pubkey-" + found_edition->asString());
805 opts.push_back (
"-e" );
806 opts.push_back (
"--" );
807 opts.push_back ( rpm_name.c_str() );
811 std::vector<std::string> excplines;
817 excplines.push_back( std::move(line) );
833 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
845 std::list<PublicKey> ret;
848 for ( it.findByName(
"gpg-pubkey" ); *it; ++it )
850 Edition edition = it->tag_edition();
855 getData(
"gpg-pubkey", edition, result );
862 os << result->tag_description();
871 catch ( std::exception & e )
873 ERR <<
"Could not dump key " << edition.
asString() <<
" in tmp file " << file.
path() << endl;
883 std::set<Edition> ret;
886 for ( it.findByName(
"gpg-pubkey" ); *it; ++it )
888 Edition edition = it->tag_edition();
890 ret.insert( edition );
907 std::list<FileInfo> result;
913 found = it.findPackage( name_r );
917 found = it.findPackage( name_r, edition_r );
934bool RpmDb::hasFile(
const std::string & file_r,
const std::string & name_r )
const
940 res = it.findByFile( file_r );
944 res = (it->tag_name() == name_r);
963 if (it.findByFile( file_r ))
965 return it->tag_name();
981 return it.findByProvides( tag_r );
995 return it.findByRequiredBy( tag_r );
1009 return it.findByConflicts( tag_r );
1023 return it.findPackage( name_r );
1037 return it.findPackage( name_r, ed_r );
1052 it.findPackage( name_r );
1072 it.findPackage( name_r, ed_r );
1083 struct RpmlogCapture :
public std::vector<std::string>
1087 rpmlogSetCallback( rpmLogCB,
this );
1088 _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
1091 RpmlogCapture(
const RpmlogCapture &) =
delete;
1092 RpmlogCapture(RpmlogCapture &&) =
delete;
1093 RpmlogCapture &operator=(
const RpmlogCapture &) =
delete;
1094 RpmlogCapture &operator=(RpmlogCapture &&) =
delete;
1097 rpmlogSetCallback(
nullptr,
nullptr );
1098 rpmlogSetMask( _oldMask );
1101 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1102 {
return reinterpret_cast<RpmlogCapture*
>(data_r)->rpmLog( rec_r ); }
1104 int rpmLog( rpmlogRec rec_r )
1106 std::string l { ::rpmlogRecMessage( rec_r ) };
1108 push_back( std::move(l) );
1116 std::ostream &
operator<<( std::ostream &
str,
const RpmlogCapture & obj )
1119 for (
const auto & l : obj ) {
1120 if ( sep )
str << sep;
else sep =
'\n';
1129 bool requireGPGSig_r,
1130 RpmDb::CheckPackageDetail & detail_r )
1133 if ( ! file.isFile() )
1135 ERR <<
"Not a file: " << file << endl;
1139 FD_t fd = ::Fopen( file.asString().c_str(),
"r.ufdio" );
1140 if ( fd == 0 || ::Ferror(fd) )
1142 ERR <<
"Can't open file for reading: " << file <<
" (" << ::Fstrerror(fd) <<
")" << endl;
1147 rpmts ts = ::rpmtsCreate();
1148 ::rpmtsSetRootDir( ts, root_r.
c_str() );
1149 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1150#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP
1151 ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
1154 RpmlogCapture vresult;
1156 static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0,
sizeof(rpmQVKArguments_s) );
return qva; })();
1157 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
1166 typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
1167 static const ResultMap resultMap {
1175 auto getresult = [](
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1176 auto it = resultMap.find( key );
1181 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1186 SawHeaderSig = (1 << 0),
1187 SawHeaderDigest = (1 << 1),
1188 SawPayloadDigest = (1 << 2),
1190 SawDigest = (1 << 4),
1192 unsigned saw = SawNone;
1194 static const str::regex rx(
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1196 for (
const std::string & line : vresult )
1198 if ( line[0] !=
' ' )
1204 lineres = getresult( resultMap, what[3] );
1208 if ( what[1][0] ==
'H' ) {
1209 saw |= ( what[2][0] ==
'S' ? SawHeaderSig :SawHeaderDigest );
1211 else if ( what[1][0] ==
'P' ) {
1212 if ( what[2][0] ==
'd' ) saw |= SawPayloadDigest;
1215 saw |= ( what[2][0] ==
'S' ? SawSig : SawDigest );
1220 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, line ) );
1242 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1243 if ( not isSigned ) {
1244 std::string message {
" " };
1245 if ( not (saw & SawHeaderSig) )
1246 message +=
_(
"Package header is not signed!");
1248 message +=
_(
"Package payload is not signed!");
1250 detail_r.push_back( RpmDb::CheckPackageDetail::value_type(
RpmDb::CHK_NOSIG, std::move(message) ) );
1251 if ( requireGPGSig_r )
1260 bool didReadHeader =
false;
1261 std::unordered_map< std::string, std::string> fprs;
1264 str::regex rxexpr(
"key ID ([a-fA-F0-9]{8}):" );
1265 for (
auto &detail : detail_r ) {
1266 auto &line = detail.second;
1270 if ( !didReadHeader ) {
1271 didReadHeader =
true;
1277 const auto &addFprs = [&](
auto tag ){
1278 const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
1279 for (
const auto &
id : list1 ) {
1280 if (
id.size() <= 8 )
1284 fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
1288 addFprs( RPMTAG_SIGGPG );
1289 addFprs( RPMTAG_SIGPGP );
1290 addFprs( RPMTAG_RSAHEADER );
1291 addFprs( RPMTAG_DSAHEADER );
1294 ERR <<
"Failed to read package signatures." << std::endl;
1305 if (
const auto &i = fprs.find( keyId ); i != fprs.end() ) {
1312 WAR << path_r <<
" (" << requireGPGSig_r <<
" -> " << ret <<
")" << endl;
1313 WAR << vresult << endl;
1316 DBG << path_r <<
" [0-Signature is OK]" << endl;
1327{
return doCheckPackageSig( path_r,
root(),
false, detail_r ); }
1333{
return doCheckPackageSig( path_r,
root(),
true, detail_r ); }
1348 opts.push_back (
"-V");
1349 opts.push_back (
"--nodeps");
1350 opts.push_back (
"--noscripts");
1351 opts.push_back (
"--nomd5");
1352 opts.push_back (
"--");
1353 opts.push_back (packageName.c_str());
1374 if (line.length() > 12 &&
1375 (line[0] ==
'S' || line[0] ==
's' ||
1376 (line[0] ==
'.' && line[7] ==
'T')))
1379 std::string filename;
1381 filename.assign(line, 11, line.length() - 11);
1421#if defined(WORKAROUNDRPMPWDBUG)
1422 args.push_back(
"#/");
1424 args.push_back(
"rpm");
1425 args.push_back(
"--root");
1427 args.push_back(
"--dbpath");
1430 args.push_back(
"-vv");
1431 const char* argv[args.size() + opts.size() + 1];
1433 const char** p = argv;
1434 p =
copy (args.begin (), args.end (), p);
1435 p =
copy (opts.begin (), opts.end (), p);
1441 librpmDb::dbRelease(
true );
1467 const auto &readResult =
io::receiveUpto( inputfile,
'\n', 5 * 1000,
false );
1468 switch ( readResult.first ) {
1474 line += readResult.second;
1479 line += readResult.second;
1480 if ( line.size() && line.back() ==
'\n')
1485 line += readResult.second;
1487 if ( line.size() && line.back() ==
'\n')
1491 L_DBG(
"RPM_DEBUG") << line << endl;
1535void RpmDb::processConfigFiles(
const std::string& line,
const std::string& name,
const char* typemsg,
const char* difffailmsg,
const char* diffgenmsg)
1537 std::string msg = line.substr(9);
1538 std::string::size_type pos1 = std::string::npos;
1539 std::string::size_type pos2 = std::string::npos;
1540 std::string file1s, file2s;
1544 pos1 = msg.find (typemsg);
1547 if ( pos1 == std::string::npos )
1550 pos2 = pos1 + strlen (typemsg);
1552 if (pos2 >= msg.length() )
1555 file1 = msg.substr (0, pos1);
1556 file2 = msg.substr (pos2);
1563 file1 =
_root + file1;
1564 file2 =
_root + file2;
1574 ERR <<
"Could not create " << file.
asString() << endl;
1578 std::ofstream notify(file.
asString().c_str(), std::ios::out|std::ios::app);
1581 ERR <<
"Could not open " << file << endl;
1587 notify <<
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
1590 ERR <<
"diff failed" << endl;
1592 file1s.c_str(), file2s.c_str()) << endl;
1597 file1s.c_str(), file2s.c_str()) << endl;
1602 if (out.substr(0,4) ==
"--- ")
1604 out.replace(4, file1.
asString().length(), file1s);
1606 std::string::size_type pos = out.find(
"\n+++ ");
1607 if (pos != std::string::npos)
1609 out.replace(pos+5, file2.
asString().length(), file2s);
1612 notify << out << endl;
1615 notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1620 WAR <<
"rpm created " << file2 <<
" but it is not different from " << file2 << endl;
1640 report->start(filename);
1655 report->finish( excpt_r );
1671 MIL <<
"RpmDb::installPackage(" << filename <<
"," << flags <<
")" << endl;
1679 ERR <<
"backup of " << filename.
asString() <<
" failed" << endl;
1682 report->progress( 0 );
1687 if ( postTransCollector_r ) {
1688 opts.push_back(
"--define");
1689 opts.push_back(
"_dump_posttrans 1");
1692 opts.push_back(
"-i");
1694 opts.push_back(
"-U");
1696 opts.push_back(
"--percent");
1697 opts.push_back(
"--noglob");
1701 opts.push_back(
"--ignorearch");
1704 opts.push_back(
"--nodigest");
1706 opts.push_back(
"--nosignature");
1708 opts.push_back (
"--excludedocs");
1710 opts.push_back (
"--noscripts");
1712 opts.push_back (
"--force");
1714 opts.push_back (
"--nodeps");
1716 opts.push_back (
"--ignoresize");
1718 opts.push_back (
"--justdb");
1720 opts.push_back (
"--test");
1722 opts.push_back (
"--noposttrans");
1724 opts.push_back(
"--");
1727 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
1728 opts.push_back ( quotedFilename.c_str() );
1733 unsigned lineno = 0;
1736 cmdout.
set(
"line", std::cref(line) );
1737 cmdout.
set(
"lineno", lineno );
1741 std::vector<std::string> configwarnings;
1749 sscanf( line.c_str() + 2,
"%d", &percent );
1750 report->progress( percent );
1758 cmdout.
set(
"lineno", lineno );
1759 report->report( cmdout );
1762 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1766 rpmmsg += line+
'\n';
1769 configwarnings.push_back(line);
1772 rpmmsg +=
"[truncated]\n";
1775 if ( postTransCollector_r && rpm_status == 0 ) {
1781 for (std::vector<std::string>::iterator it = configwarnings.begin();
1782 it != configwarnings.end(); ++it)
1786 _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
1788 _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
1791 _(
"rpm created %s as %s, but it was impossible to determine the difference"),
1793 _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
1796 if ( rpm_status != 0 )
1801 std::ostringstream sstr;
1802 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1803 historylog.
comment(sstr.str());
1806 if ( not rpmmsg.empty() )
1807 excpt.addHistory( rpmmsg );
1810 else if ( ! rpmmsg.empty() )
1815 std::ostringstream sstr;
1816 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1817 historylog.
comment(sstr.str());
1821 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
1838 +
"-" + package->edition().version()
1839 +
"-" + package->edition().release()
1840 +
"." + package->arch().asString(), flags, postTransCollector_r );
1847 report->start( name_r );
1862 report->finish( excpt_r );
1878 MIL <<
"RpmDb::doRemovePackage(" << name_r <<
"," << flags <<
")" << endl;
1887 ERR <<
"backup of " << name_r <<
" failed" << endl;
1889 report->progress( 0 );
1893 report->progress( 100 );
1898 if ( postTransCollector_r ) {
1899 opts.push_back(
"--define");
1900 opts.push_back(
"_dump_posttrans 1");
1902 opts.push_back(
"-e");
1903 opts.push_back(
"--allmatches");
1906 opts.push_back(
"--noscripts");
1908 opts.push_back(
"--nodeps");
1910 opts.push_back(
"--justdb");
1912 opts.push_back (
"--test");
1915 WAR <<
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
1918 opts.push_back(
"--");
1919 opts.push_back(name_r.c_str());
1924 unsigned lineno = 0;
1927 cmdout.
set(
"line", std::cref(line) );
1928 cmdout.
set(
"lineno", lineno );
1939 report->progress( 5 );
1947 cmdout.
set(
"lineno", lineno );
1948 report->report( cmdout );
1951 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1954 rpmmsg += line+
'\n';
1957 rpmmsg +=
"[truncated]\n";
1958 report->progress( 50 );
1960 if ( postTransCollector_r && rpm_status == 0 ) {
1966 if ( rpm_status != 0 )
1969 str::form(
"%s remove failed", name_r.c_str()),
true );
1970 std::ostringstream sstr;
1971 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1972 historylog.
comment(sstr.str());
1975 if ( not rpmmsg.empty() )
1976 excpt.addHistory( rpmmsg );
1979 else if ( ! rpmmsg.empty() )
1982 str::form(
"%s removed ok", name_r.c_str()),
true );
1984 std::ostringstream sstr;
1985 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1986 historylog.
comment(sstr.str());
1990 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2003 MIL <<
"RpmDb::runposttrans(" << filename_r <<
")" << endl;
2006 opts.push_back(
"-vv");
2007 opts.push_back(
"--runposttrans");
2008 opts.push_back(filename_r.
c_str());
2015 static const str::regex rx(
"^D: (%.*): scriptlet start$" );
2027 output_r(
"RIPOFF:"+what[1] );
2044 if ( rpm_status != 0 ) {
2045 WAR <<
"rpm --runposttrans returned " << rpm_status << endl;
2080 INT <<
"_backuppath empty" << endl;
2088 ERR <<
"Error while getting changed files for package " <<
2089 packageName << endl;
2095 DBG <<
"package " << packageName <<
" not changed -> no backup" << endl;
2106 time_t currentTime = time(0);
2107 struct tm *currentLocalTime = localtime(¤tTime);
2109 int date = (currentLocalTime->tm_year + 1900) * 10000
2110 + (currentLocalTime->tm_mon + 1) * 100
2111 + currentLocalTime->tm_mday;
2117 +
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2120 while (
PathInfo(backupFilename).isExist() && num++ < 1000);
2125 ERR << filestobackupfile.
asString() <<
" already exists and is no file" << endl;
2129 std::ofstream fp ( filestobackupfile.
asString().c_str(), std::ios::out|std::ios::trunc );
2133 ERR <<
"could not open " << filestobackupfile.
asString() << endl;
2137 for (FileList::const_iterator cit =
fileList.begin();
2140 std::string name = *cit;
2141 if ( name[0] ==
'/' )
2144 name = name.substr( 1 );
2146 DBG <<
"saving file "<< name << endl;
2151 const char*
const argv[] =
2157 "--ignore-failed-read",
2161 filestobackupfile.
asString().c_str(),
2177 int ret = tar.
close();
2181 ERR <<
"tar failed: " << tarmsg << endl;
2186 MIL <<
"tar backup ok" << endl;
2207#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2209 OUTS( CHK_OK,
_(
"Signature is OK") );
2211 OUTS( CHK_NOTFOUND,
_(
"Unknown type of signature") );
2213 OUTS( CHK_FAIL,
_(
"Signature does not verify") );
2215 OUTS( CHK_NOTTRUSTED,
_(
"Signature is OK, but key is not trusted") );
2217 OUTS( CHK_NOKEY,
_(
"Signatures public key is not available") );
2219 OUTS( CHK_ERROR,
_(
"File does not exist or signature can't be checked") );
2221 OUTS( CHK_NOSIG,
_(
"File is unsigned") );
2229 for (
const auto & el : obj )
2230 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.
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.