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