libzypp: zypp/target/rpm/RpmDb.cc Source File

libzypp 17.36.6

RpmDb.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include "librpm.h"
13extern "C"
14{
15#include <rpm/rpmcli.h>
16#include <rpm/rpmlog.h>
17}
18#include <cstdlib>
19#include <cstdio>
20#include <ctime>
21
22#include <iostream>
23#include <fstream>
24#include <sstream>
25#include <list>
26#include <map>
27#include <set>
28#include <string>
29#include <utility>
30#include <vector>
31#include <algorithm>
32
33#include <zypp-core/base/StringV.h>
34#include <zypp/base/Logger.h>
35#include <zypp/base/String.h>
36#include <zypp/base/Gettext.h>
37#include <zypp/base/LocaleGuard.h>
38#include <zypp-core/base/DtorReset>
39
40#include <zypp/Date.h>
41#include <zypp/Pathname.h>
42#include <zypp/PathInfo.h>
43#include <zypp-common/PublicKey.h>
44#include <zypp-core/ui/ProgressData>
45
46#include <zypp/target/rpm/RpmDb.h>
47#include <zypp/target/rpm/RpmCallbacks.h>
48#include <zypp/target/RpmPostTransCollector.h>
49
50#include <zypp/HistoryLog.h>
51#include <zypp/target/rpm/librpmDb.h>
52#include <zypp/target/rpm/RpmException.h>
53#include <zypp/TmpPath.h>
54#include <zypp/KeyRing.h>
55#include <zypp-common/KeyManager.h>
56#include <zypp/ZYppFactory.h>
57#include <zypp/ZConfig.h>
58#include <zypp/base/IOTools.h>
59
60using std::endl;
61using namespace zypp::filesystem;
62
63#define WARNINGMAILPATH "/var/log/YaST2/"
64#define FILEFORBACKUPFILES "YaSTBackupModifiedFiles"
65#define MAXRPMMESSAGELINES 10000
66
67#define WORKAROUNDRPMPWDBUG
68
69#undef ZYPP_BASE_LOGGER_LOGGROUP
70#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb"
71
72namespace zypp
73{
74 namespace zypp_readonly_hack
75 {
76 bool IGotIt(); // in readonly-mode
77 }
78 namespace env
79 {
80 inline bool ZYPP_RPM_DEBUG()
81 {
82 static bool val = [](){
83 const char * env = getenv("ZYPP_RPM_DEBUG");
84 return( env && str::strToBool( env, true ) );
85 }();
86 return val;
87 }
88 } // namespace env
89namespace target
90{
91namespace rpm
92{
93 const callback::UserData::ContentType InstallResolvableReport::contentRpmout( "rpmout","installpkg" );
94 const callback::UserData::ContentType RemoveResolvableReport::contentRpmout( "rpmout","removepkg" );
95
96namespace
97{
98const char* quoteInFilename_m = "\'\"";
99inline std::string rpmQuoteFilename( const Pathname & path_r )
100{
101 std::string path( path_r.asString() );
102 for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m );
103 pos != std::string::npos;
104 pos = path.find_first_of( quoteInFilename_m, pos ) )
105 {
106 path.insert( pos, "\\" );
107 pos += 2; // skip '\\' and the quoted char.
108 }
109 return path;
110}
111
112
117 inline Pathname workaroundRpmPwdBug( Pathname path_r )
118 {
119#if defined(WORKAROUNDRPMPWDBUG)
120 if ( path_r.relative() )
121 {
122 // try to prepend cwd
123 AutoDispose<char*> cwd( ::get_current_dir_name(), ::free );
124 if ( cwd )
125 return Pathname( cwd ) / path_r;
126 WAR << "Can't get cwd!" << endl;
127 }
128#endif
129 return path_r; // no problem with absolute pathnames
130 }
131}
132
133 struct KeyRingSignalReceiver : callback::ReceiveReport<KeyRingSignals>
134{
135 KeyRingSignalReceiver(RpmDb &rpmdb) : _rpmdb(rpmdb) { connect(); }
136 KeyRingSignalReceiver(const KeyRingSignalReceiver &) = delete;
137 KeyRingSignalReceiver(KeyRingSignalReceiver &&) = delete;
138 KeyRingSignalReceiver &operator=(const KeyRingSignalReceiver &) = delete;
139 KeyRingSignalReceiver &operator=(KeyRingSignalReceiver &&) = delete;
140
141 ~KeyRingSignalReceiver() override
142 {
143 disconnect();
144 }
145
146 void trustedKeyAdded( const PublicKey &key ) override
147 {
148 MIL << "trusted key added to zypp Keyring. Importing..." << endl;
149 _rpmdb.importPubkey( key );
150 }
151
152 void trustedKeyRemoved( const PublicKey &key ) override
153 {
154 MIL << "Trusted key removed from zypp Keyring. Removing..." << endl;
155 _rpmdb.removePubkey( key );
156 }
157
158 RpmDb &_rpmdb;
159};
160
161 static shared_ptr<KeyRingSignalReceiver> sKeyRingReceiver;
162
163 unsigned diffFiles(const std::string& file1, const std::string& file2, std::string& out, int maxlines)
164{
165 const char* argv[] =
166 {
167 "diff",
168 "-u",
169 file1.c_str(),
170 file2.c_str(),
171 NULL
172 };
173 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
174
175 //if(!prog)
176 //return 2;
177
178 std::string line;
179 int count = 0;
180 for (line = prog.receiveLine(), count=0;
181 !line.empty();
182 line = prog.receiveLine(), count++ )
183 {
184 if (maxlines<0?true:count<maxlines)
185 out+=line;
186 }
187
188 return prog.close();
189}
190
192//
193// CLASS NAME : RpmDb
194//
196
197#define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); }
198
200
202//
203//
204// METHOD NAME : RpmDb::RpmDb
205// METHOD TYPE : Constructor
206//
207RpmDb::RpmDb()
208 : _backuppath ("/var/adm/backup")
209 , _packagebackups(false)
210{
211 process = 0;
212 exit_code = -1;
213 librpmDb::globalInit();
214 // Some rpm versions are patched not to abort installation if
215 // symlink creation failed.
216 setenv( "RPM_IgnoreFailedSymlinks", "1", 1 );
217 sKeyRingReceiver.reset(new KeyRingSignalReceiver(*this));
218}
219
221//
222//
223// METHOD NAME : RpmDb::~RpmDb
224// METHOD TYPE : Destructor
225//
226RpmDb::~RpmDb()
227{
228 MIL << "~RpmDb()" << endl;
229 closeDatabase();
230 delete process;
231 MIL << "~RpmDb() end" << endl;
232 sKeyRingReceiver.reset();
233}
234
236//
237//
238// METHOD NAME : RpmDb::dumpOn
239// METHOD TYPE : std::ostream &
240//
241std::ostream & RpmDb::dumpOn( std::ostream & str ) const
242{
243 return str << "RpmDb[" << dumpPath( _root, _dbPath ) << "]";
244}
245
247 RpmDb::db_const_iterator RpmDb::dbConstIterator() const
248{
249 if ( initialized() )
250 return db_const_iterator( root(), dbPath() );
251 return db_const_iterator();
252}
253
255//
256//
257// METHOD NAME : RpmDb::initDatabase
258// METHOD TYPE : PMError
259//
260 void RpmDb::initDatabase( Pathname root_r, bool doRebuild_r )
261{
263 // Check arguments
265 if ( root_r.empty() )
266 root_r = "/";
267
268 const Pathname & dbPath_r { librpmDb::suggestedDbPath( root_r ) }; // also asserts root_r is absolute
269
270 // The rpmdb compat symlink.
271 // Required at least until rpmdb2solv takes a dppath argument.
272 // Otherwise it creates a db at "/var/lib/rpm".
273 if ( dbPath_r != "/var/lib/rpm" && ! PathInfo( root_r/"/var/lib/rpm" ).isExist() )
274 {
275 WAR << "Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
276 filesystem::assert_dir( root_r/"/var/lib" );
277 filesystem::symlink( "../../"/dbPath_r, root_r/"/var/lib/rpm" );
278 }
279
281 // Check whether already initialized
283 if ( initialized() )
284 {
285 // Just check for a changing root because the librpmDb::suggestedDbPath
286 // may indeed change: rpm %post moving the db from /var/lib/rpm
287 // to /usr/lib/sysimage/rpm. We continue to use the old dbpath
288 // (via the compat symlink) until a re-init.
289 if ( root_r == _root ) {
290 MIL << "Calling initDatabase: already initialized at " << dumpPath( _root, _dbPath ) << endl;
291 return;
292 }
293 else
294 ZYPP_THROW(RpmDbAlreadyOpenException(_root, _dbPath, root_r, dbPath_r));
295 }
296
297 MIL << "Calling initDatabase: " << dumpPath( root_r, dbPath_r )
298 << ( doRebuild_r ? " (rebuilddb)" : "" ) << endl;
299
301 // init database
303 // creates dbdir and empty rpm database if not present
304 // or throws RpmException
305 librpmDb::dbOpenCreate( root_r, dbPath_r );
306 _root = root_r;
307 _dbPath = dbPath_r;
308
309 if ( doRebuild_r )
310 rebuildDatabase();
311
312 MIL << "Synchronizing keys with zypp keyring" << endl;
313 syncTrustedKeys();
314
315#if 0 // if this is needed we need to forcefully close the db of running db_const_iterators
316 // Close the database in case any write acces (create/convert)
317 // happened during init. This should drop any lock acquired
318 // by librpm. On demand it will be reopened readonly and should
319 // not hold any lock.
320 librpmDb::dbRelease( true );
321#endif
322 MIL << "InitDatabase: " << *this << endl;
323}
324
326//
327//
328// METHOD NAME : RpmDb::closeDatabase
329// METHOD TYPE : PMError
330//
331 void RpmDb::closeDatabase()
332{
333 if ( ! initialized() )
334 {
335 return;
336 }
337
338 // NOTE: There are no persistent librpmDb handles to invalidate.
339 // Running db_const_iterator may keep the DB physically open until they
340 // go out of scope too.
341 MIL << "closeDatabase: " << *this << endl;
342 _root = _dbPath = Pathname();
343}
344
346//
347//
348// METHOD NAME : RpmDb::rebuildDatabase
349// METHOD TYPE : PMError
350//
351 void RpmDb::rebuildDatabase()
352{
353 callback::SendReport<RebuildDBReport> report;
354
355 report->start( root() + dbPath() );
356
357 try
358 {
359 doRebuildDatabase(report);
360 }
361 catch (RpmException & excpt_r)
362 {
363 report->finish(root() + dbPath(), RebuildDBReport::FAILED, excpt_r.asUserHistory());
364 ZYPP_RETHROW(excpt_r);
365 }
366 report->finish(root() + dbPath(), RebuildDBReport::NO_ERROR, "");
367}
368
369 void RpmDb::doRebuildDatabase(callback::SendReport<RebuildDBReport> & report)
370{
371 FAILIFNOTINITIALIZED;
372 MIL << "RpmDb::rebuildDatabase" << *this << endl;
373
374 const Pathname mydbpath { root()/dbPath() }; // the configured path used in reports
375 {
376 // For --rebuilddb take care we're using the real db directory
377 // and not a symlink. Otherwise rpm will rename the symlink and
378 // replace it with a real directory containing the converted db.
379 DtorReset guardRoot { _root };
380 DtorReset guardDbPath{ _dbPath };
381 _root = "/";
382 _dbPath = filesystem::expandlink( mydbpath );
383
384 // run rpm
385 RpmArgVec opts;
386 opts.push_back("--rebuilddb");
387 opts.push_back("-vv");
388 run_rpm (opts, ExternalProgram::Stderr_To_Stdout);
389 }
390
391 // generate and report progress
392 ProgressData tics;
393 {
394 ProgressData::value_type hdrTotal = 0;
395 for ( auto it = dbConstIterator(); *it; ++it, ++hdrTotal )
396 {;}
397 tics.range( hdrTotal );
398 }
399 tics.sendTo( [&report,&mydbpath]( const ProgressData & tics_r ) -> bool {
400 return report->progress( tics_r.reportValue(), mydbpath );
401 } );
402 tics.toMin();
403
404 std::string line;
405 std::string errmsg;
406 while ( systemReadLine( line ) )
407 {
408 static const std::string debugPrefix { "D:" };
409 static const std::string progressPrefix { "D: read h#" };
410 static const std::string ignoreSuffix { "digest: OK" };
411
412 if ( ! str::startsWith( line, debugPrefix ) )
413 {
414 if ( ! str::endsWith( line, ignoreSuffix ) )
415 {
416 errmsg += line;
417 errmsg += '\n';
418 WAR << line << endl;
419 }
420 }
421 else if ( str::startsWith( line, progressPrefix ) )
422 {
423 if ( ! tics.incr() )
424 {
425 WAR << "User requested abort." << endl;
426 systemKill();
427 }
428 }
429 }
430
431 if ( systemStatus() != 0 )
432 {
433 //TranslatorExplanation after semicolon is error message
434 ZYPP_THROW(RpmSubprocessException(std::string(_("RPM failed: ")) + (errmsg.empty() ? error_message: errmsg) ) );
435 }
436 else
437 {
438 tics.toMax();
439 }
440}
441
443namespace
444{
449 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
450 {
452 // Remember latest release and where it ocurred
453 struct Key
454 {
455 Key()
456 : _inRpmKeys( nullptr )
457 , _inZyppKeys( nullptr )
458 {}
459
460 void updateIf( const Edition & rpmKey_r )
461 {
462 std::string keyRelease( rpmKey_r.release() );
463 int comp = _release.compare( keyRelease );
464 if ( comp < 0 )
465 {
466 // update to newer release
467 _release.swap( keyRelease );
468 _inRpmKeys = &rpmKey_r;
469 _inZyppKeys = nullptr;
470 if ( !keyRelease.empty() )
471 DBG << "Old key in Z: gpg-pubkey-" << rpmKey_r.version() << "-" << keyRelease << endl;
472 }
473 else if ( comp == 0 )
474 {
475 // stay with this release
476 if ( ! _inRpmKeys )
477 _inRpmKeys = &rpmKey_r;
478 }
479 // else: this is an old release
480 else
481 DBG << "Old key in R: gpg-pubkey-" << rpmKey_r.version() << "-" << keyRelease << endl;
482 }
483
484 void updateIf( const PublicKeyData & zyppKey_r )
485 {
486 std::string keyRelease( zyppKey_r.gpgPubkeyRelease() );
487 int comp = _release.compare( keyRelease );
488 if ( comp < 0 )
489 {
490 // update to newer release
491 _release.swap( keyRelease );
492 _inRpmKeys = nullptr;
493 _inZyppKeys = &zyppKey_r;
494 if ( !keyRelease.empty() )
495 DBG << "Old key in R: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << "-" << keyRelease << endl;
496 }
497 else if ( comp == 0 )
498 {
499 // stay with this release
500 if ( ! _inZyppKeys )
501 _inZyppKeys = &zyppKey_r;
502 }
503 // else: this is an old release
504 else
505 DBG << "Old key in Z: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << "-" << keyRelease << endl;
506 }
507
508 std::string _release;
509 const Edition * _inRpmKeys;
510 const PublicKeyData * _inZyppKeys;
511 };
513
514 // collect keys by ID(version) and latest creation(release)
515 std::map<std::string,Key> _keymap;
516
517 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
518 {
519 _keymap[(*it).version()].updateIf( *it );
520 }
521
522 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
523 {
524 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
525 }
526
527 // compute missing keys
528 std::set<Edition> rpmKeys;
529 std::list<PublicKeyData> zyppKeys;
530 for_( it, _keymap.begin(), _keymap.end() )
531 {
532 DBG << "gpg-pubkey-" << (*it).first << "-" << (*it).second._release << " "
533 << ( (*it).second._inRpmKeys ? "R" : "_" )
534 << ( (*it).second._inZyppKeys ? "Z" : "_" ) << endl;
535 if ( ! (*it).second._inRpmKeys )
536 {
537 zyppKeys.push_back( *(*it).second._inZyppKeys );
538 }
539 if ( ! (*it).second._inZyppKeys )
540 {
541 rpmKeys.insert( *(*it).second._inRpmKeys );
542 }
543 }
544 rpmKeys_r.swap( rpmKeys );
545 zyppKeys_r.swap( zyppKeys );
546 }
547} // namespace
549
550 void RpmDb::syncTrustedKeys( SyncTrustedKeyBits mode_r )
551{
552 MIL << "Going to sync trusted keys..." << endl;
553 std::set<Edition> rpmKeys( pubkeyEditions() );
554 std::list<PublicKeyData> zyppKeys( getZYpp()->keyRing()->trustedPublicKeyData() );
555
556 if ( ! ( mode_r & SYNC_FROM_KEYRING ) )
557 {
558 // bsc#1064380: We relief PK from removing excess keys in the zypp keyring
559 // when re-acquiring the zyppp lock. For now we remove all excess keys.
560 // TODO: Once we can safely assume that all PK versions are updated we
561 // can think about re-importing newer key versions found in the zypp keyring and
562 // removing only excess ones (but case is not very likely). Unfixed PK versions
563 // however will remove the newer version found in the zypp keyring and by doing
564 // this, the key here will be removed via callback as well (keys are deleted
565 // via gpg id, regardless of the edition).
566 MIL << "Removing excess keys in zypp trusted keyring" << std::endl;
567 // Temporarily disconnect to prevent the attempt to pass back the delete request.
568 callback::TempConnect<KeyRingSignals> tempDisconnect;
569 bool dirty = false;
570 for ( const PublicKeyData & keyData : zyppKeys )
571 {
572 if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) )
573 {
574 DBG << "Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl;
575 getZYpp()->keyRing()->deleteKey( keyData.id(), /*trusted*/true );
576 if ( !dirty ) dirty = true;
577 }
578 }
579 if ( dirty )
580 zyppKeys = getZYpp()->keyRing()->trustedPublicKeyData();
581 }
582
583 computeKeyRingSync( rpmKeys, zyppKeys );
584 MIL << (mode_r & SYNC_TO_KEYRING ? "" : "(skip) ") << "Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
585 MIL << (mode_r & SYNC_FROM_KEYRING ? "" : "(skip) ") << "Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
586
588 if ( (mode_r & SYNC_TO_KEYRING) && ! rpmKeys.empty() )
589 {
590 // export to zypp keyring
591 MIL << "Exporting rpm keyring into zypp trusted keyring" <<endl;
592 // Temporarily disconnect to prevent the attempt to re-import the exported keys.
593 callback::TempConnect<KeyRingSignals> tempDisconnect;
594 auto keepDbOpen = dbConstIterator(); // just to keep a ref.
595
596 TmpFile tmpfile( getZYpp()->tmpPath() );
597 {
598 std::ofstream tmpos( tmpfile.path().c_str() );
599 for_( it, rpmKeys.begin(), rpmKeys.end() )
600 {
601 // we export the rpm key into a file
602 RpmHeader::constPtr result;
603 getData( "gpg-pubkey", *it, result );
604 tmpos << result->tag_description() << endl;
605 }
606 }
607 try
608 {
609 getZYpp()->keyRing()->multiKeyImport( tmpfile.path(), true /*trusted*/);
610 // bsc#1096217: Try to spot and report legacy V3 keys found in the rpm database.
611 // Modern rpm does not import those keys, but when migrating a pre SLE12 system
612 // we may find them. rpm>4.13 even complains on sderr if sucha key is present.
613 std::set<Edition> missingKeys;
614 for ( const Edition & key : rpmKeys )
615 {
616 if ( getZYpp()->keyRing()->isKeyTrusted( key.version() ) ) // key.version is the gpgkeys short ID
617 continue;
618 ERR << "Could not import key:" << str::Format("gpg-pubkey-%s") % key << " into zypp keyring (V3 key?)" << endl;
619 missingKeys.insert( key );
620 }
621 if ( ! missingKeys.empty() )
622 callback::SendReport<KeyRingReport>()->reportNonImportedKeys(missingKeys);
623 }
624 catch ( const Exception & excpt )
625 {
626 ZYPP_CAUGHT( excpt );
627 ERR << "Could not import keys into zypp keyring: " << endl;
628 }
629 }
630
632 if ( (mode_r & SYNC_FROM_KEYRING) && ! zyppKeys.empty() )
633 {
634 // import from zypp keyring
635 MIL << "Importing zypp trusted keyring" << std::endl;
636 for_( it, zyppKeys.begin(), zyppKeys.end() )
637 {
638 try
639 {
640 importPubkey( getZYpp()->keyRing()->exportTrustedPublicKey( *it ) );
641 }
642 catch ( const RpmException & exp )
643 {
644 ZYPP_CAUGHT( exp );
645 }
646 }
647 }
648 MIL << "Trusted keys synced." << endl;
649}
650
651 void RpmDb::importZyppKeyRingTrustedKeys()
652{ syncTrustedKeys( SYNC_FROM_KEYRING ); }
653
654 void RpmDb::exportTrustedKeysInZyppKeyRing()
655{ syncTrustedKeys( SYNC_TO_KEYRING ); }
656
658//
659//
660// METHOD NAME : RpmDb::importPubkey
661// METHOD TYPE : PMError
662//
663 void RpmDb::importPubkey( const PublicKey & pubkey_r )
664{
665 FAILIFNOTINITIALIZED;
666
667 // bnc#828672: On the fly key import in READONLY
668 if ( zypp_readonly_hack::IGotIt() )
669 {
670 WAR << "Key " << pubkey_r << " can not be imported. (READONLY MODE)" << endl;
671 return;
672 }
673
674 // check if the key is already in the rpm database
675 Edition keyEd( pubkey_r.gpgPubkeyVersion(), pubkey_r.gpgPubkeyRelease() );
676 std::set<Edition> rpmKeys = pubkeyEditions();
677 bool hasOldkeys = false;
678
679 for_( it, rpmKeys.begin(), rpmKeys.end() )
680 {
681 // bsc#1008325: Keys using subkeys for signing don't get a higher release
682 // if new subkeys are added, because the primary key remains unchanged.
683 // For now always re-import keys with subkeys. Here we don't want to export the
684 // keys in the rpm database to check whether the subkeys are the same. The calling
685 // code should take care, we don't re-import the same kesy over and over again.
686 if ( keyEd == *it && !pubkey_r.hasSubkeys() ) // quick test (Edition is IdStringType!)
687 {
688 MIL << "Key " << pubkey_r << " is already in the rpm trusted keyring. (skip import)" << endl;
689 return;
690 }
691
692 if ( keyEd.version() != (*it).version() )
693 continue; // different key ID (version)
694
695 if ( keyEd.release() < (*it).release() )
696 {
697 MIL << "Key " << pubkey_r << " is older than one in the rpm trusted keyring. (skip import)" << endl;
698 return;
699 }
700 else
701 {
702 hasOldkeys = true;
703 }
704 }
705 MIL << "Key " << pubkey_r << " will be imported into the rpm trusted keyring." << (hasOldkeys?"(update)":"(new)") << endl;
706
707 if ( hasOldkeys )
708 {
709 // We must explicitly delete old key IDs first (all releases,
710 // that's why we don't call removePubkey here).
711 std::string keyName( "gpg-pubkey-" + keyEd.version() );
712 RpmArgVec opts;
713 opts.push_back ( "-e" );
714 opts.push_back ( "--allmatches" );
715 opts.push_back ( "--" );
716 opts.push_back ( keyName.c_str() );
717 run_rpm( opts, ExternalProgram::Stderr_To_Stdout );
718
719 std::string line;
720 while ( systemReadLine( line ) )
721 {
722 ( str::startsWith( line, "error:" ) ? WAR : DBG ) << line << endl;
723 }
724
725 if ( systemStatus() != 0 )
726 {
727 ERR << "Failed to remove key " << pubkey_r << " from RPM trusted keyring (ignored)" << endl;
728 }
729 else
730 {
731 MIL << "Key " << pubkey_r << " has been removed from RPM trusted keyring" << endl;
732 }
733 }
734
735 // import the new key
736 RpmArgVec opts;
737 opts.push_back ( "--import" );
738 opts.push_back ( "--" );
739 std::string pubkeypath( pubkey_r.path().asString() );
740 opts.push_back ( pubkeypath.c_str() );
741 run_rpm( opts, ExternalProgram::Stderr_To_Stdout );
742
743 std::string line;
744 std::vector<std::string> excplines;
745 while ( systemReadLine( line ) )
746 {
747 if ( str::startsWith( line, "error:" ) )
748 {
749 WAR << line << endl;
750 excplines.push_back( std::move(line) );
751 }
752 else
753 DBG << line << endl;
754 }
755
756 if ( systemStatus() != 0 )
757 {
758 // Translator: %1% is a gpg public key
759 RpmSubprocessException excp( str::Format(_("Failed to import public key %1%") ) % pubkey_r.asString() );
760 excp.moveToHistory( excplines );
761 excp.addHistory( std::move(error_message) );
762 ZYPP_THROW( excp );
763 }
764 else
765 {
766 MIL << "Key " << pubkey_r << " imported in rpm trusted keyring." << endl;
767 }
768}
769
771//
772//
773// METHOD NAME : RpmDb::removePubkey
774// METHOD TYPE : PMError
775//
776 void RpmDb::removePubkey( const PublicKey & pubkey_r )
777{
778 FAILIFNOTINITIALIZED;
779
780 // check if the key is in the rpm database and just
781 // return if it does not.
782 std::set<Edition> rpm_keys = pubkeyEditions();
783 std::set<Edition>::const_iterator found_edition = rpm_keys.end();
784 std::string pubkeyVersion( pubkey_r.gpgPubkeyVersion() );
785
786 for_( it, rpm_keys.begin(), rpm_keys.end() )
787 {
788 if ( (*it).version() == pubkeyVersion )
789 {
790 found_edition = it;
791 break;
792 }
793 }
794
795 // the key does not exist, cannot be removed
796 if (found_edition == rpm_keys.end())
797 {
798 WAR << "Key " << pubkey_r.id() << " is not in rpm db" << endl;
799 return;
800 }
801
802 std::string rpm_name("gpg-pubkey-" + found_edition->asString());
803
804 RpmArgVec opts;
805 opts.push_back ( "-e" );
806 opts.push_back ( "--" );
807 opts.push_back ( rpm_name.c_str() );
808 run_rpm( opts, ExternalProgram::Stderr_To_Stdout );
809
810 std::string line;
811 std::vector<std::string> excplines;
812 while ( systemReadLine( line ) )
813 {
814 if ( str::startsWith( line, "error:" ) )
815 {
816 WAR << line << endl;
817 excplines.push_back( std::move(line) );
818 }
819 else
820 DBG << line << endl;
821 }
822
823 if ( systemStatus() != 0 )
824 {
825 // Translator: %1% is a gpg public key
826 RpmSubprocessException excp( str::Format(_("Failed to remove public key %1%") ) % pubkey_r.asString() );
827 excp.moveToHistory( excplines );
828 excp.addHistory( std::move(error_message) );
829 ZYPP_THROW( excp );
830 }
831 else
832 {
833 MIL << "Key " << pubkey_r << " has been removed from RPM trusted keyring" << endl;
834 }
835}
836
838//
839//
840// METHOD NAME : RpmDb::pubkeys
841// METHOD TYPE : std::set<Edition>
842//
843std::list<PublicKey> RpmDb::pubkeys() const
844{
845 std::list<PublicKey> ret;
846
847 auto it = dbConstIterator();
848 for ( it.findByName( "gpg-pubkey" ); *it; ++it )
849 {
850 Edition edition = it->tag_edition();
851 if (edition != Edition::noedition)
852 {
853 // we export the rpm key into a file
854 RpmHeader::constPtr result;
855 getData( "gpg-pubkey", edition, result );
856 TmpFile file(getZYpp()->tmpPath());
857 std::ofstream os;
858 try
859 {
860 os.open(file.path().asString().c_str());
861 // dump rpm key into the tmp file
862 os << result->tag_description();
863 //MIL << "-----------------------------------------------" << endl;
864 //MIL << result->tag_description() <<endl;
865 //MIL << "-----------------------------------------------" << endl;
866 os.close();
867 // read the public key from the dumped file
868 PublicKey key(file);
869 ret.push_back(key);
870 }
871 catch ( std::exception & e )
872 {
873 ERR << "Could not dump key " << edition.asString() << " in tmp file " << file.path() << endl;
874 // just ignore the key
875 }
876 }
877 }
878 return ret;
879}
880
881std::set<Edition> RpmDb::pubkeyEditions() const
882 {
883 std::set<Edition> ret;
884
885 auto it = dbConstIterator();
886 for ( it.findByName( "gpg-pubkey" ); *it; ++it )
887 {
888 Edition edition = it->tag_edition();
889 if (edition != Edition::noedition)
890 ret.insert( edition );
891 }
892 return ret;
893 }
894
895
897//
898//
899// METHOD NAME : RpmDb::fileList
900// METHOD TYPE : bool
901//
902// DESCRIPTION :
903//
904std::list<FileInfo>
905RpmDb::fileList( const std::string & name_r, const Edition & edition_r ) const
906{
907 std::list<FileInfo> result;
908
909 auto it = dbConstIterator();
910 bool found = false;
911 if (edition_r == Edition::noedition)
912 {
913 found = it.findPackage( name_r );
914 }
915 else
916 {
917 found = it.findPackage( name_r, edition_r );
918 }
919 if (!found)
920 return result;
921
922 return result;
923}
924
925
927//
928//
929// METHOD NAME : RpmDb::hasFile
930// METHOD TYPE : bool
931//
932// DESCRIPTION :
933//
934 bool RpmDb::hasFile( const std::string & file_r, const std::string & name_r ) const
935{
936 auto it = dbConstIterator();
937 bool res = false;
938 do
939 {
940 res = it.findByFile( file_r );
941 if (!res) break;
942 if (!name_r.empty())
943 {
944 res = (it->tag_name() == name_r);
945 }
946 ++it;
947 }
948 while (res && *it);
949 return res;
950}
951
953//
954//
955// METHOD NAME : RpmDb::whoOwnsFile
956// METHOD TYPE : std::string
957//
958// DESCRIPTION :
959//
960std::string RpmDb::whoOwnsFile( const std::string & file_r) const
961{
962 auto it = dbConstIterator();
963 if (it.findByFile( file_r ))
964 {
965 return it->tag_name();
966 }
967 return "";
968}
969
971//
972//
973// METHOD NAME : RpmDb::hasProvides
974// METHOD TYPE : bool
975//
976// DESCRIPTION :
977//
978 bool RpmDb::hasProvides( const std::string & tag_r ) const
979{
980 auto it = dbConstIterator();
981 return it.findByProvides( tag_r );
982}
983
985//
986//
987// METHOD NAME : RpmDb::hasRequiredBy
988// METHOD TYPE : bool
989//
990// DESCRIPTION :
991//
992 bool RpmDb::hasRequiredBy( const std::string & tag_r ) const
993{
994 auto it = dbConstIterator();
995 return it.findByRequiredBy( tag_r );
996}
997
999//
1000//
1001// METHOD NAME : RpmDb::hasConflicts
1002// METHOD TYPE : bool
1003//
1004// DESCRIPTION :
1005//
1006 bool RpmDb::hasConflicts( const std::string & tag_r ) const
1007{
1008 auto it = dbConstIterator();
1009 return it.findByConflicts( tag_r );
1010}
1011
1013//
1014//
1015// METHOD NAME : RpmDb::hasPackage
1016// METHOD TYPE : bool
1017//
1018// DESCRIPTION :
1019//
1020 bool RpmDb::hasPackage( const std::string & name_r ) const
1021{
1022 auto it = dbConstIterator();
1023 return it.findPackage( name_r );
1024}
1025
1027//
1028//
1029// METHOD NAME : RpmDb::hasPackage
1030// METHOD TYPE : bool
1031//
1032// DESCRIPTION :
1033//
1034 bool RpmDb::hasPackage( const std::string & name_r, const Edition & ed_r ) const
1035{
1036 auto it = dbConstIterator();
1037 return it.findPackage( name_r, ed_r );
1038}
1039
1041//
1042//
1043// METHOD NAME : RpmDb::getData
1044// METHOD TYPE : PMError
1045//
1046// DESCRIPTION :
1047//
1048 void RpmDb::getData( const std::string & name_r,
1049 RpmHeader::constPtr & result_r ) const
1050{
1051 auto it = dbConstIterator();
1052 it.findPackage( name_r );
1053 result_r = *it;
1054#if 0 // if this is needed we need to forcefully close the db of running db_const_iterators
1055 if (it.dbError())
1056 ZYPP_THROW(*(it.dbError()));
1057#endif
1058}
1059
1061//
1062//
1063// METHOD NAME : RpmDb::getData
1064// METHOD TYPE : void
1065//
1066// DESCRIPTION :
1067//
1068 void RpmDb::getData( const std::string & name_r, const Edition & ed_r,
1069 RpmHeader::constPtr & result_r ) const
1070{
1071 auto it = dbConstIterator();
1072 it.findPackage( name_r, ed_r );
1073 result_r = *it;
1074#if 0 // if this is needed we need to forcefully close the db of running db_const_iterators
1075 if (it.dbError())
1076 ZYPP_THROW(*(it.dbError()));
1077#endif
1078}
1079
1081namespace
1082{
1083 struct RpmlogCapture : public std::vector<std::string>
1084 {
1085 RpmlogCapture()
1086 {
1087 rpmlogSetCallback( rpmLogCB, this );
1088 _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) );
1089 }
1090
1091 RpmlogCapture(const RpmlogCapture &) = delete;
1092 RpmlogCapture(RpmlogCapture &&) = delete;
1093 RpmlogCapture &operator=(const RpmlogCapture &) = delete;
1094 RpmlogCapture &operator=(RpmlogCapture &&) = delete;
1095
1096 ~RpmlogCapture() {
1097 rpmlogSetCallback( nullptr, nullptr );
1098 rpmlogSetMask( _oldMask );
1099 }
1100
1101 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1102 { return reinterpret_cast<RpmlogCapture*>(data_r)->rpmLog( rec_r ); }
1103
1104 int rpmLog( rpmlogRec rec_r )
1105 {
1106 std::string l { ::rpmlogRecMessage( rec_r ) }; // NL terminated line!
1107 l.pop_back(); // strip trailing NL
1108 push_back( std::move(l) );
1109 return 0;
1110 }
1111
1112 private:
1113 int _oldMask = 0;
1114 };
1115
1116 std::ostream & operator<<( std::ostream & str, const RpmlogCapture & obj )
1117 {
1118 char sep = '\0';
1119 for ( const auto & l : obj ) {
1120 if ( sep ) str << sep; else sep = '\n';
1121 str << l;
1122 }
1123 return str;
1124 }
1125
1126
1127 RpmDb::CheckPackageResult doCheckPackageSig( const Pathname & path_r, // rpm file to check
1128 const Pathname & root_r, // target root
1129 bool requireGPGSig_r, // whether no gpg signature is to be reported
1130 RpmDb::CheckPackageDetail & detail_r ) // detailed result
1131 {
1132 PathInfo file( path_r );
1133 if ( ! file.isFile() )
1134 {
1135 ERR << "Not a file: " << file << endl;
1136 return RpmDb::CHK_ERROR;
1137 }
1138
1139 FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" );
1140 if ( fd == 0 || ::Ferror(fd) )
1141 {
1142 ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl;
1143 if ( fd )
1144 ::Fclose( fd );
1145 return RpmDb::CHK_ERROR;
1146 }
1147 rpmts ts = ::rpmtsCreate();
1148 ::rpmtsSetRootDir( ts, root_r.c_str() );
1149 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1150#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP
1151 ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT );
1152#endif
1153
1154 RpmlogCapture vresult;
1155 LocaleGuard guard( LC_ALL, "C" ); // bsc#1076415: rpm log output is localized, but we need to parse it :(
1156 static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0, sizeof(rpmQVKArguments_s) ); return qva; })();
1157 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.basename().c_str() );
1158 guard.restore();
1159
1160 ts = rpmtsFree(ts);
1161 ::Fclose( fd );
1162
1163 // Check the individual signature/disgest results:
1164
1165 // To.map back known result strings to enum, everything else is CHK_ERROR.
1166 typedef std::map<std::string_view,RpmDb::CheckPackageResult> ResultMap;
1167 static const ResultMap resultMap {
1168 { "OK", RpmDb::CHK_OK },
1169 { "NOKEY", RpmDb::CHK_NOKEY },
1170 { "BAD", RpmDb::CHK_FAIL },
1171 { "UNKNOWN", RpmDb::CHK_NOTFOUND },
1172 { "NOTRUSTED", RpmDb::CHK_NOTTRUSTED },
1173 { "NOTFOUND", RpmDb::CHK_NOTFOUND },
1174 };
1175 auto getresult = []( const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1176 auto it = resultMap.find( key );
1177 return it != resultMap.end() ? it->second : RpmDb::CHK_ERROR;
1178 };
1179
1180 // To track the signature states we saw.
1181 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1182
1183 // To track the kind off sigs we saw.
1184 enum Saw {
1185 SawNone = 0,
1186 SawHeaderSig = (1 << 0), // Header V3 RSA/SHA256 Signature, key ID 3dbdc284: OK
1187 SawHeaderDigest = (1 << 1), // Header SHA1 digest: OK (a60386347863affefef484ff1f26c889373eb094)
1188 SawPayloadDigest = (1 << 2), // Payload SHA256 digest: OK
1189 SawSig = (1 << 3), // V3 RSA/SHA256 Signature, key ID 3dbdc284: OK
1190 SawDigest = (1 << 4), // MD5 digest: OK (fd5259fe677a406951dcb2e9d08c4dcc)
1191 };
1192 unsigned saw = SawNone;
1193
1194 static const str::regex rx( "^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1195 str::smatch what;
1196 for ( const std::string & line : vresult )
1197 {
1198 if ( line[0] != ' ' ) // result lines are indented
1199 continue;
1200
1201 RpmDb::CheckPackageResult lineres = RpmDb::CHK_ERROR;
1202 if ( str::regex_match( line, what, rx ) ) {
1203
1204 lineres = getresult( resultMap, what[3] );
1205 if ( lineres == RpmDb::CHK_NOTFOUND )
1206 continue; // just collect details for signatures found (#229)
1207
1208 if ( what[1][0] == 'H' ) {
1209 saw |= ( what[2][0] == 'S' ? SawHeaderSig :SawHeaderDigest );
1210 }
1211 else if ( what[1][0] == 'P' ) {
1212 if ( what[2][0] == 'd' ) saw |= SawPayloadDigest;
1213 }
1214 else {
1215 saw |= ( what[2][0] == 'S' ? SawSig : SawDigest );
1216 }
1217 }
1218
1219 ++count[lineres];
1220 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, line ) );
1221 }
1222
1223 // Now combine the overall result:
1224 RpmDb::CheckPackageResult ret = ( res ? RpmDb::CHK_ERROR : RpmDb::CHK_OK );
1225
1226 if ( count[RpmDb::CHK_FAIL] )
1227 ret = RpmDb::CHK_FAIL;
1228
1229 else if ( count[RpmDb::CHK_NOTFOUND] )
1230 ret = RpmDb::CHK_NOTFOUND;
1231
1232 else if ( count[RpmDb::CHK_NOKEY] )
1233 ret = RpmDb::CHK_NOKEY;
1234
1235 else if ( count[RpmDb::CHK_NOTTRUSTED] )
1236 ret = RpmDb::CHK_NOTTRUSTED;
1237
1238 else if ( ret == RpmDb::CHK_OK ) {
1239 // Everything is OK, so check whether it's sufficient.
1240 // bsc#1184501: To count as signed the package needs a header signature
1241 // and either a payload digest (secured by the header sig) or a content signature.
1242 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1243 if ( not isSigned ) {
1244 std::string message { " " };
1245 if ( not (saw & SawHeaderSig) )
1246 message += _("Package header is not signed!");
1247 else
1248 message += _("Package payload is not signed!");
1249
1250 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( RpmDb::CHK_NOSIG, std::move(message) ) );
1251 if ( requireGPGSig_r )
1252 ret = RpmDb::CHK_NOSIG;
1253 }
1254 }
1255
1256 if ( ret != RpmDb::CHK_OK )
1257 {
1258 // In case of an error line results may be reported to the user. In case rpm printed
1259 // only 8byte key IDs to stdout we try to get longer IDs from the header.
1260 bool didReadHeader = false;
1261 std::unordered_map< std::string, std::string> fprs;
1262
1263 // we replace the data only if the key IDs are actually only 8 bytes
1264 str::regex rxexpr( "key ID ([a-fA-F0-9]{8}):" );
1265 for ( auto &detail : detail_r ) {
1266 auto &line = detail.second;
1267 str::smatch what;
1268 if ( str::regex_match( line, what, rxexpr ) ) {
1269
1270 if ( !didReadHeader ) {
1271 didReadHeader = true;
1272
1273 // Get signature info from the package header, RPM always prints only the 8 byte ID
1274 auto header = RpmHeader::readPackage( path_r, RpmHeader::NOVERIFY );
1275 if ( header ) {
1276 auto keyMgr = zypp::KeyManagerCtx::createForOpenPGP();
1277 const auto &addFprs = [&]( auto tag ){
1278 const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) );
1279 for ( const auto &id : list1 ) {
1280 if ( id.size() <= 8 )
1281 continue;
1282
1283 const auto &lowerId = str::toLower( id );
1284 fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) );
1285 }
1286 };
1287
1288 addFprs( RPMTAG_SIGGPG );
1289 addFprs( RPMTAG_SIGPGP );
1290 addFprs( RPMTAG_RSAHEADER );
1291 addFprs( RPMTAG_DSAHEADER );
1292
1293 } else {
1294 ERR << "Failed to read package signatures." << std::endl;
1295 }
1296 }
1297
1298 // if we have no keys we can substitute we can leave the loop right away
1299 if ( !fprs.size() )
1300 break;
1301
1302 {
1303 // replace the short key ID with the long ones parsed from the header
1304 const auto &keyId = str::toLower( what[1] );
1305 if ( const auto &i = fprs.find( keyId ); i != fprs.end() ) {
1306 str::replaceAll( line, keyId, i->second );
1307 }
1308 }
1309 }
1310 }
1311
1312 WAR << path_r << " (" << requireGPGSig_r << " -> " << ret << ")" << endl;
1313 WAR << vresult << endl;
1314 }
1315 else
1316 DBG << path_r << " [0-Signature is OK]" << endl;
1317 return ret;
1318 }
1319
1320} // namespace
1322//
1323// METHOD NAME : RpmDb::checkPackage
1324// METHOD TYPE : RpmDb::CheckPackageResult
1325//
1326 RpmDb::CheckPackageResult RpmDb::checkPackage( const Pathname & path_r, CheckPackageDetail & detail_r )
1327{ return doCheckPackageSig( path_r, root(), false/*requireGPGSig_r*/, detail_r ); }
1328
1329 RpmDb::CheckPackageResult RpmDb::checkPackage( const Pathname & path_r )
1330{ CheckPackageDetail dummy; return checkPackage( path_r, dummy ); }
1331
1332 RpmDb::CheckPackageResult RpmDb::checkPackageSignature( const Pathname & path_r, RpmDb::CheckPackageDetail & detail_r )
1333{ return doCheckPackageSig( path_r, root(), true/*requireGPGSig_r*/, detail_r ); }
1334
1335
1336// determine changed files of installed package
1337bool
1338RpmDb::queryChangedFiles(FileList & fileList, const std::string& packageName)
1339{
1340 bool ok = true;
1341
1342 fileList.clear();
1343
1344 if ( ! initialized() ) return false;
1345
1346 RpmArgVec opts;
1347
1348 opts.push_back ("-V");
1349 opts.push_back ("--nodeps");
1350 opts.push_back ("--noscripts");
1351 opts.push_back ("--nomd5");
1352 opts.push_back ("--");
1353 opts.push_back (packageName.c_str());
1354
1355 run_rpm (opts, ExternalProgram::Discard_Stderr);
1356
1357 if ( process == NULL )
1358 return false;
1359
1360 /* from rpm manpage
1361 5 MD5 sum
1362 S File size
1363 L Symlink
1364 T Mtime
1365 D Device
1366 U User
1367 G Group
1368 M Mode (includes permissions and file type)
1369 */
1370
1371 std::string line;
1372 while (systemReadLine(line))
1373 {
1374 if (line.length() > 12 &&
1375 (line[0] == 'S' || line[0] == 's' ||
1376 (line[0] == '.' && line[7] == 'T')))
1377 {
1378 // file has been changed
1379 std::string filename;
1380
1381 filename.assign(line, 11, line.length() - 11);
1382 fileList.insert(filename);
1383 }
1384 }
1385
1386 systemStatus();
1387 // exit code ignored, rpm returns 1 no matter if package is installed or
1388 // not
1389
1390 return ok;
1391}
1392
1393
1394/****************************************************************/
1395/* private member-functions */
1396/****************************************************************/
1397
1398/*--------------------------------------------------------------*/
1399/* Run rpm with the specified arguments, handling stderr */
1400/* as specified by disp */
1401/*--------------------------------------------------------------*/
1402void
1403RpmDb::run_rpm (const RpmArgVec& opts,
1404 ExternalProgram::Stderr_Disposition disp)
1405{
1406 if ( process )
1407 {
1408 delete process;
1409 process = NULL;
1410 }
1411 exit_code = -1;
1412
1413 if ( ! initialized() )
1414 {
1415 ZYPP_THROW(RpmDbNotOpenException());
1416 }
1417
1418 RpmArgVec args;
1419
1420 // always set root and dbpath
1421#if defined(WORKAROUNDRPMPWDBUG)
1422 args.push_back("#/"); // chdir to / to workaround bnc#819354
1423#endif
1424 args.push_back("rpm");
1425 args.push_back("--root");
1426 args.push_back(_root.asString().c_str());
1427 args.push_back("--dbpath");
1428 args.push_back(_dbPath.asString().c_str());
1429 if ( env::ZYPP_RPM_DEBUG() )
1430 args.push_back("-vv");
1431 const char* argv[args.size() + opts.size() + 1];
1432
1433 const char** p = argv;
1434 p = copy (args.begin (), args.end (), p);
1435 p = copy (opts.begin (), opts.end (), p);
1436 *p = 0;
1437
1438#if 0 // if this is needed we need to forcefully close the db of running db_const_iterators
1439 // Invalidate all outstanding database handles in case
1440 // the database gets modified.
1441 librpmDb::dbRelease( true );
1442#endif
1443
1444 // Launch the program with default locale
1445 process = new ExternalProgram(argv, disp, false, -1, true);
1446 return;
1447}
1448
1449/*--------------------------------------------------------------*/
1450/* Read a line from the rpm process */
1451/*--------------------------------------------------------------*/
1452 bool RpmDb::systemReadLine( std::string & line )
1453{
1454 line.erase();
1455
1456 if ( process == NULL )
1457 return false;
1458
1459 if ( process->inputFile() )
1460 {
1461 process->setBlocking( false );
1462 FILE * inputfile = process->inputFile();
1463 do {
1464 // Check every 5 seconds if the process is still running to prevent against
1465 // daemons launched in rpm %post that do not close their filedescriptors,
1466 // causing us to block for infinity. (bnc#174548)
1467 const auto &readResult = io::receiveUpto( inputfile, '\n', 5 * 1000, false );
1468 switch ( readResult.first ) {
1469 case io::ReceiveUpToResult::Timeout: {
1470 if ( !process->running() )
1471 return false;
1472
1473 // we might have received a partial line, lets not forget about it
1474 line += readResult.second;
1475 break;
1476 }
1477 case io::ReceiveUpToResult::Error:
1478 case io::ReceiveUpToResult::EndOfFile: {
1479 line += readResult.second;
1480 if ( line.size() && line.back() == '\n')
1481 line.pop_back();
1482 return line.size(); // in case of pending output
1483 }
1484 case io::ReceiveUpToResult::Success: {
1485 line += readResult.second;
1486
1487 if ( line.size() && line.back() == '\n')
1488 line.pop_back();
1489
1490 if ( env::ZYPP_RPM_DEBUG() )
1491 L_DBG("RPM_DEBUG") << line << endl;
1492 return true; // complete line
1493 }
1494 }
1495 } while( true );
1496 }
1497 return false;
1498}
1499
1500/*--------------------------------------------------------------*/
1501/* Return the exit status of the rpm process, closing the */
1502/* connection if not already done */
1503/*--------------------------------------------------------------*/
1504int
1505RpmDb::systemStatus()
1506{
1507 if ( process == NULL )
1508 return -1;
1509
1510 exit_code = process->close();
1511 if (exit_code == 0)
1512 error_message = "";
1513 else
1514 error_message = process->execError();
1515 process->kill();
1516 delete process;
1517 process = 0;
1518
1519 // DBG << "exit code " << exit_code << endl;
1520
1521 return exit_code;
1522}
1523
1524/*--------------------------------------------------------------*/
1525/* Forcably kill the rpm process */
1526/*--------------------------------------------------------------*/
1527void
1528RpmDb::systemKill()
1529{
1530 if (process) process->kill();
1531}
1532
1533
1534// generate diff mails for config files
1535 void RpmDb::processConfigFiles(const std::string& line, const std::string& name, const char* typemsg, const char* difffailmsg, const char* diffgenmsg)
1536{
1537 std::string msg = line.substr(9);
1538 std::string::size_type pos1 = std::string::npos;
1539 std::string::size_type pos2 = std::string::npos;
1540 std::string file1s, file2s;
1541 Pathname file1;
1542 Pathname file2;
1543
1544 pos1 = msg.find (typemsg);
1545 for (;;)
1546 {
1547 if ( pos1 == std::string::npos )
1548 break;
1549
1550 pos2 = pos1 + strlen (typemsg);
1551
1552 if (pos2 >= msg.length() )
1553 break;
1554
1555 file1 = msg.substr (0, pos1);
1556 file2 = msg.substr (pos2);
1557
1558 file1s = file1.asString();
1559 file2s = file2.asString();
1560
1561 if (!_root.empty() && _root != "/")
1562 {
1563 file1 = _root + file1;
1564 file2 = _root + file2;
1565 }
1566
1567 std::string out;
1568 int ret = diffFiles (file1.asString(), file2.asString(), out, 25);
1569 if (ret)
1570 {
1571 Pathname file = _root + WARNINGMAILPATH;
1572 if (filesystem::assert_dir(file) != 0)
1573 {
1574 ERR << "Could not create " << file.asString() << endl;
1575 break;
1576 }
1577 file += Date(Date::now()).form("config_diff_%Y_%m_%d.log");
1578 std::ofstream notify(file.asString().c_str(), std::ios::out|std::ios::app);
1579 if (!notify)
1580 {
1581 ERR << "Could not open " << file << endl;
1582 break;
1583 }
1584
1585 // Translator: %s = name of an rpm package. A list of diffs follows
1586 // this message.
1587 notify << str::form(_("Changed configuration files for %s:"), name.c_str()) << endl;
1588 if (ret>1)
1589 {
1590 ERR << "diff failed" << endl;
1591 notify << str::form(difffailmsg,
1592 file1s.c_str(), file2s.c_str()) << endl;
1593 }
1594 else
1595 {
1596 notify << str::form(diffgenmsg,
1597 file1s.c_str(), file2s.c_str()) << endl;
1598
1599 // remove root for the viewer's pleasure (#38240)
1600 if (!_root.empty() && _root != "/")
1601 {
1602 if (out.substr(0,4) == "--- ")
1603 {
1604 out.replace(4, file1.asString().length(), file1s);
1605 }
1606 std::string::size_type pos = out.find("\n+++ ");
1607 if (pos != std::string::npos)
1608 {
1609 out.replace(pos+5, file2.asString().length(), file2s);
1610 }
1611 }
1612 notify << out << endl;
1613 }
1614 notify.close();
1615 notify.open("/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1616 notify.close();
1617 }
1618 else
1619 {
1620 WAR << "rpm created " << file2 << " but it is not different from " << file2 << endl;
1621 }
1622 break;
1623 }
1624}
1625
1627//
1628// METHOD NAME : RpmDb::installPackage
1629//
1630 void RpmDb::installPackage( const Pathname & filename, RpmInstFlags flags )
1631{ installPackage( filename, flags, nullptr ); }
1632
1633 void RpmDb::installPackage( const Pathname & filename, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r )
1634{
1635 if ( postTransCollector_r && postTransCollector_r->hasPosttransScript( filename ) )
1636 flags |= rpm::RPMINST_NOPOSTTRANS; // Just set the flag here. In \ref doInstallPackage we collect what else is needed.
1637
1638 callback::SendReport<RpmInstallReport> report;
1639
1640 report->start(filename);
1641
1642 do
1643 try
1644 {
1645 doInstallPackage( filename, flags, postTransCollector_r, report );
1646 report->finish();
1647 break;
1648 }
1649 catch (RpmException & excpt_r)
1650 {
1651 RpmInstallReport::Action user = report->problem( excpt_r );
1652
1653 if ( user == RpmInstallReport::ABORT )
1654 {
1655 report->finish( excpt_r );
1656 ZYPP_RETHROW(excpt_r);
1657 }
1658 else if ( user == RpmInstallReport::IGNORE )
1659 {
1660 break;
1661 }
1662 }
1663 while (true);
1664}
1665
1666 void RpmDb::doInstallPackage( const Pathname & filename, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r, callback::SendReport<RpmInstallReport> & report )
1667{
1668 FAILIFNOTINITIALIZED;
1669 HistoryLog historylog;
1670
1671 MIL << "RpmDb::installPackage(" << filename << "," << flags << ")" << endl;
1672
1673 // backup
1674 if ( _packagebackups )
1675 {
1676 // FIXME report->progress( pd.init( -2, 100 ) ); // allow 1% for backup creation.
1677 if ( ! backupPackage( filename ) )
1678 {
1679 ERR << "backup of " << filename.asString() << " failed" << endl;
1680 }
1681 // FIXME status handling
1682 report->progress( 0 ); // allow 1% for backup creation.
1683 }
1684
1685 // run rpm
1686 RpmArgVec opts;
1687#if defined(WORKAROUNDDUMPPOSTTRANS_BUG_1216091)
1688 if ( postTransCollector_r && _root == "/" ) {
1689#else
1690 if ( postTransCollector_r ) {
1691#endif
1692 opts.push_back("--define"); // bsc#1041742: Attempt to delay %transfiletrigger(postun|in) execution iff rpm supports it.
1693 opts.push_back("_dump_posttrans 1"); // Old rpm ignores the --define, new rpm injects 'dump_posttrans:' lines to collect and execute later.
1694 }
1695 if (flags & RPMINST_NOUPGRADE)
1696 opts.push_back("-i");
1697 else
1698 opts.push_back("-U");
1699
1700 opts.push_back("--percent");
1701 opts.push_back("--noglob");
1702
1703 // ZConfig defines cross-arch installation
1704 if ( ! ZConfig::instance().systemArchitecture().compatibleWith( ZConfig::instance().defaultSystemArchitecture() ) )
1705 opts.push_back("--ignorearch");
1706
1707 if (flags & RPMINST_NODIGEST)
1708 opts.push_back("--nodigest");
1709 if (flags & RPMINST_NOSIGNATURE)
1710 opts.push_back("--nosignature");
1711 if (flags & RPMINST_EXCLUDEDOCS)
1712 opts.push_back ("--excludedocs");
1713 if (flags & RPMINST_NOSCRIPTS)
1714 opts.push_back ("--noscripts");
1715 if (flags & RPMINST_FORCE)
1716 opts.push_back ("--force");
1717 if (flags & RPMINST_NODEPS)
1718 opts.push_back ("--nodeps");
1719 if (flags & RPMINST_IGNORESIZE)
1720 opts.push_back ("--ignoresize");
1721 if (flags & RPMINST_JUSTDB)
1722 opts.push_back ("--justdb");
1723 if (flags & RPMINST_TEST)
1724 opts.push_back ("--test");
1725 if (flags & RPMINST_NOPOSTTRANS)
1726 opts.push_back ("--noposttrans");
1727
1728 opts.push_back("--");
1729
1730 // rpm requires additional quoting of special chars:
1731 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
1732 opts.push_back ( quotedFilename.c_str() );
1733 run_rpm( opts, ExternalProgram::Stderr_To_Stdout );
1734
1735 // forward additional rpm output via report;
1736 std::string line;
1737 unsigned lineno = 0;
1738 callback::UserData cmdout( InstallResolvableReport::contentRpmout );
1739 // Key "solvable" injected by RpmInstallPackageReceiver
1740 cmdout.set( "line", std::cref(line) );
1741 cmdout.set( "lineno", lineno );
1742
1743 // LEGACY: collect and forward additional rpm output in finish
1744 std::string rpmmsg;
1745 std::vector<std::string> configwarnings; // TODO: immediately process lines rather than collecting
1746 std::vector<std::string> runposttrans; // bsc#1041742: If rpm supports --runposttrans it injects 'dump_posttrans:' lines we do collect
1747
1748 while ( systemReadLine( line ) )
1749 {
1750 if ( str::startsWith( line, "%%" ) )
1751 {
1752 int percent = 0;
1753 sscanf( line.c_str() + 2, "%d", &percent );
1754 report->progress( percent );
1755 continue;
1756 }
1757 if ( str::hasPrefix( line, "dump_posttrans:" ) ) {
1758 runposttrans.push_back( line );
1759 continue;
1760 }
1761 ++lineno;
1762 cmdout.set( "lineno", lineno );
1763 report->report( cmdout );
1764
1765 if ( lineno >= MAXRPMMESSAGELINES ) {
1766 if ( line.find( " scriptlet failed, " ) == std::string::npos ) // always log %script errors
1767 continue;
1768 }
1769
1770 rpmmsg += line+'\n';
1771
1772 if ( str::startsWith( line, "warning:" ) )
1773 configwarnings.push_back(line);
1774 }
1775 if ( lineno >= MAXRPMMESSAGELINES )
1776 rpmmsg += "[truncated]\n";
1777
1778 int rpm_status = systemStatus();
1779 if ( postTransCollector_r && rpm_status == 0 ) {
1780 // Before doing anything else, handle any pending %posttrans script or dump_posttrans lines.
1781 postTransCollector_r->collectPosttransInfo( filename, runposttrans );
1782 }
1783
1784 // evaluate result
1785 for (std::vector<std::string>::iterator it = configwarnings.begin();
1786 it != configwarnings.end(); ++it)
1787 {
1788 processConfigFiles(*it, Pathname::basename(filename), " saved as ",
1789 // %s = filenames
1790 _("rpm saved %s as %s, but it was impossible to determine the difference"),
1791 // %s = filenames
1792 _("rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
1793 processConfigFiles(*it, Pathname::basename(filename), " created as ",
1794 // %s = filenames
1795 _("rpm created %s as %s, but it was impossible to determine the difference"),
1796 // %s = filenames
1797 _("rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
1798 }
1799
1800 if ( rpm_status != 0 )
1801 {
1802 historylog.comment(
1803 str::form("%s install failed", Pathname::basename(filename).c_str()),
1804 true /*timestamp*/);
1805 std::ostringstream sstr;
1806 sstr << "rpm output:" << endl << rpmmsg << endl;
1807 historylog.comment(sstr.str());
1808 // TranslatorExplanation the colon is followed by an error message
1809 auto excpt { RpmSubprocessException(_("RPM failed: ") + error_message ) };
1810 if ( not rpmmsg.empty() )
1811 excpt.addHistory( rpmmsg );
1812 ZYPP_THROW(excpt);
1813 }
1814 else if ( ! rpmmsg.empty() )
1815 {
1816 historylog.comment(
1817 str::form("%s installed ok", Pathname::basename(filename).c_str()),
1818 true /*timestamp*/);
1819 std::ostringstream sstr;
1820 sstr << "Additional rpm output:" << endl << rpmmsg << endl;
1821 historylog.comment(sstr.str());
1822
1823 // report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout)
1824 // TranslatorExplanation Text is followed by a ':' and the actual output.
1825 report->finishInfo(str::form( "%s:\n%s\n", _("Additional rpm output"), rpmmsg.c_str() ));
1826 }
1827}
1828
1830//
1831// METHOD NAME : RpmDb::removePackage
1832//
1833 void RpmDb::removePackage( Package::constPtr package, RpmInstFlags flags )
1834{ removePackage( std::move(package), flags, nullptr ); }
1835
1836 void RpmDb::removePackage( const std::string & name_r, RpmInstFlags flags )
1837{ removePackage( name_r, flags, nullptr ); }
1838
1839 void RpmDb::removePackage( const Package::constPtr& package, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r )
1840{ // 'rpm -e' does not like epochs
1841 removePackage( package->name()
1842 + "-" + package->edition().version()
1843 + "-" + package->edition().release()
1844 + "." + package->arch().asString(), flags, postTransCollector_r );
1845}
1846
1847 void RpmDb::removePackage( const std::string & name_r, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r )
1848{
1849 callback::SendReport<RpmRemoveReport> report;
1850
1851 report->start( name_r );
1852
1853 do
1854 try
1855 {
1856 doRemovePackage( name_r, flags, postTransCollector_r, report );
1857 report->finish();
1858 break;
1859 }
1860 catch (RpmException & excpt_r)
1861 {
1862 RpmRemoveReport::Action user = report->problem( excpt_r );
1863
1864 if ( user == RpmRemoveReport::ABORT )
1865 {
1866 report->finish( excpt_r );
1867 ZYPP_RETHROW(excpt_r);
1868 }
1869 else if ( user == RpmRemoveReport::IGNORE )
1870 {
1871 break;
1872 }
1873 }
1874 while (true);
1875}
1876
1877 void RpmDb::doRemovePackage( const std::string & name_r, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r, callback::SendReport<RpmRemoveReport> & report )
1878{
1879 FAILIFNOTINITIALIZED;
1880 HistoryLog historylog;
1881
1882 MIL << "RpmDb::doRemovePackage(" << name_r << "," << flags << ")" << endl;
1883
1884 // backup
1885 if ( _packagebackups )
1886 {
1887 // FIXME solve this status report somehow
1888 // report->progress( pd.init( -2, 100 ) ); // allow 1% for backup creation.
1889 if ( ! backupPackage( name_r ) )
1890 {
1891 ERR << "backup of " << name_r << " failed" << endl;
1892 }
1893 report->progress( 0 );
1894 }
1895 else
1896 {
1897 report->progress( 100 );
1898 }
1899
1900 // run rpm
1901 RpmArgVec opts;
1902#if defined(WORKAROUNDDUMPPOSTTRANS_BUG_1216091)
1903 if ( postTransCollector_r && _root == "/" ) {
1904#else
1905 if ( postTransCollector_r ) {
1906#endif
1907 opts.push_back("--define"); // bsc#1041742: Attempt to delay %transfiletrigger(postun|in) execution iff rpm supports it.
1908 opts.push_back("_dump_posttrans 1"); // Old rpm ignores the --define, new rpm injects 'dump_posttrans:' lines to collect and execute later.
1909 }
1910 opts.push_back("-e");
1911 opts.push_back("--allmatches");
1912
1913 if (flags & RPMINST_NOSCRIPTS)
1914 opts.push_back("--noscripts");
1915 if (flags & RPMINST_NODEPS)
1916 opts.push_back("--nodeps");
1917 if (flags & RPMINST_JUSTDB)
1918 opts.push_back("--justdb");
1919 if (flags & RPMINST_TEST)
1920 opts.push_back ("--test");
1921 if (flags & RPMINST_FORCE)
1922 {
1923 WAR << "IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
1924 }
1925
1926 opts.push_back("--");
1927 opts.push_back(name_r.c_str());
1928 run_rpm (opts, ExternalProgram::Stderr_To_Stdout);
1929
1930 // forward additional rpm output via report;
1931 std::string line;
1932 unsigned lineno = 0;
1933 callback::UserData cmdout( RemoveResolvableReport::contentRpmout );
1934 // Key "solvable" injected by RpmInstallPackageReceiver
1935 cmdout.set( "line", std::cref(line) );
1936 cmdout.set( "lineno", lineno );
1937
1938
1939 // LEGACY: collect and forward additional rpm output in finish
1940 std::string rpmmsg;
1941 std::vector<std::string> runposttrans; // bsc#1041742: If rpm supports --runposttrans it injects 'dump_posttrans:' lines we do collect
1942
1943 // got no progress from command, so we fake it:
1944 // 5 - command started
1945 // 50 - command completed
1946 // 100 if no error
1947 report->progress( 5 );
1948 while (systemReadLine(line))
1949 {
1950 if ( str::hasPrefix( line, "dump_posttrans:" ) ) {
1951 runposttrans.push_back( line );
1952 continue;
1953 }
1954 ++lineno;
1955 cmdout.set( "lineno", lineno );
1956 report->report( cmdout );
1957
1958 if ( lineno >= MAXRPMMESSAGELINES ) {
1959 if ( line.find( " scriptlet failed, " ) == std::string::npos ) // always log %script errors
1960 continue;
1961 }
1962 rpmmsg += line+'\n';
1963 }
1964 if ( lineno >= MAXRPMMESSAGELINES )
1965 rpmmsg += "[truncated]\n";
1966 report->progress( 50 );
1967 int rpm_status = systemStatus();
1968 if ( postTransCollector_r && rpm_status == 0 ) {
1969 // Before doing anything else, handle any pending %posttrans script or dump_posttrans lines.
1970 // 'remove' does not trigger %posttrans, but it may trigger %transfiletriggers.
1971 postTransCollector_r->collectPosttransInfo( runposttrans );
1972 }
1973
1974 if ( rpm_status != 0 )
1975 {
1976 historylog.comment(
1977 str::form("%s remove failed", name_r.c_str()), true /*timestamp*/);
1978 std::ostringstream sstr;
1979 sstr << "rpm output:" << endl << rpmmsg << endl;
1980 historylog.comment(sstr.str());
1981 // TranslatorExplanation the colon is followed by an error message
1982 auto excpt { RpmSubprocessException(_("RPM failed: ") + error_message ) };
1983 if ( not rpmmsg.empty() )
1984 excpt.addHistory( rpmmsg );
1985 ZYPP_THROW(excpt);
1986 }
1987 else if ( ! rpmmsg.empty() )
1988 {
1989 historylog.comment(
1990 str::form("%s removed ok", name_r.c_str()), true /*timestamp*/);
1991
1992 std::ostringstream sstr;
1993 sstr << "Additional rpm output:" << endl << rpmmsg << endl;
1994 historylog.comment(sstr.str());
1995
1996 // report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout)
1997 // TranslatorExplanation Text is followed by a ':' and the actual output.
1998 report->finishInfo(str::form( "%s:\n%s\n", _("Additional rpm output"), rpmmsg.c_str() ));
1999 }
2000}
2001
2003//
2004// METHOD NAME : RpmDb::runposttrans
2005//
2006 int RpmDb::runposttrans( const Pathname & filename_r, const std::function<void(const std::string&)>& output_r )
2007{
2008 FAILIFNOTINITIALIZED;
2009 HistoryLog historylog;
2010
2011 MIL << "RpmDb::runposttrans(" << filename_r << ")" << endl;
2012
2013 RpmArgVec opts;
2014 opts.push_back("-vv"); // want vverbose output to see scriptlet execution in the log
2015 opts.push_back("--runposttrans");
2016 opts.push_back(filename_r.c_str());
2017 run_rpm (opts, ExternalProgram::Stderr_To_Stdout);
2018
2019 // Tailored to suit RpmPostTransCollector.
2020 // It's a pity, but we need all those verbose debug lines just
2021 // to figure out which script is currently executed. Otherwise we
2022 // can't tell which output belongs to which script.
2023 static const str::regex rx( "^D: (%.*): scriptlet start$" );
2024 str::smatch what;
2025 std::string line;
2026 bool silent = true; // discard everything before 1st scriptlet
2027 while ( systemReadLine(line) )
2028 {
2029 if ( not output_r )
2030 continue;
2031
2032 if ( str::startsWith( line, "D:" ) ) { // rpm debug output
2033 if ( str::regex_match( line, what, rx ) ) {
2034 // forward ripoff header
2035 output_r( "RIPOFF:"+what[1] );
2036 if ( silent )
2037 silent = false;
2038 }
2039 continue;
2040 }
2041 if ( silent ) {
2042 continue;
2043 }
2044 if ( str::startsWith( line, "+ " ) ) { // shell -x debug output
2045 continue;
2046 }
2047 // forward output line
2048 output_r( line );
2049 }
2050
2051 int rpm_status = systemStatus();
2052 if ( rpm_status != 0 ) {
2053 WAR << "rpm --runposttrans returned " << rpm_status << endl;
2054 }
2055 return rpm_status;
2056}
2057
2059//
2060//
2061// METHOD NAME : RpmDb::backupPackage
2062// METHOD TYPE : bool
2063//
2064 bool RpmDb::backupPackage( const Pathname & filename )
2065{
2066 RpmHeader::constPtr h( RpmHeader::readPackage( filename, RpmHeader::NOSIGNATURE ) );
2067 if ( ! h )
2068 return false;
2069
2070 return backupPackage( h->tag_name() );
2071}
2072
2074//
2075//
2076// METHOD NAME : RpmDb::backupPackage
2077// METHOD TYPE : bool
2078//
2079 bool RpmDb::backupPackage(const std::string& packageName)
2080{
2081 HistoryLog progresslog;
2082 bool ret = true;
2083 Pathname backupFilename;
2084 Pathname filestobackupfile = _root+_backuppath+FILEFORBACKUPFILES;
2085
2086 if (_backuppath.empty())
2087 {
2088 INT << "_backuppath empty" << endl;
2089 return false;
2090 }
2091
2092 FileList fileList;
2093
2094 if (!queryChangedFiles(fileList, packageName))
2095 {
2096 ERR << "Error while getting changed files for package " <<
2097 packageName << endl;
2098 return false;
2099 }
2100
2101 if (fileList.size() <= 0)
2102 {
2103 DBG << "package " << packageName << " not changed -> no backup" << endl;
2104 return true;
2105 }
2106
2107 if (filesystem::assert_dir(_root + _backuppath) != 0)
2108 {
2109 return false;
2110 }
2111
2112 {
2113 // build up archive name
2114 time_t currentTime = time(0);
2115 struct tm *currentLocalTime = localtime(&currentTime);
2116
2117 int date = (currentLocalTime->tm_year + 1900) * 10000
2118 + (currentLocalTime->tm_mon + 1) * 100
2119 + currentLocalTime->tm_mday;
2120
2121 int num = 0;
2122 do
2123 {
2124 backupFilename = _root + _backuppath
2125 + str::form("%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2126
2127 }
2128 while ( PathInfo(backupFilename).isExist() && num++ < 1000);
2129
2130 PathInfo pi(filestobackupfile);
2131 if (pi.isExist() && !pi.isFile())
2132 {
2133 ERR << filestobackupfile.asString() << " already exists and is no file" << endl;
2134 return false;
2135 }
2136
2137 std::ofstream fp ( filestobackupfile.asString().c_str(), std::ios::out|std::ios::trunc );
2138
2139 if (!fp)
2140 {
2141 ERR << "could not open " << filestobackupfile.asString() << endl;
2142 return false;
2143 }
2144
2145 for (FileList::const_iterator cit = fileList.begin();
2146 cit != fileList.end(); ++cit)
2147 {
2148 std::string name = *cit;
2149 if ( name[0] == '/' )
2150 {
2151 // remove slash, file must be relative to -C parameter of tar
2152 name = name.substr( 1 );
2153 }
2154 DBG << "saving file "<< name << endl;
2155 fp << name << endl;
2156 }
2157 fp.close();
2158
2159 const char* const argv[] =
2160 {
2161 "tar",
2162 "-czhP",
2163 "-C",
2164 _root.asString().c_str(),
2165 "--ignore-failed-read",
2166 "-f",
2167 backupFilename.asString().c_str(),
2168 "-T",
2169 filestobackupfile.asString().c_str(),
2170 NULL
2171 };
2172
2173 // execute tar in inst-sys (we dont know if there is a tar below _root !)
2174 ExternalProgram tar(argv, ExternalProgram::Stderr_To_Stdout, false, -1, true);
2175
2176 std::string tarmsg;
2177
2178 // TODO: it is probably possible to start tar with -v and watch it adding
2179 // files to report progress
2180 for (std::string output = tar.receiveLine(); output.length() ;output = tar.receiveLine())
2181 {
2182 tarmsg+=output;
2183 }
2184
2185 int ret = tar.close();
2186
2187 if ( ret != 0)
2188 {
2189 ERR << "tar failed: " << tarmsg << endl;
2190 ret = false;
2191 }
2192 else
2193 {
2194 MIL << "tar backup ok" << endl;
2195 progresslog.comment(
2196 str::form(_("created backup %s"), backupFilename.asString().c_str())
2197 , /*timestamp*/true);
2198 }
2199
2200 filesystem::unlink(filestobackupfile);
2201 }
2202
2203 return ret;
2204}
2205
2206 void RpmDb::setBackupPath(const Pathname& path)
2207{
2208 _backuppath = path;
2209}
2210
2211std::ostream & operator<<( std::ostream & str, RpmDb::CheckPackageResult obj )
2212{
2213 switch ( obj )
2214 {
2215#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2216 // translators: possible rpm package signature check result [brief]
2217 OUTS( CHK_OK, _("Signature is OK") );
2218 // translators: possible rpm package signature check result [brief]
2219 OUTS( CHK_NOTFOUND, _("Unknown type of signature") );
2220 // translators: possible rpm package signature check result [brief]
2221 OUTS( CHK_FAIL, _("Signature does not verify") );
2222 // translators: possible rpm package signature check result [brief]
2223 OUTS( CHK_NOTTRUSTED, _("Signature is OK, but key is not trusted") );
2224 // translators: possible rpm package signature check result [brief]
2225 OUTS( CHK_NOKEY, _("Signatures public key is not available") );
2226 // translators: possible rpm package signature check result [brief]
2227 OUTS( CHK_ERROR, _("File does not exist or signature can't be checked") );
2228 // translators: possible rpm package signature check result [brief]
2229 OUTS( CHK_NOSIG, _("File is unsigned") );
2230#undef OUTS
2231 }
2232 return str << "UnknowSignatureCheckError("+str::numstring(obj)+")";
2233}
2234
2235std::ostream & operator<<( std::ostream & str, const RpmDb::CheckPackageDetail & obj )
2236{
2237 for ( const auto & el : obj )
2238 str << el.second << endl;
2239 return str;
2240}
2241
2242} // namespace rpm
2243} // namespace target
2244} // namespace zypp
HistoryLog.h
KeyRing.h
LocaleGuard.h
RpmCallbacks.h
MAXRPMMESSAGELINES
#define MAXRPMMESSAGELINES
Definition RpmDb.cc:65
WARNINGMAILPATH
#define WARNINGMAILPATH
Definition RpmDb.cc:63
FAILIFNOTINITIALIZED
#define FAILIFNOTINITIALIZED
Definition RpmDb.cc:197
FILEFORBACKUPFILES
#define FILEFORBACKUPFILES
Definition RpmDb.cc:64
RpmDb.h
RpmException.h
RpmPostTransCollector.h
OUTS
#define OUTS(V)
ZConfig.h
ZYppFactory.h
shared_ptr
zypp::Date
Store and operate on date (time_t).
Definition Date.h:33
zypp::Date::form
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
Definition Date.h:112
zypp::Date::now
static Date now()
Return the current time.
Definition Date.h:78
zypp::DtorReset
Assign a vaiable a certain value when going out of scope.
Definition dtorreset.h:50
zypp::Edition
Edition represents [epoch:]version[-release]
Definition Edition.h:61
zypp::Edition::version
std::string version() const
Version.
Definition Edition.cc:94
zypp::Edition::release
std::string release() const
Release.
Definition Edition.cc:110
zypp::Edition::noedition
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Definition Edition.h:73
zypp::Exception
Base class for Exception.
Definition Exception.h:147
zypp::Exception::asUserHistory
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:127
zypp::Exception::addHistory
void addHistory(const std::string &msg_r)
Add some message text to the history.
Definition Exception.cc:176
zypp::Exception::moveToHistory
void moveToHistory(TContainer &&msgc_r)
addHistory from string container types (oldest first) moving
Definition Exception.h:248
zypp::ExternalProgram
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
Definition ExternalProgram.h:64
zypp::ExternalProgram::close
int close() override
Wait for the progamm to complete.
Definition ExternalProgram.cc:357
zypp::ExternalProgram::Stderr_Disposition
Stderr_Disposition
Define symbols for different policies on the handling of stderr.
Definition ExternalProgram.h:74
zypp::ExternalProgram::Discard_Stderr
@ Discard_Stderr
Definition ExternalProgram.h:76
zypp::ExternalProgram::Stderr_To_Stdout
@ Stderr_To_Stdout
Definition ExternalProgram.h:77
zypp::HistoryLog
Writing the zypp history file.
Definition HistoryLog.h:57
zypp::HistoryLog::comment
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Definition HistoryLog.cc:190
zypp::IdStringType::asString
std::string asString() const
Definition IdStringType.h:108
zypp::Package::constPtr
TraitsType::constPtrType constPtr
Definition Package.h:39
zypp::Pathname::basename
std::string basename() const
Return the last component of this path.
Definition Pathname.h:130
zypp::ProgressData
Maintain [min,max] and counter (value) for progress counting.
Definition progressdata.h:132
zypp::ProgressData::value_type
long long value_type
Definition progressdata.h:134
zypp::ProgressData::reportValue
value_type reportValue() const
Definition progressdata.h:322
zypp::ProgressData::sendTo
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
Definition progressdata.h:229
zypp::ProgressData::toMax
bool toMax()
Set counter value to current max value (unless no range).
Definition progressdata.h:276
zypp::ProgressData::incr
bool incr(value_type val_r=1)
Increment counter value (default by 1).
Definition progressdata.h:264
zypp::ProgressData::toMin
bool toMin()
Set counter value to current min value.
Definition progressdata.h:272
zypp::ProgressData::range
void range(value_type max_r)
Set new [0,max].
Definition progressdata.h:216
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:940
zypp::ZYppFactory::getZYpp
ZYpp::Ptr getZYpp()
Convenience to get the Pointer to the ZYpp instance.
Definition ZYppFactory.h:77
zypp::base::ReferenceCounted::operator<<
friend std::ostream & operator<<(std::ostream &str, const ReferenceCounted &obj)
Stream output via dumpOn.
zypp::callback::UserData
Typesafe passing of user data via callbacks.
Definition UserData.h:40
zypp::callback::UserData::set
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
Definition UserData.h:119
zypp::callback::UserData::ContentType
zypp::ContentType ContentType
Definition UserData.h:51
zypp::externalprogram::ExternalDataSource::receiveLine
std::string receiveLine()
Read one line from the input stream.
Definition ExternalDataSource.cc:115
zypp::filesystem::PathInfo
Wrapper class for stat/lstat.
Definition PathInfo.h:226
zypp::filesystem::PathInfo::isFile
bool isFile() const
Definition PathInfo.h:295
zypp::filesystem::PathInfo::isExist
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:286
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:47
zypp::filesystem::Pathname::c_str
const char * c_str() const
String representation.
Definition Pathname.h:112
zypp::filesystem::Pathname::asString
const std::string & asString() const
String representation.
Definition Pathname.h:93
zypp::filesystem::Pathname::basename
std::string basename() const
Return the last component of this path.
Definition Pathname.h:130
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition Pathname.h:116
zypp::filesystem::Pathname::relative
bool relative() const
Test for a relative path.
Definition Pathname.h:120
zypp::filesystem::TmpFile
Provide a new empty temporary file and delete it when no longer needed.
Definition TmpPath.h:128
zypp::filesystem::TmpPath::path
Pathname path() const
Definition TmpPath.cc:152
zypp::str::regex
Regular expression.
Definition Regex.h:95
zypp::str::smatch
Regular expression match result.
Definition Regex.h:168
zypp::target::RpmPostTransCollector
Extract and remember posttrans scripts for later execution.
Definition RpmPostTransCollector.h:40
zypp::target::RpmPostTransCollector::collectPosttransInfo
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.
Definition RpmPostTransCollector.cc:424
zypp::target::RpmPostTransCollector::hasPosttransScript
bool hasPosttransScript(const Pathname &rpmPackage_r)
Test whether a package defines a posttrans script.
Definition RpmPostTransCollector.cc:421
zypp::target::rpm::RpmDbAlreadyOpenException
Definition RpmException.h:181
zypp::target::rpm::RpmDbNotOpenException
Definition RpmException.h:205
zypp::target::rpm::RpmDb
Interface to the rpm program.
Definition RpmDb.h:51
zypp::target::rpm::RpmDb::getData
void getData(const std::string &name_r, RpmHeader::constPtr &result_r) const
Get an installed packages data from rpmdb.
Definition RpmDb.cc:1048
zypp::target::rpm::RpmDb::doRebuildDatabase
void doRebuildDatabase(callback::SendReport< RebuildDBReport > &report)
Definition RpmDb.cc:369
zypp::target::rpm::RpmDb::queryChangedFiles
bool queryChangedFiles(FileList &fileList, const std::string &packageName)
determine which files of an installed package have been modified.
Definition RpmDb.cc:1338
zypp::target::rpm::RpmDb::error_message
std::string error_message
Error message from running rpm as external program.
Definition RpmDb.h:344
zypp::target::rpm::RpmDb::hasRequiredBy
bool hasRequiredBy(const std::string &tag_r) const
Return true if at least one package requires a certain tag.
Definition RpmDb.cc:992
zypp::target::rpm::RpmDb::RpmArgVec
std::vector< const char * > RpmArgVec
Definition RpmDb.h:303
zypp::target::rpm::RpmDb::whoOwnsFile
std::string whoOwnsFile(const std::string &file_r) const
Return name of package owning file or empty string if no installed package owns file.
Definition RpmDb.cc:960
zypp::target::rpm::RpmDb::exportTrustedKeysInZyppKeyRing
void exportTrustedKeysInZyppKeyRing()
insert all rpm trusted keys into zypp trusted keyring
Definition RpmDb.cc:654
zypp::target::rpm::RpmDb::importPubkey
void importPubkey(const PublicKey &pubkey_r)
Import ascii armored public key in file pubkey_r.
Definition RpmDb.cc:663
zypp::target::rpm::RpmDb::installPackage
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
Definition RpmDb.cc:1630
zypp::target::rpm::RpmDb::_backuppath
Pathname _backuppath
/var/adm/backup
Definition RpmDb.h:347
zypp::target::rpm::RpmDb::dumpOn
std::ostream & dumpOn(std::ostream &str) const override
Dump debug info.
Definition RpmDb.cc:241
zypp::target::rpm::RpmDb::run_rpm
void run_rpm(const RpmArgVec &options, ExternalProgram::Stderr_Disposition stderr_disp=ExternalProgram::Stderr_To_Stdout)
Run rpm with the specified arguments and handle stderr.
Definition RpmDb.cc:1403
zypp::target::rpm::RpmDb::initDatabase
void initDatabase(Pathname root_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database below root_r.
Definition RpmDb.cc:260
zypp::target::rpm::RpmDb::runposttrans
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.
Definition RpmDb.cc:2006
zypp::target::rpm::RpmDb::initialized
bool initialized() const
Definition RpmDb.h:125
zypp::target::rpm::RpmDb::process
ExternalProgram * process
The connection to the rpm process.
Definition RpmDb.h:301
zypp::target::rpm::RpmDb::SyncTrustedKeyBits
SyncTrustedKeyBits
Sync mode for syncTrustedKeys.
Definition RpmDb.h:278
zypp::target::rpm::RpmDb::SYNC_TO_KEYRING
@ SYNC_TO_KEYRING
export rpm trusted keys into zypp trusted keyring
Definition RpmDb.h:279
zypp::target::rpm::RpmDb::SYNC_FROM_KEYRING
@ SYNC_FROM_KEYRING
import zypp trusted keys into rpm database.
Definition RpmDb.h:280
zypp::target::rpm::RpmDb::~RpmDb
~RpmDb() override
Destructor.
Definition RpmDb.cc:226
zypp::target::rpm::RpmDb::pubkeys
std::list< PublicKey > pubkeys() const
Return the long ids of all installed public keys.
Definition RpmDb.cc:843
zypp::target::rpm::RpmDb::pubkeyEditions
std::set< Edition > pubkeyEditions() const
Return the edition of all installed public keys.
Definition RpmDb.cc:881
zypp::target::rpm::RpmDb::systemStatus
int systemStatus()
Return the exit status of the general rpm process, closing the connection if not already done.
Definition RpmDb.cc:1505
zypp::target::rpm::RpmDb::FileList
std::set< std::string > FileList
Definition RpmDb.h:370
zypp::target::rpm::RpmDb::checkPackageSignature
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).
Definition RpmDb.cc:1332
zypp::target::rpm::RpmDb::backupPackage
bool backupPackage(const std::string &packageName)
create tar.gz of all changed files in a Package
Definition RpmDb.cc:2079
zypp::target::rpm::RpmDb::hasProvides
bool hasProvides(const std::string &tag_r) const
Return true if at least one package provides a certain tag.
Definition RpmDb.cc:978
zypp::target::rpm::RpmDb::systemKill
void systemKill()
Forcably kill the system process.
Definition RpmDb.cc:1528
zypp::target::rpm::RpmDb::root
const Pathname & root() const
Definition RpmDb.h:109
zypp::target::rpm::RpmDb::removePubkey
void removePubkey(const PublicKey &pubkey_r)
Remove a public key from the rpm database.
Definition RpmDb.cc:776
zypp::target::rpm::RpmDb::RpmDb
RpmDb()
Constructor.
Definition RpmDb.cc:207
zypp::target::rpm::RpmDb::removePackage
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
Definition RpmDb.cc:1836
zypp::target::rpm::RpmDb::dbConstIterator
db_const_iterator dbConstIterator() const
Definition RpmDb.cc:247
zypp::target::rpm::RpmDb::fileList
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 !...
Definition RpmDb.cc:905
zypp::target::rpm::RpmDb::dbPath
const Pathname & dbPath() const
Definition RpmDb.h:117
zypp::target::rpm::RpmDb::_dbPath
Pathname _dbPath
Directory that contains the rpmdb.
Definition RpmDb.h:91
zypp::target::rpm::RpmDb::closeDatabase
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
Definition RpmDb.cc:331
zypp::target::rpm::RpmDb::setBackupPath
void setBackupPath(const Pathname &path)
set path where package backups are stored
Definition RpmDb.cc:2206
zypp::target::rpm::RpmDb::_packagebackups
bool _packagebackups
create package backups?
Definition RpmDb.h:350
zypp::target::rpm::RpmDb::checkPackage
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,...
Definition RpmDb.cc:1326
zypp::target::rpm::RpmDb::importZyppKeyRingTrustedKeys
void importZyppKeyRingTrustedKeys()
iterates through zypp keyring and import all non-existent keys into rpm keyring
Definition RpmDb.cc:651
zypp::target::rpm::RpmDb::doInstallPackage
void doInstallPackage(const Pathname &filename, RpmInstFlags flags, RpmPostTransCollector *postTransCollector_r, callback::SendReport< RpmInstallReport > &report)
Definition RpmDb.cc:1666
zypp::target::rpm::RpmDb::_root
Pathname _root
Root directory for all operations.
Definition RpmDb.h:86
zypp::target::rpm::RpmDb::hasConflicts
bool hasConflicts(const std::string &tag_r) const
Return true if at least one package conflicts with a certain tag.
Definition RpmDb.cc:1006
zypp::target::rpm::RpmDb::exit_code
int exit_code
The exit code of the rpm process, or -1 if not yet known.
Definition RpmDb.h:338
zypp::target::rpm::RpmDb::syncTrustedKeys
void syncTrustedKeys(SyncTrustedKeyBits mode_r=SYNC_BOTH)
Sync trusted keys stored in rpm database and zypp trusted keyring.
Definition RpmDb.cc:550
zypp::target::rpm::RpmDb::processConfigFiles
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"
Definition RpmDb.cc:1535
zypp::target::rpm::RpmDb::CheckPackageResult
CheckPackageResult
checkPackage result
Definition RpmDb.h:377
zypp::target::rpm::RpmDb::CHK_ERROR
@ CHK_ERROR
Definition RpmDb.h:383
zypp::target::rpm::RpmDb::CHK_NOTTRUSTED
@ CHK_NOTTRUSTED
Definition RpmDb.h:381
zypp::target::rpm::RpmDb::CHK_NOSIG
@ CHK_NOSIG
Definition RpmDb.h:384
zypp::target::rpm::RpmDb::CHK_NOKEY
@ CHK_NOKEY
Definition RpmDb.h:382
zypp::target::rpm::RpmDb::CHK_FAIL
@ CHK_FAIL
Definition RpmDb.h:380
zypp::target::rpm::RpmDb::CHK_NOTFOUND
@ CHK_NOTFOUND
Definition RpmDb.h:379
zypp::target::rpm::RpmDb::CHK_OK
@ CHK_OK
Definition RpmDb.h:378
zypp::target::rpm::RpmDb::hasPackage
bool hasPackage(const std::string &name_r) const
Return true if package is installed.
Definition RpmDb.cc:1020
zypp::target::rpm::RpmDb::doRemovePackage
void doRemovePackage(const std::string &name_r, RpmInstFlags flags, RpmPostTransCollector *postTransCollector_r, callback::SendReport< RpmRemoveReport > &report)
Definition RpmDb.cc:1877
zypp::target::rpm::RpmDb::systemReadLine
bool systemReadLine(std::string &line)
Read a line from the general rpm query.
Definition RpmDb.cc:1452
zypp::target::rpm::RpmDb::rebuildDatabase
void rebuildDatabase()
Rebuild the rpm database (rpm –rebuilddb).
Definition RpmDb.cc:351
zypp::target::rpm::RpmDb::hasFile
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 ...
Definition RpmDb.cc:934
zypp::target::rpm::RpmException
Just inherits Exception to separate media exceptions.
Definition RpmException.h:39
zypp::target::rpm::RpmHeader::constPtr
intrusive_ptr< const RpmHeader > constPtr
Definition RpmHeader.h:65
zypp::target::rpm::RpmHeader::readPackage
static RpmHeader::constPtr readPackage(const Pathname &path, VERIFICATION verification=VERIFY)
Get an accessible packages data from disk.
Definition RpmHeader.cc:212
zypp::target::rpm::RpmHeader::NOSIGNATURE
@ NOSIGNATURE
Definition RpmHeader.h:197
zypp::target::rpm::RpmHeader::NOVERIFY
@ NOVERIFY
Definition RpmHeader.h:198
zypp::target::rpm::RpmSubprocessException
Definition RpmException.h:130
zypp::target::rpm::librpmDb::globalInit
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
Definition librpmDb.cc:139
zypp::target::rpm::librpmDb::dbOpenCreate
static librpmDb::constPtr dbOpenCreate(const Pathname &root_r, const Pathname &dbPath_r=Pathname())
Assert the rpmdb below the system at root_r exists.
Definition librpmDb.cc:198
zypp::target::rpm::librpmDb::suggestedDbPath
static Pathname suggestedDbPath(const Pathname &root_r)
Definition librpmDb.cc:171
librpmDb.h
librpm.h
str
String related utilities and Regular expression matching.
ztui::table::CStyle::Edition
@ Edition
Editions with v-r setparator highlighted.
Definition Table.h:160
zypp::env
Namespace intended to collect all environment variables we use.
Definition Env.h:23
zypp::env::ZYPP_RPM_DEBUG
bool ZYPP_RPM_DEBUG()
Definition RpmDb.cc:80
zypp::filesystem
Types and functions for filesystem operations.
Definition Glob.cc:24
zypp::filesystem::symlink
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
Definition PathInfo.cc:860
zypp::filesystem::copy
int copy(const Pathname &file, const Pathname &dest)
Like 'cp file dest'.
Definition PathInfo.cc:825
zypp::filesystem::expandlink
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...
Definition PathInfo.cc:950
zypp::filesystem::unlink
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:705
zypp::filesystem::assert_dir
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:324
zypp::io::receiveUpto
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
Definition IOTools.cc:85
zypp::io::Timeout
@ Timeout
Definition IOTools.h:72
zypp::io::Success
@ Success
Definition IOTools.h:71
zypp::io::Error
@ Error
Definition IOTools.h:74
zypp::io::EndOfFile
@ EndOfFile
Definition IOTools.h:73
zypp::str::replaceAll
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).
Definition String.cc:331
zypp::str::numstring
std::string numstring(char n, int w=0)
Definition String.h:289
zypp::str::hasPrefix
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition String.h:1026
zypp::str::toLower
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition String.cc:178
zypp::str::startsWith
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
Definition String.h:1084
zypp::str::endsWith
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
Definition String.h:1091
zypp::str::regex_match
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
Definition Regex.h:70
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
zypp::str::strToBool
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:429
zypp::target::rpm::diffFiles
unsigned diffFiles(const std::string &file1, const std::string &file2, std::string &out, int maxlines)
Definition RpmDb.cc:163
zypp::target::rpm::RPMINST_NOSIGNATURE
@ RPMINST_NOSIGNATURE
Definition RpmFlags.h:47
zypp::target::rpm::RPMINST_NOSCRIPTS
@ RPMINST_NOSCRIPTS
Definition RpmFlags.h:41
zypp::target::rpm::RPMINST_NODEPS
@ RPMINST_NODEPS
Definition RpmFlags.h:43
zypp::target::rpm::RPMINST_JUSTDB
@ RPMINST_JUSTDB
Definition RpmFlags.h:45
zypp::target::rpm::RPMINST_FORCE
@ RPMINST_FORCE
Definition RpmFlags.h:42
zypp::target::rpm::RPMINST_IGNORESIZE
@ RPMINST_IGNORESIZE
Definition RpmFlags.h:44
zypp::target::rpm::RPMINST_TEST
@ RPMINST_TEST
Definition RpmFlags.h:49
zypp::target::rpm::RPMINST_NOPOSTTRANS
@ RPMINST_NOPOSTTRANS
Definition RpmFlags.h:50
zypp::target::rpm::RPMINST_NODIGEST
@ RPMINST_NODIGEST
Definition RpmFlags.h:46
zypp::target::rpm::RPMINST_NOUPGRADE
@ RPMINST_NOUPGRADE
Definition RpmFlags.h:48
zypp::target::rpm::RPMINST_EXCLUDEDOCS
@ RPMINST_EXCLUDEDOCS
Definition RpmFlags.h:40
zypp::target::rpm::operator<<
std::ostream & operator<<(std::ostream &str, const librpmDb::db_const_iterator &obj)
Definition librpmDb.cc:412
zypp::target::rpm::dumpPath
_dumpPath dumpPath(const Pathname &root_r, const Pathname &sub_r)
dumpPath iomaip to dump '(root_r)sub_r' output,
Definition librpmDb.h:42
zypp::target::rpm::sKeyRingReceiver
static shared_ptr< KeyRingSignalReceiver > sKeyRingReceiver
Definition RpmDb.cc:161
zypp::target
Definition KeyRing.h:325
zypp::zypp_readonly_hack
Definition repomanager.cc:45
zypp::zypp_readonly_hack::IGotIt
bool IGotIt()
Definition ZYppFactory.cc:92
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition Application.cc:20
zypp::callback::ReceiveReport
Definition Callback.h:169
zypp::callback::ReceiveReport< KeyRingSignals >::connect
void connect()
Definition Callback.h:183
zypp::callback::ReceiveReport< KeyRingSignals >::disconnect
void disconnect()
Definition Callback.h:186
zypp::callback::SendReport
Definition Callback.h:237
zypp::callback::TempConnect
Temporarily connect a ReceiveReport then restore the previous one.
Definition Callback.h:285
zypp::str::Format
Convenient building of std::string with boost::format.
Definition String.h:253
zypp::str::Format::asString
std::string asString() const
Definition String.h:262
zypp::target::rpm::KeyRingSignalReceiver
Definition RpmDb.cc:134
zypp::target::rpm::KeyRingSignalReceiver::operator=
KeyRingSignalReceiver & operator=(const KeyRingSignalReceiver &)=delete
zypp::target::rpm::KeyRingSignalReceiver::trustedKeyRemoved
void trustedKeyRemoved(const PublicKey &key) override
Definition RpmDb.cc:152
zypp::target::rpm::KeyRingSignalReceiver::operator=
KeyRingSignalReceiver & operator=(KeyRingSignalReceiver &&)=delete
zypp::target::rpm::KeyRingSignalReceiver::KeyRingSignalReceiver
KeyRingSignalReceiver(const KeyRingSignalReceiver &)=delete
zypp::target::rpm::KeyRingSignalReceiver::KeyRingSignalReceiver
KeyRingSignalReceiver(RpmDb &rpmdb)
Definition RpmDb.cc:135
zypp::target::rpm::KeyRingSignalReceiver::trustedKeyAdded
void trustedKeyAdded(const PublicKey &key) override
Definition RpmDb.cc:146
zypp::target::rpm::KeyRingSignalReceiver::~KeyRingSignalReceiver
~KeyRingSignalReceiver() override
Definition RpmDb.cc:141
zypp::target::rpm::KeyRingSignalReceiver::KeyRingSignalReceiver
KeyRingSignalReceiver(KeyRingSignalReceiver &&)=delete
zypp::target::rpm::KeyRingSignalReceiver::_rpmdb
RpmDb & _rpmdb
Definition RpmDb.cc:158
zypp::target::rpm::RebuildDBReport::FAILED
@ FAILED
Definition ZYppCallbacks.h:696
zypp::target::rpm::RebuildDBReport::NO_ERROR
@ NO_ERROR
Definition ZYppCallbacks.h:695
zypp::target::rpm::RpmDb::CheckPackageDetail
Detailed rpm signature check log messages A single multiline message if CHK_OK.
Definition RpmDb.h:392
zypp::target::rpm::RpmDb::db_const_iterator
Wrapper providing a librpmDb::db_const_iterator for this RpmDb.
Definition RpmDb.h:65
zypp::target::rpm::RpmInstallReport::Action
Action
Definition RpmCallbacks.h:73
zypp::target::rpm::RpmInstallReport::IGNORE
@ IGNORE
Definition RpmCallbacks.h:76
zypp::target::rpm::RpmInstallReport::ABORT
@ ABORT
Definition RpmCallbacks.h:74
zypp::target::rpm::RpmRemoveReport::Action
Action
Definition RpmCallbacks.h:36
zypp::target::rpm::RpmRemoveReport::ABORT
@ ABORT
Definition RpmCallbacks.h:37
zypp::target::rpm::RpmRemoveReport::IGNORE
@ IGNORE
Definition RpmCallbacks.h:39
for_
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
ZYPP_RETHROW
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:444
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:440
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:424
_
#define _(MSG)
Definition Gettext.h:39
DBG
#define DBG
Definition Logger.h:99
MIL
#define MIL
Definition Logger.h:100
ERR
#define ERR
Definition Logger.h:102
WAR
#define WAR
Definition Logger.h:101
L_DBG
#define L_DBG(GROUP)
Definition Logger.h:108
INT
#define INT
Definition Logger.h:104
StringV.h
Date.h
PathInfo.h
Pathname.h
TmpPath.h
Gettext.h
Interface to gettext.
IOTools.h
Logger.h
String.h