*
*/
#include "librpm.h"
-
+extern "C"
+{
+#include <rpm/rpmcli.h>
+#include <rpm/rpmlog.h>
+}
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <fstream>
+#include <sstream>
#include <list>
#include <map>
#include <set>
#include "zypp/base/Logger.h"
#include "zypp/base/String.h"
-#include "zypp/base/Regex.h"
+#include "zypp/base/Gettext.h"
#include "zypp/Date.h"
#include "zypp/Pathname.h"
#include "zypp/target/rpm/RpmDb.h"
#include "zypp/target/rpm/RpmCallbacks.h"
-#include "zypp/target/CommitLog.h"
+#include "zypp/HistoryLog.h"
#include "zypp/target/rpm/librpmDb.h"
#include "zypp/target/rpm/RpmException.h"
#include "zypp/TmpPath.h"
#include "zypp/KeyRing.h"
#include "zypp/ZYppFactory.h"
-
-#ifndef _
-#define _(X) X
-#endif
+#include "zypp/ZConfig.h"
using namespace std;
using namespace zypp::filesystem;
+#define WARNINGMAILPATH "/var/log/YaST2/"
+#define FILEFORBACKUPFILES "YaSTBackupModifiedFiles"
+#define MAXRPMMESSAGELINES 10000
+
+#define WORKAROUNDRPMPWDBUG
+
namespace zypp
{
+ namespace zypp_readonly_hack
+ {
+ bool IGotIt(); // in readonly-mode
+ }
namespace target
{
namespace rpm
{
namespace
{
-const char* quoteInFilename_m = " \t";
+#if 1 // No more need to escape whitespace since rpm-4.4.2.3
+const char* quoteInFilename_m = "\'\"";
+#else
+const char* quoteInFilename_m = " \t\'\"";
+#endif
inline string rpmQuoteFilename( const Pathname & path_r )
{
string path( path_r.asString() );
}
return path;
}
+
+
+ /** Workaround bnc#827609 - rpm needs a readable pwd so we
+ * chdir to /. Turn realtive pathnames into absolute ones
+ * by prepending cwd so rpm still finds them
+ */
+ inline Pathname workaroundRpmPwdBug( Pathname path_r )
+ {
+#if defined(WORKAROUNDRPMPWDBUG)
+ if ( path_r.relative() )
+ {
+ // try to prepend cwd
+ AutoDispose<char*> cwd( ::get_current_dir_name(), ::free );
+ if ( cwd )
+ return Pathname( cwd ) / path_r;
+ WAR << "Can't get cwd!" << endl;
+ }
+#endif
+ return path_r; // no problem with absolute pathnames
+ }
}
struct KeyRingSignalReceiver : callback::ReceiveReport<KeyRingSignals>
return str;
}
-///////////////////////////////////////////////////////////////////
-// CLASS NAME : RpmDbPtr
-// CLASS NAME : RpmDbconstPtr
-///////////////////////////////////////////////////////////////////
-
-#define WARNINGMAILPATH "/var/log/YaST2/"
-#define FILEFORBACKUPFILES "YaSTBackupModifiedFiles"
-
-///////////////////////////////////////////////////////////////////
-//
-// CLASS NAME : RpmDb::Packages
-/**
- * Helper class for RpmDb::getPackages() to build the
- * list<Package::Ptr> returned. We have to assert, that there
- * is a unique entry for every string.
- *
- * In the first step we build the _list list which contains all
- * packages (even those which are contained in multiple versions).
- *
- * At the end buildIndex() is called to build the _index is created
- * and points to the last installed versions of all packages.
- * Operations changing the rpmdb
- * content (install/remove package) should set _valid to false. The
- * next call to RpmDb::getPackages() will then reread the the rpmdb.
- *
- * Note that outside RpmDb::getPackages() _list and _index are always
- * in sync. So you may use lookup(PkgName) to retrieve a specific
- * Package::Ptr.
- **/
-class RpmDb::Packages
-{
-public:
- list<Package::Ptr> _list;
- map<string,Package::Ptr> _index;
- bool _valid;
- Packages() : _valid( false )
- {}
- void clear()
- {
- _list.clear();
- _index.clear();
- _valid = false;
- }
- Package::Ptr lookup( const string & name_r ) const
- {
- map<string,Package::Ptr>::const_iterator got = _index.find( name_r );
- if ( got != _index.end() )
- return got->second;
- return Package::Ptr();
- }
- void buildIndex()
- {
- _index.clear();
- for ( list<Package::Ptr>::iterator iter = _list.begin();
- iter != _list.end(); ++iter )
- {
- string name = (*iter)->name();
- Package::Ptr & nptr = _index[name]; // be shure to get a reference!
-
- if ( nptr )
- {
- WAR << "Multiple entries for package '" << name << "' in rpmdb" << endl;
- if ( nptr->installtime() > (*iter)->installtime() )
- continue;
- else
- nptr = *iter;
- }
- else
- {
- nptr = *iter;
- }
- }
- _valid = true;
- }
-};
-///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//
//
RpmDb::RpmDb()
: _dbStateInfo( DbSI_NO_INIT )
- , _packages( * new Packages ) // delete in destructor
#warning Check for obsolete memebers
, _backuppath ("/var/adm/backup")
, _packagebackups(false)
{
process = 0;
exit_code = -1;
-
+ librpmDb::globalInit();
// Some rpm versions are patched not to abort installation if
// symlink creation failed.
setenv( "RPM_IgnoreFailedSymlinks", "1", 1 );
{
MIL << "~RpmDb()" << endl;
closeDatabase();
-
delete process;
- delete &_packages;
MIL << "~RpmDb() end" << endl;
sKeyRingReceiver.reset();
}
// METHOD NAME : RpmDb::initDatabase
// METHOD TYPE : PMError
//
-void RpmDb::initDatabase( Pathname root_r, Pathname dbPath_r )
+void RpmDb::initDatabase( Pathname root_r, Pathname dbPath_r, bool doRebuild_r )
{
///////////////////////////////////////////////////////////////////
// Check arguments
///////////////////////////////////////////////////////////////////
+ bool quickinit( root_r.empty() );
+
if ( root_r.empty() )
root_r = "/";
ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r));
}
- MIL << "Calling initDatabase: " << stringPath( root_r, dbPath_r ) << endl;
+ MIL << "Calling initDatabase: " << stringPath( root_r, dbPath_r )
+ << ( doRebuild_r ? " (rebuilddb)" : "" )
+ << ( quickinit ? " (quickinit)" : "" ) << endl;
///////////////////////////////////////////////////////////////////
// Check whether already initialized
// init database
///////////////////////////////////////////////////////////////////
librpmDb::unblockAccess();
+
+ if ( quickinit )
+ {
+ MIL << "QUICK initDatabase (no systemRoot set)" << endl;
+ return;
+ }
+
DbStateInfoBits info = DbSI_NO_INIT;
try
{
_dbPath = dbPath_r;
_dbStateInfo = info;
-#warning Add rebuild database once have the info about context
-#if 0
- if ( ! ( Y2PM::runningFromSystem() ) )
+ if ( doRebuild_r )
{
if ( dbsi_has( info, DbSI_HAVE_V4 )
- && ! dbsi_has( info, DbSI_MADE_V4 ) )
+ && ! dbsi_has( info, DbSI_MADE_V4 ) )
{
- err = rebuildDatabase();
+ rebuildDatabase();
}
}
-#endif
- MIL << "Syncronizing keys with zypp keyring" << endl;
- // we do this one by one now.
- importZyppKeyRingTrustedKeys();
- exportTrustedKeysInZyppKeyRing();
+ MIL << "Synchronizing keys with zypp keyring" << endl;
+ syncTrustedKeys();
// Close the database in case any write acces (create/convert)
// happened during init. This should drop any lock acquired
{
WAR << "Non empty rpm3 and rpm4 database found: using rpm4" << endl;
-#warning EXCEPTION: nonempty rpm4 and rpm3 database found.
- //ConvertDbReport::Send report( RpmDbCallbacks::convertDbReport );
- //report->start( dbInfo.dbV3().path() );
- //report->stop( some error );
-
// set DbSI_MODIFIED_V4 as it's not a temporary which can be removed.
dbsi_set( info_r, DbSI_MODIFIED_V4 );
removeV3( _root + _dbPath, dbsi_has( _dbStateInfo, DbSI_MADE_V3TOV4 ) );
dbsi_clr( _dbStateInfo, DbSI_HAVE_V3 );
}
-
- // invalidate Packages list
- _packages._valid = false;
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// Block further database access
///////////////////////////////////////////////////////////////////
- _packages.clear();
librpmDb::blockAccess();
///////////////////////////////////////////////////////////////////
}
catch (RpmException & excpt_r)
{
- report->finish(root() + dbPath(), RebuildDBReport::FAILED, excpt_r.asUserString());
+ report->finish(root() + dbPath(), RebuildDBReport::FAILED, excpt_r.asUserHistory());
ZYPP_RETHROW(excpt_r);
}
report->finish(root() + dbPath(), RebuildDBReport::NO_ERROR, "");
// don't call modifyDatabase because it would remove the old
// rpm3 database, if the current database is a temporary one.
- // But do invalidate packages list.
- _packages._valid = false;
run_rpm (opts, ExternalProgram::Stderr_To_Stdout);
// progress report: watch this file growing
if ( newMaster() )
{ // file is removed at the end of rebuild.
// current size should be upper limit for new db
- report->progress( (100 * newMaster.size()) / dbMaster.size(), root() + dbPath());
+ if ( ! report->progress( (100 * newMaster.size()) / dbMaster.size(), root() + dbPath()) )
+ {
+ WAR << "User requested abort." << endl;
+ systemKill();
+ filesystem::recursive_rmdir( newMaster.path().dirname() );
+ }
}
if ( line.compare( 0, 2, "D:" ) )
if ( rpm_status != 0 )
{
- ZYPP_THROW(RpmSubprocessException(string("rpm failed with message: ") + errmsg));
+ //TranslatorExplanation after semicolon is error message
+ ZYPP_THROW(RpmSubprocessException(string(_("RPM failed: ") +
+ (errmsg.empty() ? error_message: errmsg))));
}
else
{
}
}
-void RpmDb::importZyppKeyRingTrustedKeys()
+///////////////////////////////////////////////////////////////////
+namespace
{
- MIL << "Importing zypp trusted keyring" << std::endl;
+ /** \ref RpmDb::syncTrustedKeys helper
+ * Compute which keys need to be exprted to / imported from the zypp keyring.
+ * Return result via argument list.
+ */
+ void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
+ {
+ ///////////////////////////////////////////////////////////////////
+ // Remember latest release and where it ocurred
+ struct Key
+ {
+ Key()
+ : _inRpmKeys( nullptr )
+ , _inZyppKeys( nullptr )
+ {}
- std::list<PublicKey> rpm_keys = pubkeys();
+ void updateIf( const Edition & rpmKey_r )
+ {
+ std::string keyRelease( rpmKey_r.release() );
+ int comp = _release.compare( keyRelease );
+ if ( comp < 0 )
+ {
+ // update to newer release
+ _release.swap( keyRelease );
+ _inRpmKeys = &rpmKey_r;
+ _inZyppKeys = nullptr;
+ if ( !keyRelease.empty() )
+ DBG << "Old key in R: gpg-pubkey-" << rpmKey_r.version() << "-" << keyRelease << endl;
+ }
+ else if ( comp == 0 )
+ {
+ // stay with this release
+ if ( ! _inRpmKeys )
+ _inRpmKeys = &rpmKey_r;
+ }
+ // else: this is an old release
+ else
+ DBG << "Old key in R: gpg-pubkey-" << rpmKey_r.version() << "-" << keyRelease << endl;
+ }
+
+ void updateIf( const PublicKeyData & zyppKey_r )
+ {
+ std::string keyRelease( zyppKey_r.gpgPubkeyRelease() );
+ int comp = _release.compare( keyRelease );
+ if ( comp < 0 )
+ {
+ // update to newer release
+ _release.swap( keyRelease );
+ _inRpmKeys = nullptr;
+ _inZyppKeys = &zyppKey_r;
+ if ( !keyRelease.empty() )
+ DBG << "Old key in Z: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << "-" << keyRelease << endl;
+ }
+ else if ( comp == 0 )
+ {
+ // stay with this release
+ if ( ! _inZyppKeys )
+ _inZyppKeys = &zyppKey_r;
+ }
+ // else: this is an old release
+ else
+ DBG << "Old key in Z: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << "-" << keyRelease << endl;
+ }
- std::list<PublicKey> zypp_keys;
+ std::string _release;
+ const Edition * _inRpmKeys;
+ const PublicKeyData * _inZyppKeys;
+ };
+ ///////////////////////////////////////////////////////////////////
- zypp_keys = getZYpp()->keyRing()->trustedPublicKeys();
+ // collect keys by ID(version) and latest creation(release)
+ std::map<std::string,Key> _keymap;
- for ( std::list<PublicKey>::const_iterator it = zypp_keys.begin(); it != zypp_keys.end(); ++it)
+ for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
{
- // we find only the left part of the long gpg key, as rpm does not support long ids
- std::list<PublicKey>::iterator ik = find( rpm_keys.begin(), rpm_keys.end(), (*it));
- if ( ik != rpm_keys.end() )
- {
- MIL << "Key " << (*it).id() << " (" << (*it).name() << ") is already in rpm database." << std::endl;
- }
- else
- {
- // now import the key in rpm
- try
- {
- importPubkey((*it).path());
- MIL << "Trusted key " << (*it).id() << " (" << (*it).name() << ") imported in rpm database." << std::endl;
- }
- catch (RpmException &e)
- {
- ERR << "Could not import key " << (*it).id() << " (" << (*it).name() << " from " << (*it).path() << " in rpm database" << std::endl;
- }
- }
+ _keymap[(*it).version()].updateIf( *it );
}
-}
-void RpmDb::exportTrustedKeysInZyppKeyRing()
-{
- MIL << "Exporting rpm keyring into zypp trusted keyring" <<endl;
-
- set<Edition> rpm_keys = pubkeyEditions();
-
- list<PublicKey> zypp_keys;
- zypp_keys = getZYpp()->keyRing()->trustedPublicKeys();
-
- for ( set<Edition>::const_iterator it = rpm_keys.begin(); it != rpm_keys.end(); ++it)
- {
- // search the zypp key into the rpm keys
- // long id is edition version + release
- string id = str::toUpper( (*it).version() + (*it).release());
- list<PublicKey>::iterator ik = find( zypp_keys.begin(), zypp_keys.end(), id);
- if ( ik != zypp_keys.end() )
+ for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
{
- MIL << "Key " << (*it) << " is already in zypp database." << endl;
+ _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
}
- else
+
+ // compute missing keys
+ std::set<Edition> rpmKeys;
+ std::list<PublicKeyData> zyppKeys;
+ for_( it, _keymap.begin(), _keymap.end() )
{
- // we export the rpm key into a file
- RpmHeader::constPtr result = new RpmHeader();
- getData( string("gpg-pubkey"), *it, result );
- TmpFile file(getZYpp()->tmpPath());
- ofstream os;
- try
+ DBG << "gpg-pubkey-" << (*it).first << "-" << (*it).second._release << " "
+ << ( (*it).second._inRpmKeys ? "R" : "_" )
+ << ( (*it).second._inZyppKeys ? "Z" : "_" ) << endl;
+ if ( ! (*it).second._inRpmKeys )
{
- os.open(file.path().asString().c_str());
- // dump rpm key into the tmp file
- os << result->tag_description();
- //MIL << "-----------------------------------------------" << endl;
- //MIL << result->tag_description() <<endl;
- //MIL << "-----------------------------------------------" << endl;
- os.close();
+ zyppKeys.push_back( *(*it).second._inZyppKeys );
}
- catch (exception &e)
+ if ( ! (*it).second._inZyppKeys )
{
- ERR << "Could not dump key " << (*it) << " in tmp file " << file.path() << endl;
- // just ignore the key
+ rpmKeys.insert( *(*it).second._inRpmKeys );
}
+ }
+ rpmKeys_r.swap( rpmKeys );
+ zyppKeys_r.swap( zyppKeys );
+ }
+} // namespace
+///////////////////////////////////////////////////////////////////
+
+void RpmDb::syncTrustedKeys( SyncTrustedKeyBits mode_r )
+{
+ MIL << "Going to sync trusted keys..." << endl;
+ std::set<Edition> rpmKeys( pubkeyEditions() );
+ std::list<PublicKeyData> zyppKeys( getZYpp()->keyRing()->trustedPublicKeyData() );
+ computeKeyRingSync( rpmKeys, zyppKeys );
+ MIL << (mode_r & SYNC_TO_KEYRING ? "" : "(skip) ") << "Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
+ MIL << (mode_r & SYNC_FROM_KEYRING ? "" : "(skip) ") << "Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
+
+ ///////////////////////////////////////////////////////////////////
+ if ( (mode_r & SYNC_TO_KEYRING) && ! rpmKeys.empty() )
+ {
+ // export to zypp keyring
+ MIL << "Exporting rpm keyring into zypp trusted keyring" <<endl;
+ // Temporarily disconnect to prevent the attemt to re-import the exported keys.
+ callback::TempConnect<KeyRingSignals> tempDisconnect;
+ librpmDb::db_const_iterator keepDbOpen; // just to keep a ref.
+
+ TmpFile tmpfile( getZYpp()->tmpPath() );
+ {
+ ofstream tmpos( tmpfile.path().c_str() );
+ for_( it, rpmKeys.begin(), rpmKeys.end() )
+ {
+ // we export the rpm key into a file
+ RpmHeader::constPtr result;
+ getData( string("gpg-pubkey"), *it, result );
+ tmpos << result->tag_description() << endl;
+ }
+ }
+ try
+ {
+ getZYpp()->keyRing()->multiKeyImport( tmpfile.path(), true /*trusted*/);
+ }
+ catch (Exception &e)
+ {
+ ERR << "Could not import keys into in zypp keyring" << endl;
+ }
+ }
- // now import the key in zypp
+ ///////////////////////////////////////////////////////////////////
+ if ( (mode_r & SYNC_FROM_KEYRING) && ! zyppKeys.empty() )
+ {
+ // import from zypp keyring
+ MIL << "Importing zypp trusted keyring" << std::endl;
+ for_( it, zyppKeys.begin(), zyppKeys.end() )
+ {
try
{
- getZYpp()->keyRing()->importKey( file.path(), true /*trusted*/);
- MIL << "Trusted key " << (*it) << " imported in zypp keyring." << endl;
+ importPubkey( getZYpp()->keyRing()->exportTrustedPublicKey( *it ) );
}
- catch (Exception &e)
+ catch ( const RpmException & exp )
{
- ERR << "Could not import key " << (*it) << " in zypp keyring" << endl;
+ ZYPP_CAUGHT( exp );
}
}
}
+ MIL << "Trusted keys synced." << endl;
}
+void RpmDb::importZyppKeyRingTrustedKeys()
+{ syncTrustedKeys( SYNC_FROM_KEYRING ); }
+
+void RpmDb::exportTrustedKeysInZyppKeyRing()
+{ syncTrustedKeys( SYNC_TO_KEYRING ); }
+
///////////////////////////////////////////////////////////////////
//
//
{
FAILIFNOTINITIALIZED;
- // check if the key is already in the rpm database and just
- // return if it does.
- set<Edition> rpm_keys = pubkeyEditions();
- for ( set<Edition>::const_iterator it = rpm_keys.begin(); it != rpm_keys.end(); ++it)
+ // bnc#828672: On the fly key import in READONLY
+ if ( zypp_readonly_hack::IGotIt() )
+ {
+ WAR << "Key " << pubkey_r << " can not be imported. (READONLY MODE)" << endl;
+ return;
+ }
+
+ // check if the key is already in the rpm database
+ Edition keyEd( pubkey_r.gpgPubkeyVersion(), pubkey_r.gpgPubkeyRelease() );
+ set<Edition> rpmKeys = pubkeyEditions();
+ bool hasOldkeys = false;
+
+ for_( it, rpmKeys.begin(), rpmKeys.end() )
{
- string id = str::toUpper( (*it).version() );
- string keyshortid = pubkey_r.id().substr(8,8);
- MIL << "Comparing '" << id << "' to '" << keyshortid << "'" << endl;
- if ( id == keyshortid )
+ if ( keyEd == *it ) // quick test (Edition is IdStringType!)
{
- // they match id
- // FIXME id is not sufficient?
- MIL << "Key " << pubkey_r << " is already in the rpm trusted keyring." << endl;
+ MIL << "Key " << pubkey_r << " is already in the rpm trusted keyring. (skip import)" << endl;
return;
}
+
+ if ( keyEd.version() != (*it).version() )
+ continue; // different key ID (version)
+
+ if ( keyEd.release() < (*it).release() )
+ {
+ MIL << "Key " << pubkey_r << " is older than one in the rpm trusted keyring. (skip import)" << endl;
+ return;
+ }
+ else
+ {
+ hasOldkeys = true;
+ }
}
- // key does not exists, lets import it
+ MIL << "Key " << pubkey_r << " will be imported into the rpm trusted keyring." << (hasOldkeys?"(update)":"(new)") << endl;
+
+ if ( hasOldkeys )
+ {
+ // We must explicitly delete old key IDs first (all releases,
+ // that's why we don't call removePubkey here).
+ std::string keyName( "gpg-pubkey-" + keyEd.version() );
+ RpmArgVec opts;
+ opts.push_back ( "-e" );
+ opts.push_back ( "--allmatches" );
+ opts.push_back ( "--" );
+ opts.push_back ( keyName.c_str() );
+ // don't call modifyDatabase because it would remove the old
+ // rpm3 database, if the current database is a temporary one.
+ run_rpm( opts, ExternalProgram::Stderr_To_Stdout );
+
+ string line;
+ while ( systemReadLine( line ) )
+ {
+ ( str::startsWith( line, "error:" ) ? WAR : DBG ) << line << endl;
+ }
+ if ( systemStatus() != 0 )
+ {
+ ERR << "Failed to remove key " << pubkey_r << " from RPM trusted keyring (ignored)" << endl;
+ }
+ else
+ {
+ MIL << "Key " << pubkey_r << " has been removed from RPM trusted keyring" << endl;
+ }
+ }
+
+ // import the new key
RpmArgVec opts;
opts.push_back ( "--import" );
opts.push_back ( "--" );
// don't call modifyDatabase because it would remove the old
// rpm3 database, if the current database is a temporary one.
- // But do invalidate packages list.
- _packages._valid = false;
run_rpm( opts, ExternalProgram::Stderr_To_Stdout );
string line;
while ( systemReadLine( line ) )
{
- if ( line.substr( 0, 6 ) == "error:" )
- {
- WAR << line << endl;
- }
- else
- {
- DBG << line << endl;
- }
+ ( str::startsWith( line, "error:" ) ? WAR : DBG ) << line << endl;
}
- int rpm_status = systemStatus();
-
- if ( rpm_status != 0 )
+ if ( systemStatus() != 0 )
{
- ZYPP_THROW(RpmSubprocessException(string("Failed to import public key from file ") + pubkey_r.asString() + string(": rpm returned ") + str::numstring(rpm_status)));
+ //TranslatorExplanation first %s is file name, second is error message
+ ZYPP_THROW(RpmSubprocessException( str::Format(_("Failed to import public key from file %s: %s"))
+ % pubkey_r.asString()
+ % error_message ));
}
else
{
// check if the key is in the rpm database and just
// return if it does not.
set<Edition> rpm_keys = pubkeyEditions();
-
- // search the key
set<Edition>::const_iterator found_edition = rpm_keys.end();
+ std::string pubkeyVersion( pubkey_r.gpgPubkeyVersion() );
- for ( set<Edition>::const_iterator it = rpm_keys.begin(); it != rpm_keys.end(); ++it)
+ for_( it, rpm_keys.begin(), rpm_keys.end() )
{
- string id = str::toUpper( (*it).version() );
- string keyshortid = pubkey_r.id().substr(8,8);
- MIL << "Comparing '" << id << "' to '" << keyshortid << "'" << endl;
- if ( id == keyshortid )
+ if ( (*it).version() == pubkeyVersion )
{
found_edition = it;
break;
// don't call modifyDatabase because it would remove the old
// rpm3 database, if the current database is a temporary one.
- // But do invalidate packages list.
- _packages._valid = false;
run_rpm( opts, ExternalProgram::Stderr_To_Stdout );
string line;
if ( rpm_status != 0 )
{
- ZYPP_THROW(RpmSubprocessException(string("Failed to remove public key ") + pubkey_r.asString() + string(": rpm returned ") + str::numstring(rpm_status)));
+ //TranslatorExplanation first %s is key name, second is error message
+ ZYPP_THROW(RpmSubprocessException( str::Format(_("Failed to remove public key %s: %s"))
+ % pubkey_r.asString()
+ % error_message ));
}
else
{
if (edition != Edition::noedition)
{
// we export the rpm key into a file
- RpmHeader::constPtr result = new RpmHeader();
+ RpmHeader::constPtr result;
getData( string("gpg-pubkey"), edition, result );
TmpFile file(getZYpp()->tmpPath());
ofstream os;
//MIL << "-----------------------------------------------" << endl;
os.close();
// read the public key from the dumped file
- PublicKey key(file.path());
+ PublicKey key(file);
ret.push_back(key);
}
catch (exception &e)
return ret;
}
-///////////////////////////////////////////////////////////////////
-//
-//
-// METHOD NAME : RpmDb::packagesValid
-// METHOD TYPE : bool
-//
-bool RpmDb::packagesValid() const
-{
- return( _packages._valid || ! initialized() );
-}
-
-///////////////////////////////////////////////////////////////////
-//
-//
-// METHOD NAME : RpmDb::getPackages
-// METHOD TYPE : const list<Package::Ptr> &
-//
-// DESCRIPTION :
-//
-const list<Package::Ptr> & RpmDb::getPackages()
-{
- callback::SendReport<ScanDBReport> report;
-
- report->start ();
-
- try
- {
- const list<Package::Ptr> & ret = doGetPackages(report);
- report->finish(ScanDBReport::NO_ERROR, "");
- return ret;
- }
- catch (RpmException & excpt_r)
- {
- report->finish(ScanDBReport::FAILED, excpt_r.asUserString ());
- ZYPP_RETHROW(excpt_r);
- }
-#warning fixme
- static const list<Package::Ptr> empty_list;
- return empty_list;
-}
-
-#warning FIX READING RPM DATBASE TO POOL
-#if 0 // obsolete helper
-inline static void insertCaps( Capabilities &capset, capability::CapabilityImplPtrSet ptrset, CapFactory &factory )
-{
- for ( capability::CapabilityImplPtrSet::const_iterator it = ptrset.begin();
- it != ptrset.end();
- ++it )
- {
- capset.insert( factory.fromImpl(*it) );
- }
-}
-#endif
-
-//
-// make Package::Ptr from RpmHeader
-// return NULL on error
-//
-Package::Ptr RpmDb::makePackageFromHeader( const RpmHeader::constPtr header,
- set<string> * filerequires,
- const Pathname & location, Repository repo )
-{
- if ( ! header )
- return 0;
-
- if ( header->isSrc() )
- {
- WAR << "Can't make Package from SourcePackage header" << endl;
- return 0;
- }
-
- Package::Ptr pptr;
-#warning FIX READING RPM DATBASE TO POOL
-#if 0
- string name = header->tag_name();
-
- // create dataprovider
- detail::ResImplTraits<RPMPackageImpl>::Ptr impl( new RPMPackageImpl( header ) );
-
- impl->setRepository( repo );
- if (!location.empty())
- impl->setLocation( OnMediaLocation(location,1) );
-
- Edition edition;
- try
- {
- edition = Edition( header->tag_version(),
- header->tag_release(),
- header->tag_epoch());
- }
- catch (Exception & excpt_r)
- {
- ZYPP_CAUGHT( excpt_r );
- WAR << "Package " << name << " has bad edition '"
- << (header->tag_epoch()==0?"":(header->tag_epoch()+":"))
- << header->tag_version()
- << (header->tag_release().empty()?"":(string("-") + header->tag_release())) << "'";
- return pptr;
- }
-
- Arch arch;
- try
- {
- arch = Arch( header->tag_arch() );
- }
- catch (Exception & excpt_r)
- {
- ZYPP_CAUGHT( excpt_r );
- WAR << "Package " << name << " has bad architecture '" << header->tag_arch() << "'";
- return pptr;
- }
-
- // Collect basic Resolvable data
- NVRAD dataCollect( header->tag_name(),
- edition,
- arch );
-
- list<string> filenames = impl->filenames();
- CapFactory capfactory;
- insertCaps( dataCollect[Dep::PROVIDES], header->tag_provides( filerequires ), capfactory );
-
- for (list<string>::const_iterator filename = filenames.begin();
- filename != filenames.end();
- ++filename)
- {
- if ( capability::isInterestingFileSpec( *filename ) )
- {
- try
- {
- dataCollect[Dep::PROVIDES].insert(capfactory.fromImpl(capability::buildFile(ResTraits<Package>::kind, *filename) ));
- }
- catch (Exception & excpt_r)
- {
- ZYPP_CAUGHT( excpt_r );
- WAR << "Ignoring invalid capability: " << *filename << endl;
- }
- }
- }
-
- insertCaps( dataCollect[Dep::REQUIRES], header->tag_requires( filerequires ), capfactory );
- insertCaps( dataCollect[Dep::PREREQUIRES], header->tag_prerequires( filerequires ), capfactory );
- insertCaps( dataCollect[Dep::CONFLICTS], header->tag_conflicts( filerequires ), capfactory );
- insertCaps( dataCollect[Dep::OBSOLETES], header->tag_obsoletes( filerequires ), capfactory );
- insertCaps( dataCollect[Dep::ENHANCES], header->tag_enhances( filerequires ), capfactory );
- insertCaps( dataCollect[Dep::SUPPLEMENTS], header->tag_supplements( filerequires ), capfactory );
-
- try
- {
- // create package from dataprovider
- pptr = detail::makeResolvableFromImpl( dataCollect, impl );
- }
- catch (Exception & excpt_r)
- {
- ZYPP_CAUGHT( excpt_r );
- ERR << "Can't create Package::Ptr" << endl;
- }
-#endif
- return pptr;
-}
-
-const list<Package::Ptr> & RpmDb::doGetPackages(callback::SendReport<ScanDBReport> & report)
-{
- if ( packagesValid() )
- {
- return _packages._list;
- }
-
- _packages.clear();
-
- ///////////////////////////////////////////////////////////////////
- // Collect package data.
- ///////////////////////////////////////////////////////////////////
- unsigned expect = 0;
- librpmDb::constPtr dbptr;
- librpmDb::dbAccess( dbptr );
- expect = dbptr->size();
- DBG << "Expecting " << expect << " packages" << endl;
-
- librpmDb::db_const_iterator iter;
- unsigned current = 0;
- Pathname location;
-
- for ( iter.findAll(); *iter; ++iter, ++current, report->progress( (100*current)/expect))
- {
-
- string name = iter->tag_name();
- if ( name == string( "gpg-pubkey" ) )
- {
- DBG << "Ignoring pseudo package " << name << endl;
- // pseudo package filtered, as we can't handle multiple instances
- // of 'gpg-pubkey-VERS-REL'.
- continue;
- }
-
- Package::Ptr pptr = makePackageFromHeader( *iter, &_filerequires, location, Repository() );
- if ( ! pptr )
- {
- WAR << "Failed to make package from database header '" << name << "'" << endl;
- continue;
- }
-
- _packages._list.push_back( pptr );
- }
- _packages.buildIndex();
- DBG << "Found installed packages: " << _packages._list.size() << endl;
-
-#warning FILEREQUIRES HACK SHOULD BE DONE WHEN WRITING THE RPMDB SOLV FILE
-#if 0
- ///////////////////////////////////////////////////////////////////
- // Evaluate filerequires collected so far
- ///////////////////////////////////////////////////////////////////
- for ( set<string>::iterator it = _filerequires.begin(); it != _filerequires.end(); ++it )
- {
-
- for ( iter.findByFile( *it ); *iter; ++iter )
- {
- Package::Ptr pptr = _packages.lookup( iter->tag_name() );
- if ( !pptr )
- {
- WAR << "rpmdb.findByFile returned unknown package " << *iter << endl;
- continue;
- }
- pptr->injectProvides(_f.parse(ResTraits<Package>::kind, *it));
- }
- }
-#endif
-
- ///////////////////////////////////////////////////////////////////
- // Build final packages list
- ///////////////////////////////////////////////////////////////////
- return _packages._list;
-}
///////////////////////////////////////////////////////////////////
//
}
///////////////////////////////////////////////////////////////////
+namespace
+{
+ struct RpmlogCapture : public std::string
+ {
+ RpmlogCapture()
+ { rpmlog()._cap = this; }
+
+ ~RpmlogCapture()
+ { rpmlog()._cap = nullptr; }
+
+ private:
+ struct Rpmlog
+ {
+ Rpmlog()
+ : _cap( nullptr )
+ {
+ rpmlogSetCallback( rpmLogCB, this );
+ rpmSetVerbosity( RPMLOG_INFO );
+ _f = ::fopen( "/dev/null","w");
+ rpmlogSetFile( _f );
+ }
+
+ ~Rpmlog()
+ { if ( _f ) ::fclose( _f ); }
+
+ static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
+ { return reinterpret_cast<Rpmlog*>(data_r)->rpmLog( rec_r ); }
+
+ int rpmLog( rpmlogRec rec_r )
+ {
+ if ( _cap ) (*_cap) = rpmlogRecMessage( rec_r );
+ return RPMLOG_DEFAULT;
+ }
+
+ FILE * _f;
+ std::string * _cap;
+ };
+
+ static Rpmlog & rpmlog()
+ { static Rpmlog _rpmlog; return _rpmlog; }
+ };
+
+
+} // namespace
+///////////////////////////////////////////////////////////////////
//
// METHOD NAME : RpmDb::checkPackage
-// METHOD TYPE : RpmDb::checkPackageResult
+// METHOD TYPE : RpmDb::CheckPackageResult
//
-RpmDb::checkPackageResult RpmDb::checkPackage( const Pathname & path_r )
+RpmDb::CheckPackageResult RpmDb::checkPackage( const Pathname & path_r, CheckPackageDetail & detail_r )
{
PathInfo file( path_r );
if ( ! file.isFile() )
::Fclose( fd );
return CHK_ERROR;
}
-
rpmts ts = ::rpmtsCreate();
::rpmtsSetRootDir( ts, root().asString().c_str() );
::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
- int res = ::rpmReadPackageFile( ts, fd, path_r.asString().c_str(), NULL );
- ts = ::rpmtsFree(ts);
+ rpmQVKArguments_s qva;
+ memset( &qva, 0, sizeof(rpmQVKArguments_s) );
+ qva.qva_flags = (VERIFY_DIGEST|VERIFY_SIGNATURE);
+
+ RpmlogCapture vresult;
+ int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.basename().c_str() );
+
+ ts = rpmtsFree(ts);
::Fclose( fd );
- switch ( res )
+
+ if ( res == 0 )
{
- case RPMRC_OK:
+ detail_r.push_back( CheckPackageDetail::value_type( CHK_OK, std::move(vresult) ) );
return CHK_OK;
- break;
- case RPMRC_NOTFOUND:
- WAR << "Signature is unknown type. " << file << endl;
- return CHK_NOTFOUND;
- break;
- case RPMRC_FAIL:
- WAR << "Signature does not verify. " << file << endl;
- return CHK_FAIL;
- break;
- case RPMRC_NOTTRUSTED:
- WAR << "Signature is OK, but key is not trusted. " << file << endl;
- return CHK_NOTTRUSTED;
- break;
- case RPMRC_NOKEY:
- WAR << "Public key is unavailable. " << file << endl;
- return CHK_NOKEY;
- break;
}
- ERR << "Error reading header." << file << endl;
- return CHK_ERROR;
+
+ // results per line...
+ WAR << vresult;
+ std::vector<std::string> lines;
+ str::split( vresult, std::back_inserter(lines), "\n" );
+ unsigned count[6] = { 0, 0, 0, 0, 0, 0 };
+
+ for ( unsigned i = 1; i < lines.size(); ++i )
+ {
+ std::string & line( lines[i] );
+ CheckPackageResult lineres = CHK_ERROR;
+ if ( line.find( ": OK" ) != std::string::npos )
+ { lineres = CHK_OK; }
+ else if ( line.find( ": NOKEY" ) != std::string::npos )
+ { lineres = CHK_NOKEY; }
+ else if ( line.find( ": BAD" ) != std::string::npos )
+ { lineres = CHK_FAIL; }
+ else if ( line.find( ": UNKNOWN" ) != std::string::npos )
+ { lineres = CHK_NOTFOUND; }
+ else if ( line.find( ": NOTRUSTED" ) != std::string::npos )
+ { lineres = CHK_NOTTRUSTED; }
+
+ ++count[lineres];
+ detail_r.push_back( CheckPackageDetail::value_type( lineres, std::move(line) ) );
+ }
+
+ CheckPackageResult ret = CHK_ERROR;
+ if ( count[CHK_FAIL] )
+ ret = CHK_FAIL;
+
+ else if ( count[CHK_NOTFOUND] )
+ ret = CHK_NOTFOUND;
+
+ else if ( count[CHK_NOKEY] )
+ ret = CHK_NOKEY;
+
+ else if ( count[CHK_NOTTRUSTED] )
+ ret = CHK_NOTTRUSTED;
+
+ return ret;
}
+RpmDb::CheckPackageResult RpmDb::checkPackage( const Pathname & path_r )
+{ CheckPackageDetail dummy; return checkPackage( path_r, dummy ); }
+
+
// determine changed files of installed package
bool
RpmDb::queryChangedFiles(FileList & fileList, const string& packageName)
RpmArgVec args;
// always set root and dbpath
+#if defined(WORKAROUNDRPMPWDBUG)
+ args.push_back("#/"); // chdir to / to workaround bnc#819354
+#endif
args.push_back("rpm");
args.push_back("--root");
args.push_back(_root.asString().c_str());
/*--------------------------------------------------------------*/
/* Read a line from the rpm process */
/*--------------------------------------------------------------*/
-bool
-RpmDb::systemReadLine(string &line)
+bool RpmDb::systemReadLine( string & line )
{
line.erase();
if ( process == NULL )
return false;
- line = process->receiveLine();
+ if ( process->inputFile() )
+ {
+ process->setBlocking( false );
+ FILE * inputfile = process->inputFile();
+ int inputfileFd = ::fileno( inputfile );
+ do
+ {
+ /* Watch inputFile to see when it has input. */
+ fd_set rfds;
+ FD_ZERO( &rfds );
+ FD_SET( inputfileFd, &rfds );
+
+ /* Wait up to 5 seconds. */
+ struct timeval tv;
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
- if (line.length() == 0)
- return false;
+ int retval = select( inputfileFd+1, &rfds, NULL, NULL, &tv );
- if (line[line.length() - 1] == '\n')
- line.erase(line.length() - 1);
+ if ( retval == -1 )
+ {
+ ERR << "select error: " << strerror(errno) << endl;
+ if ( errno != EINTR )
+ return false;
+ }
+ else if ( retval )
+ {
+ // Data is available now.
+ static size_t linebuffer_size = 0; // static because getline allocs
+ static char * linebuffer = 0; // and reallocs if buffer is too small
+ ssize_t nread = getline( &linebuffer, &linebuffer_size, inputfile );
+ if ( nread == -1 )
+ {
+ if ( ::feof( inputfile ) )
+ return line.size(); // in case of pending output
+ }
+ else
+ {
+ if ( nread > 0 )
+ {
+ if ( linebuffer[nread-1] == '\n' )
+ --nread;
+ line += string( linebuffer, nread );
+ }
+
+ if ( ! ::ferror( inputfile ) || ::feof( inputfile ) )
+ return true; // complete line
+ }
+ clearerr( inputfile );
+ }
+ else
+ {
+ // No data within time.
+ if ( ! process->running() )
+ return false;
+ }
+ } while ( true );
+ }
- return true;
+ return false;
}
/*--------------------------------------------------------------*/
return -1;
exit_code = process->close();
+ if (exit_code == 0)
+ error_message = "";
+ else
+ error_message = process->execError();
process->kill();
delete process;
process = 0;
// METHOD NAME : RpmDb::installPackage
// METHOD TYPE : PMError
//
-void RpmDb::installPackage( const Pathname & filename, unsigned flags )
+void RpmDb::installPackage( const Pathname & filename, RpmInstFlags flags )
{
callback::SendReport<RpmInstallReport> report;
while (true);
}
-void RpmDb::doInstallPackage( const Pathname & filename, unsigned flags, callback::SendReport<RpmInstallReport> & report )
+void RpmDb::doInstallPackage( const Pathname & filename, RpmInstFlags flags, callback::SendReport<RpmInstallReport> & report )
{
FAILIFNOTINITIALIZED;
- CommitLog progresslog;
+ HistoryLog historylog;
MIL << "RpmDb::installPackage(" << filename << "," << flags << ")" << endl;
// FIXME status handling
report->progress( 0 ); // allow 1% for backup creation.
}
- else
- {
- report->progress( 100 );
- }
// run rpm
RpmArgVec opts;
opts.push_back("-i");
else
opts.push_back("-U");
+
opts.push_back("--percent");
+ opts.push_back("--noglob");
+
+ // ZConfig defines cross-arch installation
+ if ( ! ZConfig::instance().systemArchitecture().compatibleWith( ZConfig::instance().defaultSystemArchitecture() ) )
+ opts.push_back("--ignorearch");
if (flags & RPMINST_NODIGEST)
opts.push_back("--nodigest");
if (flags & RPMINST_NOSIGNATURE)
opts.push_back("--nosignature");
- if (flags & RPMINST_NODOCS)
+ if (flags & RPMINST_EXCLUDEDOCS)
opts.push_back ("--excludedocs");
if (flags & RPMINST_NOSCRIPTS)
opts.push_back ("--noscripts");
opts.push_back ("--justdb");
if (flags & RPMINST_TEST)
opts.push_back ("--test");
+ if (flags & RPMINST_NOPOSTTRANS)
+ opts.push_back ("--noposttrans");
opts.push_back("--");
// rpm requires additional quoting of special chars:
- string quotedFilename( rpmQuoteFilename( filename ) );
+ string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
opts.push_back ( quotedFilename.c_str() );
modifyDatabase(); // BEFORE run_rpm
string line;
string rpmmsg;
vector<string> configwarnings;
- vector<string> errorlines;
+ unsigned linecnt = 0;
while (systemReadLine(line))
{
+ if ( linecnt < MAXRPMMESSAGELINES )
+ ++linecnt;
+ else
+ continue;
+
if (line.substr(0,2)=="%%")
{
int percent;
configwarnings.push_back(line);
}
}
+ if ( linecnt > MAXRPMMESSAGELINES )
+ rpmmsg += "[truncated]\n";
+
int rpm_status = systemStatus();
// evaluate result
if ( rpm_status != 0 )
{
- // %s = filename of rpm package
- progresslog(/*timestamp*/true) << str::form(_("%s install failed"), Pathname::basename(filename).c_str()) << endl;
- progresslog() << _("rpm output:") << endl << rpmmsg << endl;
- ZYPP_THROW(RpmSubprocessException(string("RPM failed: ") + rpmmsg));
- }
- else
- {
- // %s = filename of rpm package
- progresslog(/*timestamp*/true) << str::form(_("%s installed ok"), Pathname::basename(filename).c_str()) << endl;
- if ( ! rpmmsg.empty() )
- {
- progresslog() << _("Additional rpm output:") << endl << rpmmsg << endl;
- }
+ historylog.comment(
+ str::form("%s install failed", Pathname::basename(filename).c_str()),
+ true /*timestamp*/);
+ ostringstream sstr;
+ sstr << "rpm output:" << endl << rpmmsg << endl;
+ historylog.comment(sstr.str());
+ // TranslatorExplanation the colon is followed by an error message
+ ZYPP_THROW(RpmSubprocessException(string(_("RPM failed: ")) +
+ (rpmmsg.empty() ? error_message : rpmmsg)));
+ }
+ else if ( ! rpmmsg.empty() )
+ {
+ historylog.comment(
+ str::form("%s installed ok", Pathname::basename(filename).c_str()),
+ true /*timestamp*/);
+ ostringstream sstr;
+ sstr << "Additional rpm output:" << endl << rpmmsg << endl;
+ historylog.comment(sstr.str());
+
+ // report additional rpm output in finish
+ // TranslatorExplanation Text is followed by a ':' and the actual output.
+ report->finishInfo(str::form( "%s:\n%s\n", _("Additional rpm output"), rpmmsg.c_str() ));
}
}
// METHOD NAME : RpmDb::removePackage
// METHOD TYPE : PMError
//
-void RpmDb::removePackage( Package::constPtr package, unsigned flags )
+void RpmDb::removePackage( Package::constPtr package, RpmInstFlags flags )
{
+ // 'rpm -e' does not like epochs
return removePackage( package->name()
- + "-" + package->edition().asString()
+ + "-" + package->edition().version()
+ + "-" + package->edition().release()
+ "." + package->arch().asString(), flags );
}
// METHOD NAME : RpmDb::removePackage
// METHOD TYPE : PMError
//
-void RpmDb::removePackage( const string & name_r, unsigned flags )
+void RpmDb::removePackage( const string & name_r, RpmInstFlags flags )
{
callback::SendReport<RpmRemoveReport> report;
report->start( name_r );
- try
- {
- doRemovePackage(name_r, flags, report);
- }
- catch (RpmException & excpt_r)
- {
- report->finish(excpt_r);
- ZYPP_RETHROW(excpt_r);
- }
- report->finish();
+ do
+ try
+ {
+ doRemovePackage(name_r, flags, report);
+ report->finish();
+ break;
+ }
+ catch (RpmException & excpt_r)
+ {
+ RpmRemoveReport::Action user = report->problem( excpt_r );
+
+ if ( user == RpmRemoveReport::ABORT )
+ {
+ report->finish( excpt_r );
+ ZYPP_RETHROW(excpt_r);
+ }
+ else if ( user == RpmRemoveReport::IGNORE )
+ {
+ break;
+ }
+ }
+ while (true);
}
-void RpmDb::doRemovePackage( const string & name_r, unsigned flags, callback::SendReport<RpmRemoveReport> & report )
+void RpmDb::doRemovePackage( const string & name_r, RpmInstFlags flags, callback::SendReport<RpmRemoveReport> & report )
{
FAILIFNOTINITIALIZED;
- CommitLog progresslog;
+ HistoryLog historylog;
MIL << "RpmDb::doRemovePackage(" << name_r << "," << flags << ")" << endl;
// 50 - command completed
// 100 if no error
report->progress( 5 );
+ unsigned linecnt = 0;
while (systemReadLine(line))
{
+ if ( linecnt < MAXRPMMESSAGELINES )
+ ++linecnt;
+ else
+ continue;
rpmmsg += line+'\n';
}
+ if ( linecnt > MAXRPMMESSAGELINES )
+ rpmmsg += "[truncated]\n";
report->progress( 50 );
int rpm_status = systemStatus();
if ( rpm_status != 0 )
{
- // %s = name of rpm package
- progresslog(/*timestamp*/true) << str::form(_("%s remove failed"), name_r.c_str()) << endl;
- progresslog() << _("rpm output:") << endl << rpmmsg << endl;
- ZYPP_THROW(RpmSubprocessException(string("RPM failed: ") + rpmmsg));
+ historylog.comment(
+ str::form("%s remove failed", name_r.c_str()), true /*timestamp*/);
+ ostringstream sstr;
+ sstr << "rpm output:" << endl << rpmmsg << endl;
+ historylog.comment(sstr.str());
+ // TranslatorExplanation the colon is followed by an error message
+ ZYPP_THROW(RpmSubprocessException(string(_("RPM failed: ")) +
+ (rpmmsg.empty() ? error_message: rpmmsg)));
}
- else
+ else if ( ! rpmmsg.empty() )
{
- progresslog(/*timestamp*/true) << str::form(_("%s remove ok"), name_r.c_str()) << endl;
- if ( ! rpmmsg.empty() )
- {
- progresslog() << _("Additional rpm output:") << endl << rpmmsg << endl;
- }
+ historylog.comment(
+ str::form("%s removed ok", name_r.c_str()), true /*timestamp*/);
+
+ ostringstream sstr;
+ sstr << "Additional rpm output:" << endl << rpmmsg << endl;
+ historylog.comment(sstr.str());
+
+ // report additional rpm output in finish
+ // TranslatorExplanation Text is followed by a ':' and the actual output.
+ report->finishInfo(str::form( "%s:\n%s\n", _("Additional rpm output"), rpmmsg.c_str() ));
}
}
//
bool RpmDb::backupPackage(const string& packageName)
{
- CommitLog progresslog;
+ HistoryLog progresslog;
bool ret = true;
Pathname backupFilename;
Pathname filestobackupfile = _root+_backuppath+FILEFORBACKUPFILES;
else
{
MIL << "tar backup ok" << endl;
- progresslog(/*timestamp*/true) << str::form(_("created backup %s"), backupFilename.asString().c_str()) << endl;
+ progresslog.comment(
+ str::form(_("created backup %s"), backupFilename.asString().c_str())
+ , /*timestamp*/true);
}
filesystem::unlink(filestobackupfile);
_backuppath = path;
}
+std::ostream & operator<<( std::ostream & str, RpmDb::CheckPackageResult obj )
+{
+ switch ( obj )
+ {
+#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
+ // translators: possible rpm package signature check result [brief]
+ OUTS( CHK_OK, _("Signature is OK") );
+ // translators: possible rpm package signature check result [brief]
+ OUTS( CHK_NOTFOUND, _("Unknown type of signature") );
+ // translators: possible rpm package signature check result [brief]
+ OUTS( CHK_FAIL, _("Signature does not verify") );
+ // translators: possible rpm package signature check result [brief]
+ OUTS( CHK_NOTTRUSTED, _("Signature is OK, but key is not trusted") );
+ // translators: possible rpm package signature check result [brief]
+ OUTS( CHK_NOKEY, _("Signatures public key is not available") );
+ // translators: possible rpm package signature check result [brief]
+ OUTS( CHK_ERROR, _("File does not exist or signature can't be checked") );
+#undef OUTS
+ }
+ return str << "UnknowSignatureCheckError("+str::numstring(obj)+")";
+}
+
+std::ostream & operator<<( std::ostream & str, const RpmDb::CheckPackageDetail & obj )
+{
+ for ( const auto & el : obj )
+ str << el.second << endl;
+ return str;
+}
+
} // namespace rpm
} // namespace target
} // namespace zypp