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