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