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