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");
103const char* quoteInFilename_m =
"\'\"";
105const char* quoteInFilename_m =
" \t\'\"";
107inline std::string rpmQuoteFilename(
const Pathname & path_r )
109 std::string path( path_r.
asString() );
110 for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m );
111 pos != std::string::npos;
112 pos = path.find_first_of( quoteInFilename_m, pos ) )
114 path.insert( pos,
"\\" );
127#if defined(WORKAROUNDRPMPWDBUG)
134 WAR <<
"Can't get cwd!" << endl;
156 MIL <<
"trusted key added to zypp Keyring. Importing..." << endl;
162 MIL <<
"Trusted key removed from zypp Keyring. Removing..." << endl;
171unsigned diffFiles(
const std::string& file1,
const std::string& file2, std::string& out,
int maxlines)
192 if (maxlines<0?
true:count<maxlines)
218#define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); }
229 : _backuppath (
"/var/adm/backup")
230 , _packagebackups(false)
237 setenv(
"RPM_IgnoreFailedSymlinks",
"1", 1 );
249 MIL <<
"~RpmDb()" << endl;
252 MIL <<
"~RpmDb() end" << endl;
278 bool quickinit( root_r.
empty() );
280 if ( root_r.
empty() )
288 if ( dbPath_r !=
"/var/lib/rpm" && !
PathInfo( root_r/
"/var/lib/rpm" ).isExist() )
290 WAR <<
"Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
304 if ( root_r ==
_root ) {
312 MIL <<
"Calling initDatabase: " <<
stringPath( root_r, dbPath_r )
313 << ( doRebuild_r ?
" (rebuilddb)" :
"" )
314 << ( quickinit ?
" (quickinit)" :
"" ) << endl;
323 MIL <<
"QUICK initDatabase (no systemRoot set)" << endl;
345 MIL <<
"Synchronizing keys with zypp keyring" << endl;
354 MIL <<
"InitDatabase: " << *
this << endl;
370 MIL <<
"Calling closeDatabase: " << *
this << endl;
382 MIL <<
"closeDatabase: " << *
this << endl;
412 MIL <<
"RpmDb::rebuildDatabase" << *
this << endl;
426 opts.push_back(
"--rebuilddb");
427 opts.push_back(
"-vv");
437 tics.
range( hdrTotal );
440 return report->progress( tics_r.
reportValue(), mydbpath );
448 static const std::string debugPrefix {
"D:" };
449 static const std::string progressPrefix {
"D: read h#" };
450 static const std::string ignoreSuffix {
"digest: OK" };
465 WAR <<
"User requested abort." << endl;
489 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
500 void updateIf(
const Edition & rpmKey_r )
502 std::string keyRelease( rpmKey_r.
release() );
503 int comp = _release.compare( keyRelease );
507 _release.swap( keyRelease );
508 _inRpmKeys = &rpmKey_r;
509 _inZyppKeys =
nullptr;
510 if ( !keyRelease.empty() )
511 DBG <<
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
513 else if ( comp == 0 )
517 _inRpmKeys = &rpmKey_r;
521 DBG <<
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
527 int comp = _release.compare( keyRelease );
531 _release.swap( keyRelease );
532 _inRpmKeys =
nullptr;
533 _inZyppKeys = &zyppKey_r;
534 if ( !keyRelease.empty() )
535 DBG <<
"Old key in R: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
537 else if ( comp == 0 )
541 _inZyppKeys = &zyppKey_r;
545 DBG <<
"Old key in Z: gpg-pubkey-" << zyppKey_r.
gpgPubkeyVersion() <<
"-" << keyRelease << endl;
548 std::string _release;
549 const Edition * _inRpmKeys;
555 std::map<std::string,Key> _keymap;
557 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
559 _keymap[(*it).version()].updateIf( *it );
562 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
564 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
568 std::set<Edition> rpmKeys;
569 std::list<PublicKeyData> zyppKeys;
570 for_( it, _keymap.begin(), _keymap.end() )
572 DBG <<
"gpg-pubkey-" << (*it).first <<
"-" << (*it).second._release <<
" "
573 << ( (*it).second._inRpmKeys ?
"R" :
"_" )
574 << ( (*it).second._inZyppKeys ?
"Z" :
"_" ) << endl;
575 if ( ! (*it).second._inRpmKeys )
577 zyppKeys.push_back( *(*it).second._inZyppKeys );
579 if ( ! (*it).second._inZyppKeys )
581 rpmKeys.insert( *(*it).second._inRpmKeys );
584 rpmKeys_r.swap( rpmKeys );
585 zyppKeys_r.swap( zyppKeys );
592 MIL <<
"Going to sync trusted keys..." << endl;
594 std::list<PublicKeyData> zyppKeys( getZYpp()->keyRing()->trustedPublicKeyData() );
606 MIL <<
"Removing excess keys in zypp trusted keyring" << std::endl;
612 if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) )
614 DBG <<
"Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl;
615 getZYpp()->keyRing()->deleteKey( keyData.id(),
true );
616 if ( !dirty ) dirty =
true;
620 zyppKeys = getZYpp()->keyRing()->trustedPublicKeyData();
623 computeKeyRingSync( rpmKeys, zyppKeys );
624 MIL << (mode_r &
SYNC_TO_KEYRING ?
"" :
"(skip) ") <<
"Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
625 MIL << (mode_r &
SYNC_FROM_KEYRING ?
"" :
"(skip) ") <<
"Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
631 MIL <<
"Exporting rpm keyring into zypp trusted keyring" <<endl;
636 TmpFile tmpfile( getZYpp()->tmpPath() );
638 std::ofstream tmpos( tmpfile.
path().
c_str() );
639 for_( it, rpmKeys.begin(), rpmKeys.end() )
643 getData(
"gpg-pubkey", *it, result );
644 tmpos << result->tag_description() << endl;
649 getZYpp()->keyRing()->multiKeyImport( tmpfile.
path(),
true );
653 std::set<Edition> missingKeys;
654 for (
const Edition & key : rpmKeys )
656 if ( getZYpp()->keyRing()->isKeyTrusted( key.version() ) )
658 ERR <<
"Could not import key:" <<
str::Format(
"gpg-pubkey-%s") % key <<
" into zypp keyring (V3 key?)" << endl;
659 missingKeys.insert( key );
661 if ( ! missingKeys.empty() )
667 ERR <<
"Could not import keys into zypp keyring: " << endl;
675 MIL <<
"Importing zypp trusted keyring" << std::endl;
676 for_( it, zyppKeys.begin(), zyppKeys.end() )
680 importPubkey( getZYpp()->keyRing()->exportTrustedPublicKey( *it ) );
688 MIL <<
"Trusted keys synced." << endl;
710 WAR <<
"Key " << pubkey_r <<
" can not be imported. (READONLY MODE)" << endl;
717 bool hasOldkeys =
false;
719 for_( it, rpmKeys.begin(), rpmKeys.end() )
728 MIL <<
"Key " << pubkey_r <<
" is already in the rpm trusted keyring. (skip import)" << endl;
732 if ( keyEd.
version() != (*it).version() )
735 if ( keyEd.
release() < (*it).release() )
737 MIL <<
"Key " << pubkey_r <<
" is older than one in the rpm trusted keyring. (skip import)" << endl;
745 MIL <<
"Key " << pubkey_r <<
" will be imported into the rpm trusted keyring." << (hasOldkeys?
"(update)":
"(new)") << endl;
751 std::string keyName(
"gpg-pubkey-" + keyEd.
version() );
753 opts.push_back (
"-e" );
754 opts.push_back (
"--allmatches" );
755 opts.push_back (
"--" );
756 opts.push_back ( keyName.c_str() );
767 ERR <<
"Failed to remove key " << pubkey_r <<
" from RPM trusted keyring (ignored)" << endl;
771 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
777 opts.push_back (
"--import" );
778 opts.push_back (
"--" );
780 opts.push_back ( pubkeypath.c_str() );
784 std::vector<std::string> excplines;
790 excplines.push_back( std::move(line) );
806 MIL <<
"Key " << pubkey_r <<
" imported in rpm trusted keyring." << endl;
823 std::set<Edition>::const_iterator found_edition = rpm_keys.end();
826 for_( it, rpm_keys.begin(), rpm_keys.end() )
828 if ( (*it).version() == pubkeyVersion )
836 if (found_edition == rpm_keys.end())
838 WAR <<
"Key " << pubkey_r.
id() <<
" is not in rpm db" << endl;
842 std::string rpm_name(
"gpg-pubkey-" + found_edition->asString());
845 opts.push_back (
"-e" );
846 opts.push_back (
"--" );
847 opts.push_back ( rpm_name.c_str() );
851 std::vector<std::string> excplines;
857 excplines.push_back( std::move(line) );
873 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
885 std::list<PublicKey> ret;
888 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
890 Edition edition = it->tag_edition();
895 getData(
"gpg-pubkey", edition, result );
896 TmpFile file(getZYpp()->tmpPath());
902 os << result->tag_description();
911 catch ( std::exception & e )
913 ERR <<
"Could not dump key " << edition.
asString() <<
" in tmp file " << file.
path() << endl;
923 std::set<Edition> ret;
926 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
928 Edition edition = it->tag_edition();
930 ret.insert( edition );
947 std::list<FileInfo> result;
974bool RpmDb::hasFile(
const std::string & file_r,
const std::string & name_r )
const
984 res = (it->tag_name() == name_r);
1005 return it->tag_name();
1119 struct RpmlogCapture :
public std::vector<std::string>
1123 rpmlogSetCallback( rpmLogCB,
this );
1124 _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
1127 RpmlogCapture(
const RpmlogCapture &) =
delete;
1128 RpmlogCapture(RpmlogCapture &&) =
delete;
1129 RpmlogCapture &operator=(
const RpmlogCapture &) =
delete;
1130 RpmlogCapture &operator=(RpmlogCapture &&) =
delete;
1133 rpmlogSetCallback(
nullptr,
nullptr );
1134 rpmlogSetMask( _oldMask );
1137 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1138 {
return reinterpret_cast<RpmlogCapture*
>(data_r)->rpmLog( rec_r ); }
1140 int rpmLog( rpmlogRec rec_r )
1142 std::string l { ::rpmlogRecMessage( rec_r ) };
1144 push_back( std::move(l) );
1152 std::ostream &
operator<<( std::ostream &
str,
const RpmlogCapture & obj )
1155 for (
const auto & l : obj ) {
1156 if ( sep )
str << sep;
else sep =
'\n';
1165 bool requireGPGSig_r,
1166 RpmDb::CheckPackageDetail & detail_r )
1169 if ( ! file.isFile() )
1171 ERR <<
"Not a file: " << file << endl;
1175 FD_t fd = ::Fopen( file.asString().c_str(),
"r.ufdio" );
1176 if ( fd == 0 || ::Ferror(fd) )
1178 ERR <<
"Can't open file for reading: " << file <<
" (" << ::Fstrerror(fd) <<
")" << endl;
1183 rpmts ts = ::rpmtsCreate();
1184 ::rpmtsSetRootDir( ts, root_r.
c_str() );
1185 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1186#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP
1187 ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
1190 RpmlogCapture vresult;
1192 static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0,
sizeof(rpmQVKArguments_s) );
return qva; })();
1193 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
1202 typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
1203 static const ResultMap resultMap {
1211 auto getresult = [](
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1212 auto it = resultMap.find( key );
1217 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1222 SawHeaderSig = (1 << 0),
1223 SawHeaderDigest = (1 << 1),
1224 SawPayloadDigest = (1 << 2),
1226 SawDigest = (1 << 4),
1228 unsigned saw = SawNone;
1230 static const str::regex rx(
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1232 for (
const std::string & line : vresult )
1234 if ( line[0] !=
' ' )
1240 lineres = getresult( resultMap, what[3] );
1244 if ( what[1][0] ==
'H' ) {
1245 saw |= ( what[2][0] ==
'S' ? SawHeaderSig :SawHeaderDigest );
1247 else if ( what[1][0] ==
'P' ) {
1248 if ( what[2][0] ==
'd' ) saw |= SawPayloadDigest;
1251 saw |= ( what[2][0] ==
'S' ? SawSig : SawDigest );
1256 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, line ) );
1278 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1279 if ( not isSigned ) {
1280 std::string message {
" " };
1281 if ( not (saw & SawHeaderSig) )
1282 message +=
_(
"Package header is not signed!");
1284 message +=
_(
"Package payload is not signed!");
1286 detail_r.push_back( RpmDb::CheckPackageDetail::value_type(
RpmDb::CHK_NOSIG, std::move(message) ) );
1287 if ( requireGPGSig_r )
1296 bool didReadHeader =
false;
1297 std::unordered_map< std::string, std::string> fprs;
1300 str::regex rxexpr(
"key ID ([a-fA-F0-9]{8}):" );
1301 for (
auto &detail : detail_r ) {
1302 auto &line = detail.second;
1306 if ( !didReadHeader ) {
1307 didReadHeader =
true;
1313 const auto &addFprs = [&](
auto tag ){
1314 const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
1315 for (
const auto &
id : list1 ) {
1316 if (
id.size() <= 8 )
1320 fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
1324 addFprs( RPMTAG_SIGGPG );
1325 addFprs( RPMTAG_SIGPGP );
1326 addFprs( RPMTAG_RSAHEADER );
1327 addFprs( RPMTAG_DSAHEADER );
1330 ERR <<
"Failed to read package signatures." << std::endl;
1341 if (
const auto &i = fprs.find( keyId ); i != fprs.end() ) {
1348 WAR << path_r <<
" (" << requireGPGSig_r <<
" -> " << ret <<
")" << endl;
1349 WAR << vresult << endl;
1352 DBG << path_r <<
" [0-Signature is OK]" << endl;
1363{
return doCheckPackageSig( path_r,
root(),
false, detail_r ); }
1369{
return doCheckPackageSig( path_r,
root(),
true, detail_r ); }
1384 opts.push_back (
"-V");
1385 opts.push_back (
"--nodeps");
1386 opts.push_back (
"--noscripts");
1387 opts.push_back (
"--nomd5");
1388 opts.push_back (
"--");
1389 opts.push_back (packageName.c_str());
1410 if (line.length() > 12 &&
1411 (line[0] ==
'S' || line[0] ==
's' ||
1412 (line[0] ==
'.' && line[7] ==
'T')))
1415 std::string filename;
1417 filename.assign(line, 11, line.length() - 11);
1457#if defined(WORKAROUNDRPMPWDBUG)
1458 args.push_back(
"#/");
1460 args.push_back(
"rpm");
1461 args.push_back(
"--root");
1463 args.push_back(
"--dbpath");
1466 args.push_back(
"-vv");
1467 const char* argv[args.size() + opts.size() + 1];
1469 const char** p = argv;
1470 p =
copy (args.begin (), args.end (), p);
1471 p =
copy (opts.begin (), opts.end (), p);
1501 const auto &readResult =
io::receiveUpto( inputfile,
'\n', 5 * 1000,
false );
1502 switch ( readResult.first ) {
1508 line += readResult.second;
1513 line += readResult.second;
1514 if ( line.size() && line.back() ==
'\n')
1519 line += readResult.second;
1521 if ( line.size() && line.back() ==
'\n')
1525 L_DBG(
"RPM_DEBUG") << line << endl;
1569void RpmDb::processConfigFiles(
const std::string& line,
const std::string& name,
const char* typemsg,
const char* difffailmsg,
const char* diffgenmsg)
1571 std::string msg = line.substr(9);
1572 std::string::size_type pos1 = std::string::npos;
1573 std::string::size_type pos2 = std::string::npos;
1574 std::string file1s, file2s;
1578 pos1 = msg.find (typemsg);
1581 if ( pos1 == std::string::npos )
1584 pos2 = pos1 + strlen (typemsg);
1586 if (pos2 >= msg.length() )
1589 file1 = msg.substr (0, pos1);
1590 file2 = msg.substr (pos2);
1597 file1 =
_root + file1;
1598 file2 =
_root + file2;
1608 ERR <<
"Could not create " << file.
asString() << endl;
1612 std::ofstream notify(file.
asString().c_str(), std::ios::out|std::ios::app);
1615 ERR <<
"Could not open " << file << endl;
1621 notify <<
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
1624 ERR <<
"diff failed" << endl;
1626 file1s.c_str(), file2s.c_str()) << endl;
1631 file1s.c_str(), file2s.c_str()) << endl;
1636 if (out.substr(0,4) ==
"--- ")
1638 out.replace(4, file1.
asString().length(), file1s);
1640 std::string::size_type pos = out.find(
"\n+++ ");
1641 if (pos != std::string::npos)
1643 out.replace(pos+5, file2.
asString().length(), file2s);
1646 notify << out << endl;
1649 notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1654 WAR <<
"rpm created " << file2 <<
" but it is not different from " << file2 << endl;
1674 report->start(filename);
1689 report->finish( excpt_r );
1705 MIL <<
"RpmDb::installPackage(" << filename <<
"," << flags <<
")" << endl;
1713 ERR <<
"backup of " << filename.
asString() <<
" failed" << endl;
1716 report->progress( 0 );
1721#if defined(WORKAROUNDDUMPPOSTTRANSBUG)
1722 if ( postTransCollector_r &&
_root ==
"/" ) {
1724 if ( postTransCollector_r ) {
1726 opts.push_back(
"--define");
1727 opts.push_back(
"_dump_posttrans 1");
1730 opts.push_back(
"-i");
1732 opts.push_back(
"-U");
1734 opts.push_back(
"--percent");
1735 opts.push_back(
"--noglob");
1739 opts.push_back(
"--ignorearch");
1742 opts.push_back(
"--nodigest");
1744 opts.push_back(
"--nosignature");
1746 opts.push_back (
"--excludedocs");
1748 opts.push_back (
"--noscripts");
1750 opts.push_back (
"--force");
1752 opts.push_back (
"--nodeps");
1754 opts.push_back (
"--ignoresize");
1756 opts.push_back (
"--justdb");
1758 opts.push_back (
"--test");
1760 opts.push_back (
"--noposttrans");
1762 opts.push_back(
"--");
1765 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
1766 opts.push_back ( quotedFilename.c_str() );
1771 unsigned lineno = 0;
1774 cmdout.
set(
"line", std::cref(line) );
1775 cmdout.
set(
"lineno", lineno );
1779 std::vector<std::string> configwarnings;
1787 sscanf( line.c_str() + 2,
"%d", &percent );
1788 report->progress( percent );
1796 cmdout.
set(
"lineno", lineno );
1797 report->report( cmdout );
1800 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1804 rpmmsg += line+
'\n';
1807 configwarnings.push_back(line);
1810 rpmmsg +=
"[truncated]\n";
1813 if ( postTransCollector_r && rpm_status == 0 ) {
1819 for (std::vector<std::string>::iterator it = configwarnings.begin();
1820 it != configwarnings.end(); ++it)
1824 _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
1826 _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
1829 _(
"rpm created %s as %s, but it was impossible to determine the difference"),
1831 _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
1834 if ( rpm_status != 0 )
1839 std::ostringstream sstr;
1840 sstr <<
"rpm output:" << endl << rpmmsg << endl;
1841 historylog.
comment(sstr.str());
1844 if ( not rpmmsg.empty() )
1848 else if ( ! rpmmsg.empty() )
1853 std::ostringstream sstr;
1854 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
1855 historylog.
comment(sstr.str());
1859 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
1876 +
"-" + package->edition().version()
1877 +
"-" + package->edition().release()
1878 +
"." + package->arch().asString(), flags, postTransCollector_r );
1885 report->start( name_r );
1900 report->finish( excpt_r );
1916 MIL <<
"RpmDb::doRemovePackage(" << name_r <<
"," << flags <<
")" << endl;
1925 ERR <<
"backup of " << name_r <<
" failed" << endl;
1927 report->progress( 0 );
1931 report->progress( 100 );
1936#if defined(WORKAROUNDDUMPPOSTTRANSBUG)
1937 if ( postTransCollector_r &&
_root ==
"/" ) {
1939 if ( postTransCollector_r ) {
1941 opts.push_back(
"--define");
1942 opts.push_back(
"_dump_posttrans 1");
1944 opts.push_back(
"-e");
1945 opts.push_back(
"--allmatches");
1948 opts.push_back(
"--noscripts");
1950 opts.push_back(
"--nodeps");
1952 opts.push_back(
"--justdb");
1954 opts.push_back (
"--test");
1957 WAR <<
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
1960 opts.push_back(
"--");
1961 opts.push_back(name_r.c_str());
1966 unsigned lineno = 0;
1969 cmdout.
set(
"line", std::cref(line) );
1970 cmdout.
set(
"lineno", lineno );
1981 report->progress( 5 );
1989 cmdout.
set(
"lineno", lineno );
1990 report->report( cmdout );
1993 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
1996 rpmmsg += line+
'\n';
1999 rpmmsg +=
"[truncated]\n";
2000 report->progress( 50 );
2002 if ( postTransCollector_r && rpm_status == 0 ) {
2008 if ( rpm_status != 0 )
2011 str::form(
"%s remove failed", name_r.c_str()),
true );
2012 std::ostringstream sstr;
2013 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2014 historylog.
comment(sstr.str());
2017 if ( not rpmmsg.empty() )
2021 else if ( ! rpmmsg.empty() )
2024 str::form(
"%s removed ok", name_r.c_str()),
true );
2026 std::ostringstream sstr;
2027 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
2028 historylog.
comment(sstr.str());
2032 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2045 MIL <<
"RpmDb::runposttrans(" << filename_r <<
")" << endl;
2048 opts.push_back(
"-vv");
2049 opts.push_back(
"--runposttrans");
2050 opts.push_back(filename_r.
c_str());
2057 static const str::regex rx(
"^D: (%.*): scriptlet start$" );
2069 output_r(
"RIPOFF:"+what[1] );
2086 if ( rpm_status != 0 ) {
2087 WAR <<
"rpm --runposttrans returned " << rpm_status << endl;
2122 INT <<
"_backuppath empty" << endl;
2130 ERR <<
"Error while getting changed files for package " <<
2131 packageName << endl;
2137 DBG <<
"package " << packageName <<
" not changed -> no backup" << endl;
2148 time_t currentTime = time(0);
2149 struct tm *currentLocalTime = localtime(¤tTime);
2151 int date = (currentLocalTime->tm_year + 1900) * 10000
2152 + (currentLocalTime->tm_mon + 1) * 100
2153 + currentLocalTime->tm_mday;
2159 +
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2162 while (
PathInfo(backupFilename).isExist() && num++ < 1000);
2167 ERR << filestobackupfile.
asString() <<
" already exists and is no file" << endl;
2171 std::ofstream fp ( filestobackupfile.
asString().c_str(), std::ios::out|std::ios::trunc );
2175 ERR <<
"could not open " << filestobackupfile.
asString() << endl;
2179 for (FileList::const_iterator cit =
fileList.begin();
2182 std::string name = *cit;
2183 if ( name[0] ==
'/' )
2186 name = name.substr( 1 );
2188 DBG <<
"saving file "<< name << endl;
2193 const char*
const argv[] =
2199 "--ignore-failed-read",
2203 filestobackupfile.
asString().c_str(),
2219 int ret = tar.
close();
2223 ERR <<
"tar failed: " << tarmsg << endl;
2228 MIL <<
"tar backup ok" << endl;
2249#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2261 OUTS(
CHK_ERROR,
_(
"File does not exist or signature can't be checked") );
2271 for (
const auto & el : obj )
2272 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.
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
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.
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 unsigned dbRelease(bool force_r=false) ZYPP_API
If there are no outstanding references to the database (e.g.
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
static std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
static unsigned blockAccess() ZYPP_API
Blocks further access to rpmdb.
static void unblockAccess() ZYPP_API
Allow access to rpmdb e.g.
static void dbAccess()
Access the database at the current default location.
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)
static shared_ptr< KeyRingSignalReceiver > sKeyRingReceiver
std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
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.
#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.