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