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