15#include <rpm/rpmcli.h>
16#include <rpm/rpmlog.h>
32#include <zypp-core/base/StringV.h>
33#include <zypp/base/Logger.h>
34#include <zypp/base/String.h>
35#include <zypp/base/Gettext.h>
37#include <zypp-core/base/DtorReset>
40#include <zypp/Pathname.h>
41#include <zypp/PathInfo.h>
43#include <zypp-core/ui/ProgressData>
52#include <zypp/TmpPath.h>
57#include <zypp/base/IOTools.h>
62#define WARNINGMAILPATH "/var/log/YaST2/"
63#define FILEFORBACKUPFILES "YaSTBackupModifiedFiles"
64#define MAXRPMMESSAGELINES 10000
66#define WORKAROUNDRPMPWDBUG
70#define WORKAROUNDDUMPPOSTTRANSBUG
72#undef ZYPP_BASE_LOGGER_LOGGROUP
73#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb"
77 namespace zypp_readonly_hack
85 static bool val = [](){
86 const char * env = getenv(
"ZYPP_RPM_DEBUG");
102const char* quoteInFilename_m =
"\'\"";
104const char* quoteInFilename_m =
" \t\'\"";
106inline std::string rpmQuoteFilename(
const Pathname & path_r )
108 std::string path( path_r.
asString() );
109 for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m );
110 pos != std::string::npos;
111 pos = path.find_first_of( quoteInFilename_m, pos ) )
113 path.insert( pos,
"\\" );
126#if defined(WORKAROUNDRPMPWDBUG)
133 WAR <<
"Can't get cwd!" << endl;
154 MIL <<
"trusted key added to zypp Keyring. Importing..." << endl;
160 MIL <<
"Trusted key removed from zypp Keyring. Removing..." << endl;
169unsigned diffFiles(
const std::string file1,
const std::string file2, std::string& out,
int maxlines)
190 if (maxlines<0?
true:count<maxlines)
216#define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); }
227 : _backuppath (
"/var/adm/backup")
228 , _packagebackups(false)
235 setenv(
"RPM_IgnoreFailedSymlinks",
"1", 1 );
247 MIL <<
"~RpmDb()" << endl;
250 MIL <<
"~RpmDb() end" << endl;
276 bool quickinit( root_r.
empty() );
278 if ( root_r.
empty() )
286 if ( dbPath_r !=
"/var/lib/rpm" && !
PathInfo( root_r/
"/var/lib/rpm" ).isExist() )
288 WAR <<
"Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
302 if ( root_r ==
_root ) {
310 MIL <<
"Calling initDatabase: " <<
stringPath( root_r, dbPath_r )
311 << ( doRebuild_r ?
" (rebuilddb)" :
"" )
312 << ( quickinit ?
" (quickinit)" :
"" ) << endl;
321 MIL <<
"QUICK initDatabase (no systemRoot set)" << endl;
343 MIL <<
"Synchronizing keys with zypp keyring" << endl;
352 MIL <<
"InitDatabase: " << *
this << endl;
368 MIL <<
"Calling closeDatabase: " << *
this << endl;
380 MIL <<
"closeDatabase: " << *
this << endl;
410 MIL <<
"RpmDb::rebuildDatabase" << *
this << endl;
424 opts.push_back(
"--rebuilddb");
425 opts.push_back(
"-vv");
435 tics.
range( hdrTotal );
438 return report->progress( tics_r.
reportValue(), mydbpath );
446 static const std::string debugPrefix {
"D:" };
447 static const std::string progressPrefix {
"D: read h#" };
448 static const std::string ignoreSuffix {
"digest: OK" };
463 WAR <<
"User requested abort." << endl;
487 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
498 void updateIf(
const Edition & rpmKey_r )
500 std::string keyRelease( rpmKey_r.
release() );
501 int comp = _release.compare( keyRelease );
505 _release.swap( keyRelease );
506 _inRpmKeys = &rpmKey_r;
507 _inZyppKeys =
nullptr;
508 if ( !keyRelease.empty() )
509 DBG <<
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
511 else if ( comp == 0 )
515 _inRpmKeys = &rpmKey_r;
519 DBG <<
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
525 int comp = _release.compare( keyRelease );
529 _release.swap( keyRelease );
530 _inRpmKeys =
nullptr;
531 _inZyppKeys = &zyppKey_r;
532 if ( !keyRelease.empty() )
533 DBG <<
"Old key in R: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
535 else if ( comp == 0 )
539 _inZyppKeys = &zyppKey_r;
543 DBG <<
"Old key in Z: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
546 std::string _release;
553 std::map<std::string,Key> _keymap;
555 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
557 _keymap[(*it).version()].updateIf( *it );
560 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
562 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
566 std::set<Edition> rpmKeys;
567 std::list<PublicKeyData> zyppKeys;
568 for_( it, _keymap.begin(), _keymap.end() )
570 DBG <<
"gpg-pubkey-" << (*it).first <<
"-" << (*it).second._release <<
" "
571 << ( (*it).second._inRpmKeys ?
"R" :
"_" )
572 << ( (*it).second._inZyppKeys ?
"Z" :
"_" ) << endl;
573 if ( ! (*it).second._inRpmKeys )
575 zyppKeys.push_back( *(*it).second._inZyppKeys );
577 if ( ! (*it).second._inZyppKeys )
579 rpmKeys.insert( *(*it).second._inRpmKeys );
582 rpmKeys_r.swap( rpmKeys );
583 zyppKeys_r.swap( zyppKeys );
590 MIL <<
"Going to sync trusted keys..." << endl;
592 std::list<PublicKeyData> zyppKeys( getZYpp()->keyRing()->trustedPublicKeyData() );
604 MIL <<
"Removing excess keys in zypp trusted keyring" << std::endl;
610 if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) )
612 DBG <<
"Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl;
613 getZYpp()->keyRing()->deleteKey( keyData.id(),
true );
614 if ( !dirty ) dirty =
true;
618 zyppKeys = getZYpp()->keyRing()->trustedPublicKeyData();
621 computeKeyRingSync( rpmKeys, zyppKeys );
622 MIL << (mode_r &
SYNC_TO_KEYRING ?
"" :
"(skip) ") <<
"Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
623 MIL << (mode_r &
SYNC_FROM_KEYRING ?
"" :
"(skip) ") <<
"Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
629 MIL <<
"Exporting rpm keyring into zypp trusted keyring" <<endl;
634 TmpFile tmpfile( getZYpp()->tmpPath() );
636 std::ofstream tmpos( tmpfile.
path().
c_str() );
637 for_( it, rpmKeys.begin(), rpmKeys.end() )
641 getData(
"gpg-pubkey", *it, result );
642 tmpos << result->tag_description() << endl;
647 getZYpp()->keyRing()->multiKeyImport( tmpfile.
path(),
true );
651 std::set<Edition> missingKeys;
652 for (
const Edition & key : rpmKeys )
654 if ( getZYpp()->keyRing()->isKeyTrusted( key.version() ) )
656 ERR <<
"Could not import key:" <<
str::Format(
"gpg-pubkey-%s") % key <<
" into zypp keyring (V3 key?)" << endl;
657 missingKeys.insert( key );
659 if ( ! missingKeys.empty() )
665 ERR <<
"Could not import keys into zypp keyring: " << endl;
673 MIL <<
"Importing zypp trusted keyring" << std::endl;
674 for_( it, zyppKeys.begin(), zyppKeys.end() )
678 importPubkey( getZYpp()->keyRing()->exportTrustedPublicKey( *it ) );
686 MIL <<
"Trusted keys synced." << endl;
708 WAR <<
"Key " << pubkey_r <<
" can not be imported. (READONLY MODE)" << endl;
715 bool hasOldkeys =
false;
717 for_( it, rpmKeys.begin(), rpmKeys.end() )
726 MIL <<
"Key " << pubkey_r <<
" is already in the rpm trusted keyring. (skip import)" << endl;
730 if ( keyEd.
version() != (*it).version() )
733 if ( keyEd.
release() < (*it).release() )
735 MIL <<
"Key " << pubkey_r <<
" is older than one in the rpm trusted keyring. (skip import)" << endl;
743 MIL <<
"Key " << pubkey_r <<
" will be imported into the rpm trusted keyring." << (hasOldkeys?
"(update)":
"(new)") << endl;
749 std::string keyName(
"gpg-pubkey-" + keyEd.
version() );
751 opts.push_back (
"-e" );
752 opts.push_back (
"--allmatches" );
753 opts.push_back (
"--" );
754 opts.push_back ( keyName.c_str() );
765 ERR <<
"Failed to remove key " << pubkey_r <<
" from RPM trusted keyring (ignored)" << endl;
769 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
775 opts.push_back (
"--import" );
776 opts.push_back (
"--" );
778 opts.push_back ( pubkeypath.c_str() );
782 std::vector<std::string> excplines;
788 excplines.push_back( std::move(line) );
804 MIL <<
"Key " << pubkey_r <<
" imported in rpm trusted keyring." << endl;
821 std::set<Edition>::const_iterator found_edition = rpm_keys.end();
824 for_( it, rpm_keys.begin(), rpm_keys.end() )
826 if ( (*it).version() == pubkeyVersion )
834 if (found_edition == rpm_keys.end())
836 WAR <<
"Key " << pubkey_r.
id() <<
" is not in rpm db" << endl;
840 std::string rpm_name(
"gpg-pubkey-" + found_edition->asString());
843 opts.push_back (
"-e" );
844 opts.push_back (
"--" );
845 opts.push_back ( rpm_name.c_str() );
849 std::vector<std::string> excplines;
855 excplines.push_back( std::move(line) );
871 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
883 std::list<PublicKey> ret;
886 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
888 Edition edition = it->tag_edition();
893 getData(
"gpg-pubkey", edition, result );
894 TmpFile file(getZYpp()->tmpPath());
900 os << result->tag_description();
909 catch ( std::exception & e )
911 ERR <<
"Could not dump key " << edition.
asString() <<
" in tmp file " << file.
path() << endl;
921 std::set<Edition> ret;
924 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
926 Edition edition = it->tag_edition();
928 ret.insert( edition );
945 std::list<FileInfo> result;
972bool RpmDb::hasFile(
const std::string & file_r,
const std::string & name_r )
const
982 res = (it->tag_name() == name_r);
1003 return it->tag_name();
1117 struct RpmlogCapture :
public std::vector<std::string>
1121 rpmlogSetCallback( rpmLogCB,
this );
1122 _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
1127 rpmlogSetCallback(
nullptr,
nullptr );
1128 rpmlogSetMask( _oldMask );
1131 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1132 {
return reinterpret_cast<RpmlogCapture*
>(data_r)->rpmLog( rec_r ); }
1134 int rpmLog( rpmlogRec rec_r )
1136 std::string l { ::rpmlogRecMessage( rec_r ) };
1138 push_back( std::move(l) );
1146 std::ostream &
operator<<( std::ostream &
str,
const RpmlogCapture & obj )
1149 for (
const auto & l : obj ) {
1150 if ( sep )
str << sep;
else sep =
'\n';
1159 bool requireGPGSig_r,
1160 RpmDb::CheckPackageDetail & detail_r )
1163 if ( ! file.isFile() )
1165 ERR <<
"Not a file: " << file << endl;
1169 FD_t fd = ::Fopen( file.asString().c_str(),
"r.ufdio" );
1170 if ( fd == 0 || ::Ferror(fd) )
1172 ERR <<
"Can't open file for reading: " << file <<
" (" << ::Fstrerror(fd) <<
")" << endl;
1177 rpmts ts = ::rpmtsCreate();
1178 ::rpmtsSetRootDir( ts, root_r.
c_str() );
1179 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1180#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP
1181 ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
1184 RpmlogCapture vresult;
1186 static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0,
sizeof(rpmQVKArguments_s) );
return qva; })();
1187 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
1196 typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
1197 static const ResultMap resultMap {
1205 auto getresult = [](
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1206 auto it = resultMap.find( key );
1211 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1216 SawHeaderSig = (1 << 0),
1217 SawHeaderDigest = (1 << 1),
1218 SawPayloadDigest = (1 << 2),
1220 SawDigest = (1 << 4),
1222 unsigned saw = SawNone;
1224 static const str::regex rx(
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1226 for (
const std::string & line : vresult )
1228 if ( line[0] !=
' ' )
1234 lineres = getresult( resultMap, what[3] );
1238 if ( what[1][0] ==
'H' ) {
1239 saw |= ( what[2][0] ==
'S' ? SawHeaderSig :SawHeaderDigest );
1241 else if ( what[1][0] ==
'P' ) {
1242 if ( what[2][0] ==
'd' ) saw |= SawPayloadDigest;
1245 saw |= ( what[2][0] ==
'S' ? SawSig : SawDigest );
1250 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, std::move(line) ) );
1272 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1273 if ( not isSigned ) {
1274 std::string message {
" " };
1275 if ( not (saw & SawHeaderSig) )
1276 message +=
_(
"Package header is not signed!");
1278 message +=
_(
"Package payload is not signed!");
1280 detail_r.push_back( RpmDb::CheckPackageDetail::value_type(
RpmDb::CHK_NOSIG, std::move(message) ) );
1281 if ( requireGPGSig_r )
1290 bool didReadHeader =
false;
1291 std::unordered_map< std::string, std::string> fprs;
1294 str::regex rxexpr(
"key ID ([a-fA-F0-9]{8}):" );
1295 for (
auto &detail : detail_r ) {
1296 auto &line = detail.second;
1300 if ( !didReadHeader ) {
1301 didReadHeader =
true;
1307 const auto &addFprs = [&](
auto tag ){
1308 const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
1309 for (
const auto &
id : list1 ) {
1310 if (
id.size() <= 8 )
1314 fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
1318 addFprs( RPMTAG_SIGGPG );
1319 addFprs( RPMTAG_SIGPGP );
1320 addFprs( RPMTAG_RSAHEADER );
1321 addFprs( RPMTAG_DSAHEADER );
1324 ERR <<
"Failed to read package signatures." << std::endl;
1335 if (
const auto &i = fprs.find( keyId ); i != fprs.end() ) {
1342 WAR << path_r <<
" (" << requireGPGSig_r <<
" -> " << ret <<
")" << endl;
1343 WAR << vresult << endl;
1346 DBG << path_r <<
" [0-Signature is OK]" << endl;
1357{
return doCheckPackageSig( path_r,
root(),
false, detail_r ); }
1363{
return doCheckPackageSig( path_r,
root(),
true, detail_r ); }
1378 opts.push_back (
"-V");
1379 opts.push_back (
"--nodeps");
1380 opts.push_back (
"--noscripts");
1381 opts.push_back (
"--nomd5");
1382 opts.push_back (
"--");
1383 opts.push_back (packageName.c_str());
1404 if (line.length() > 12 &&
1405 (line[0] ==
'S' || line[0] ==
's' ||
1406 (line[0] ==
'.' && line[7] ==
'T')))
1409 std::string filename;
1411 filename.assign(line, 11, line.length() - 11);
1451#if defined(WORKAROUNDRPMPWDBUG)
1452 args.push_back(
"#/");
1454 args.push_back(
"rpm");
1455 args.push_back(
"--root");
1457 args.push_back(
"--dbpath");
1460 args.push_back(
"-vv");
1461 const char* argv[args.size() + opts.size() + 1];
1463 const char** p = argv;
1464 p =
copy (args.begin (), args.end (), p);
1465 p =
copy (opts.begin (), opts.end (), p);
1495 const auto &readResult =
io::receiveUpto( inputfile,
'\n', 5 * 1000,
false );
1496 switch ( readResult.first ) {
1502 line += readResult.second;
1507 line += readResult.second;
1508 if ( line.size() && line.back() ==
'\n')
1513 line += readResult.second;
1515 if ( line.size() && line.back() ==
'\n')
1519 L_DBG(
"RPM_DEBUG") << line << endl;
1563void RpmDb::processConfigFiles(
const std::string& line,
const std::string& name,
const char* typemsg,
const char* difffailmsg,
const char* diffgenmsg)
1565 std::string msg = line.substr(9);
1566 std::string::size_type pos1 = std::string::npos;
1567 std::string::size_type pos2 = std::string::npos;
1568 std::string file1s, file2s;
1572 pos1 = msg.find (typemsg);
1575 if ( pos1 == std::string::npos )
1578 pos2 = pos1 + strlen (typemsg);
1580 if (pos2 >= msg.length() )
1583 file1 = msg.substr (0, pos1);
1584 file2 = msg.substr (pos2);
1591 file1 =
_root + file1;
1592 file2 =
_root + file2;
1602 ERR <<
"Could not create " << file.
asString() << endl;
1606 std::ofstream notify(file.
asString().c_str(), std::ios::out|std::ios::app);
1609 ERR <<
"Could not open " << file << endl;
1615 notify <<
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
1618 ERR <<
"diff failed" << endl;
1620 file1s.c_str(), file2s.c_str()) << endl;
1625 file1s.c_str(), file2s.c_str()) << endl;
1630 if (out.substr(0,4) ==
"--- ")
1632 out.replace(4, file1.
asString().length(), file1s);
1634 std::string::size_type pos = out.find(
"\n+++ ");
1635 if (pos != std::string::npos)
1637 out.replace(pos+5, file2.
asString().length(), file2s);
1640 notify << out << endl;
1643 notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1648 WAR <<
"rpm created " << file2 <<
" but it is not different from " << file2 << endl;
1668 report->start(filename);
1683 report->finish( excpt_r );
1699 MIL <<
"RpmDb::installPackage(" << filename <<
"," << flags <<
")" << endl;
1707 ERR <<
"backup of " << filename.
asString() <<
" failed" << endl;
1710 report->progress( 0 );
1715#if defined(WORKAROUNDDUMPPOSTTRANSBUG)
1716 if ( postTransCollector_r &&
_root ==
"/" ) {
1718 if ( postTransCollector_r ) {
1720 opts.push_back(
"--define");
1721 opts.push_back(
"_dump_posttrans 1");
1724 opts.push_back(
"-i");
1726 opts.push_back(
"-U");
1728 opts.push_back(
"--percent");
1729 opts.push_back(
"--noglob");
1733 opts.push_back(
"--ignorearch");
1736 opts.push_back(
"--nodigest");
1738 opts.push_back(
"--nosignature");
1740 opts.push_back (
"--excludedocs");
1742 opts.push_back (
"--noscripts");
1744 opts.push_back (
"--force");
1746 opts.push_back (
"--nodeps");
1748 opts.push_back (
"--ignoresize");
1750 opts.push_back (
"--justdb");
1752 opts.push_back (
"--test");
1754 opts.push_back (
"--noposttrans");
1756 opts.push_back(
"--");
1759 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
1760 opts.push_back ( quotedFilename.c_str() );
1765 unsigned lineno = 0;
1768 cmdout.
set(
"line", std::cref(line) );
1769 cmdout.
set(
"lineno", lineno );
1773 std::vector<std::string> configwarnings;
1781 sscanf( line.c_str() + 2,
"%d", &percent );
1782 report->progress( percent );
1790 cmdout.
set(
"lineno", lineno );
1791 report->report( cmdout );
1794 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1798 rpmmsg += line+
'\n';
1801 configwarnings.push_back(line);
1804 rpmmsg +=
"[truncated]\n";
1807 if ( postTransCollector_r && rpm_status == 0 ) {
1813 for (std::vector<std::string>::iterator it = configwarnings.begin();
1814 it != configwarnings.end(); ++it)
1818 _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
1820 _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
1823 _(
"rpm created %s as %s, but it was impossible to determine the difference"),
1825 _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
1828 if ( rpm_status != 0 )
1833 std::ostringstream sstr;
1834 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1835 historylog.
comment(sstr.str());
1838 if ( not rpmmsg.empty() )
1842 else if ( ! rpmmsg.empty() )
1847 std::ostringstream sstr;
1848 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1849 historylog.
comment(sstr.str());
1853 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
1870 +
"-" + package->edition().version()
1871 +
"-" + package->edition().release()
1872 +
"." + package->arch().asString(), flags, postTransCollector_r );
1879 report->start( name_r );
1894 report->finish( excpt_r );
1910 MIL <<
"RpmDb::doRemovePackage(" << name_r <<
"," << flags <<
")" << endl;
1919 ERR <<
"backup of " << name_r <<
" failed" << endl;
1921 report->progress( 0 );
1925 report->progress( 100 );
1930#if defined(WORKAROUNDDUMPPOSTTRANSBUG)
1931 if ( postTransCollector_r &&
_root ==
"/" ) {
1933 if ( postTransCollector_r ) {
1935 opts.push_back(
"--define");
1936 opts.push_back(
"_dump_posttrans 1");
1938 opts.push_back(
"-e");
1939 opts.push_back(
"--allmatches");
1942 opts.push_back(
"--noscripts");
1944 opts.push_back(
"--nodeps");
1946 opts.push_back(
"--justdb");
1948 opts.push_back (
"--test");
1951 WAR <<
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
1954 opts.push_back(
"--");
1955 opts.push_back(name_r.c_str());
1960 unsigned lineno = 0;
1963 cmdout.
set(
"line", std::cref(line) );
1964 cmdout.
set(
"lineno", lineno );
1975 report->progress( 5 );
1983 cmdout.
set(
"lineno", lineno );
1984 report->report( cmdout );
1987 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1990 rpmmsg += line+
'\n';
1993 rpmmsg +=
"[truncated]\n";
1994 report->progress( 50 );
1996 if ( postTransCollector_r && rpm_status == 0 ) {
2002 if ( rpm_status != 0 )
2005 str::form(
"%s remove failed", name_r.c_str()),
true );
2006 std::ostringstream sstr;
2007 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2008 historylog.
comment(sstr.str());
2011 if ( not rpmmsg.empty() )
2015 else if ( ! rpmmsg.empty() )
2018 str::form(
"%s removed ok", name_r.c_str()),
true );
2020 std::ostringstream sstr;
2021 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
2022 historylog.
comment(sstr.str());
2026 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2039 MIL <<
"RpmDb::runposttrans(" << filename_r <<
")" << endl;
2042 opts.push_back(
"-vv");
2043 opts.push_back(
"--runposttrans");
2044 opts.push_back(filename_r.
c_str());
2051 static const str::regex rx(
"^D: (%.*): scriptlet start$" );
2063 output_r(
"RIPOFF:"+what[1] );
2080 if ( rpm_status != 0 ) {
2081 WAR <<
"rpm --runposttrans returned " << rpm_status << endl;
2116 INT <<
"_backuppath empty" << endl;
2124 ERR <<
"Error while getting changed files for package " <<
2125 packageName << endl;
2131 DBG <<
"package " << packageName <<
" not changed -> no backup" << endl;
2142 time_t currentTime = time(0);
2143 struct tm *currentLocalTime = localtime(¤tTime);
2145 int date = (currentLocalTime->tm_year + 1900) * 10000
2146 + (currentLocalTime->tm_mon + 1) * 100
2147 + currentLocalTime->tm_mday;
2153 +
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2156 while (
PathInfo(backupFilename).isExist() && num++ < 1000);
2161 ERR << filestobackupfile.
asString() <<
" already exists and is no file" << endl;
2165 std::ofstream fp ( filestobackupfile.
asString().c_str(), std::ios::out|std::ios::trunc );
2169 ERR <<
"could not open " << filestobackupfile.
asString() << endl;
2173 for (FileList::const_iterator cit =
fileList.begin();
2176 std::string name = *cit;
2177 if ( name[0] ==
'/' )
2180 name = name.substr( 1 );
2182 DBG <<
"saving file "<< name << endl;
2187 const char*
const argv[] =
2193 "--ignore-failed-read",
2197 filestobackupfile.
asString().c_str(),
2213 int ret = tar.
close();
2217 ERR <<
"tar failed: " << tarmsg << endl;
2222 MIL <<
"tar backup ok" << endl;
2243#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2255 OUTS(
CHK_ERROR,
_(
"File does not exist or signature can't be checked") );
2265 for (
const auto & el : obj )
2266 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 ...
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.
int close()
Wait for the progamm to complete.
Stderr_Disposition
Define symbols for different policies on the handling of stderr.
Writing the zypp history file.
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
std::string asString() const
static KeyManagerCtx createForOpenPGP()
Creates a new KeyManagerCtx for PGP using a volatile temp.
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.
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.
virtual std::ostream & dumpOn(std::ostream &str) const
Dump debug info.
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
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.
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.
int runposttrans(const Pathname &filename_r, std::function< void(const std::string &)> output_r)
Run collected posttrans and transfiletrigger(postun|in) if rpm --runposttrans is supported.
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.
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
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.
std::vector< const char * > RpmArgVec
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)
std::set< std::string > FileList
bool systemReadLine(std::string &line)
Read a line from the general rpm query.
void rebuildDatabase()
Rebuild the rpm database (rpm –rebuilddb).
bool hasFile(const std::string &file_r, const std::string &name_r="") const
Return true if at least one package owns a certain file (name_r empty) Return true if package name_r ...
Just inherits Exception to separate media exceptions.
Subclass to retrieve database content.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
bool findByFile(const std::string &file_r)
Reset to iterate all packages that own a certain file.
bool findByRequiredBy(const std::string &tag_r)
Reset to iterate all packages that require a certain tag.
bool findPackage(const std::string &name_r)
Find package by name.
shared_ptr< RpmException > dbError() const
Return any database error.
bool findByConflicts(const std::string &tag_r)
Reset to iterate all packages that conflict with a certain tag.
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
static std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
static unsigned dbRelease(bool force_r=false)
If there are no outstanding references to the database (e.g.
static void dbAccess()
Access the database at the current default location.
static unsigned blockAccess()
Blocks further access to rpmdb.
static Pathname suggestedDbPath(const Pathname &root_r)
static void unblockAccess()
Allow access to rpmdb e.g.
String related utilities and Regular expression matching.
Types and functions for filesystem operations.
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'.
int copy(const Pathname &file, const Pathname &dest)
Like 'cp file dest'.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
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.
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.
std::string toLower(const std::string &s)
Return lowercase version of s.
std::ostream & operator<<(std::ostream &str, const librpmDb::db_const_iterator &obj)
static shared_ptr< KeyRingSignalReceiver > sKeyRingReceiver
std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
unsigned diffFiles(const std::string file1, const std::string file2, std::string &out, int maxlines)
Easy-to use interface to the ZYPP dependency resolver.
Temporarily connect a ReceiveReport then restore the previous one.
static const UserData::ContentType contentRpmout
"rpmout/installpkg": Additional rpm output (sent immediately).
virtual void trustedKeyRemoved(const PublicKey &key)
virtual void trustedKeyAdded(const PublicKey &key)
KeyRingSignalReceiver(RpmDb &rpmdb)
static const UserData::ContentType contentRpmout
"rpmout/removepkg": Additional rpm output (sent immediately).
Detailed rpm signature check log messages A single multiline message if CHK_OK.
#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.