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