15 #include <rpm/rpmcli.h>
16 #include <rpm/rpmlog.h>
55 using namespace zypp::filesystem;
57 #define WARNINGMAILPATH "/var/log/YaST2/"
58 #define FILEFORBACKUPFILES "YaSTBackupModifiedFiles"
59 #define MAXRPMMESSAGELINES 10000
61 #define WORKAROUNDRPMPWDBUG
65 namespace zypp_readonly_hack
73 static bool val = [](){
74 const char * env = getenv(
"ZYPP_RPM_DEBUG");
86 #if 1 // No more need to escape whitespace since rpm-4.4.2.3
87 const char* quoteInFilename_m =
"\'\"";
89 const char* quoteInFilename_m =
" \t\'\"";
91 inline std::string rpmQuoteFilename(
const Pathname & path_r )
93 std::string path( path_r.
asString() );
95 pos != std::string::npos;
96 pos = path.find_first_of( quoteInFilename_m, pos ) )
98 path.insert( pos,
"\\" );
111 #if defined(WORKAROUNDRPMPWDBUG)
115 AutoDispose<char*> cwd( ::get_current_dir_name(), ::free );
118 WAR <<
"Can't get cwd!" << endl;
139 MIL <<
"trusted key added to zypp Keyring. Importing..." << endl;
140 _rpmdb.importPubkey( key );
145 MIL <<
"Trusted key removed from zypp Keyring. Removing..." << endl;
146 _rpmdb.removePubkey( key );
154 unsigned diffFiles(
const std::string file1,
const std::string file2, std::string& out,
int maxlines)
175 if (maxlines<0?
true:count<maxlines)
190 inline std::string
stringPath(
const Pathname & root_r,
const Pathname & sub_r )
203 if ( obj == RpmDb::DbSI_NO_INIT )
209 #define ENUM_OUT(B,C) str << ( obj & RpmDb::B ? C : '-' )
232 #define FAILIFNOTINITIALIZED if( ! initialized() ) { ZYPP_THROW(RpmDbNotOpenException()); }
243 : _dbStateInfo( DbSI_NO_INIT )
244 #warning Check for obsolete memebers
245 , _backuppath (
"/var/adm/backup")
246 , _packagebackups(false)
247 , _warndirexists(false)
254 setenv(
"RPM_IgnoreFailedSymlinks",
"1", 1 );
266 MIL <<
"~RpmDb()" << endl;
269 MIL <<
"~RpmDb() end" << endl;
279 db_path =
"/var/lib/rpm";
283 PathInfo rpmdb_info(
root() + db_path +
"/Packages");
285 if ( rpmdb_info.isExist() )
286 return rpmdb_info.mtime();
306 #define ENUM_OUT(B,C) str << ( _dbStateInfo & B ? C : '-' )
332 bool quickinit( root_r.empty() );
334 if ( root_r.empty() )
337 if ( dbPath_r.empty() )
338 dbPath_r =
"/var/lib/rpm";
340 if ( ! (root_r.absolute() && dbPath_r.absolute()) )
342 ERR <<
"Illegal root or dbPath: " <<
stringPath( root_r, dbPath_r ) << endl;
346 MIL <<
"Calling initDatabase: " <<
stringPath( root_r, dbPath_r )
347 << ( doRebuild_r ?
" (rebuilddb)" :
"" )
348 << ( quickinit ?
" (quickinit)" :
"" ) << endl;
372 MIL <<
"QUICK initDatabase (no systemRoot set)" << endl;
385 ERR <<
"Cleanup on error: state " << info << endl;
400 MIL <<
"Cleanup: state " << info << endl;
409 MIL <<
"Update mode: Cleanup delayed until closeOldDatabase." << endl;
412 #warning CHECK: notify root about conversion backup.
427 MIL <<
"Synchronizing keys with zypp keyring" << endl;
436 MIL <<
"InitDatabase: " << *
this << endl;
462 ERR <<
"Bad database directory: " << dbInfo.
dbDir() << endl;
469 MIL <<
"Found rpm4 database in " << dbInfo.
dbDir() << endl;
473 MIL <<
"Creating new rpm4 database in " << dbInfo.
dbDir() << endl;
485 DBG <<
"Initial state: " << info_r <<
": " <<
stringPath( root_r, dbPath_r );
504 DBG <<
"Access state: " << info_r <<
": " <<
stringPath( root_r, dbPath_r );
513 bool dbEmpty = dbptr->empty();
516 MIL <<
"Empty rpm4 database " << dbInfo.
dbV4() << endl;
521 MIL <<
"Found rpm3 database " << dbInfo.
dbV3() << endl;
532 WAR <<
"Backup converted rpm3 database failed: error(" << res <<
")" << endl;
539 MIL <<
"Backup converted rpm3 database: " << dbInfo.
dbV3ToV4() << endl;
548 WAR <<
"Non empty rpm3 and rpm4 database found: using rpm4" << endl;
554 DBG <<
"Convert state: " << info_r <<
": " <<
stringPath( root_r, dbPath_r );
560 MIL <<
"Rpm3 database backup: " << dbInfo.
dbV3ToV4() << endl;
572 const char * v3backup =
"packages.rpm3";
573 const char * master =
"Packages";
574 const char * index[] =
596 PathInfo pi( dbdir_r );
599 ERR <<
"Can't remove rpm4 database in non directory: " << dbdir_r << endl;
603 for (
const char ** f = index; *f; ++f )
612 pi( dbdir_r + master );
615 MIL <<
"Removing rpm4 database " << pi << endl;
621 pi( dbdir_r + v3backup );
624 MIL <<
"Removing converted rpm3 database backup " << pi << endl;
638 const char * master =
"packages.rpm";
639 const char * index[] =
641 "conflictsindex.rpm",
652 PathInfo pi( dbdir_r );
655 ERR <<
"Can't remove rpm3 database in non directory: " << dbdir_r << endl;
659 for (
const char ** f = index; *f; ++f )
668 #warning CHECK: compare vs existing v3 backup. notify root
669 pi( dbdir_r + master );
672 Pathname m( pi.path() );
677 Pathname b( m.extend(
"3" ) );
682 Pathname b( m.extend(
".deleted" ) );
692 MIL <<
"(Re)moved rpm3 database to " << pi << endl;
732 MIL <<
"Calling closeDatabase: " << *
this << endl;
763 MIL <<
"closeDatabase: " << *
this << endl;
794 MIL <<
"RpmDb::rebuildDatabase" << *
this << endl;
797 PathInfo dbMaster(
root() +
dbPath() +
"Packages" );
798 PathInfo dbMasterBackup( dbMaster.path().extend(
".y2backup" ) );
802 opts.push_back(
"--rebuilddb");
803 opts.push_back(
"-vv");
810 PathInfo newMaster(
root()
823 if ( ! report->progress( (100 * newMaster.size()) / dbMaster.size(),
root() +
dbPath()) )
825 WAR <<
"User requested abort." << endl;
831 if ( line.compare( 0, 2,
"D:" ) )
833 errmsg += line +
'\n';
841 if ( rpm_status != 0 )
859 void computeKeyRingSync( std::set<Edition> & rpmKeys_r, std::list<PublicKeyData> & zyppKeys_r )
870 void updateIf(
const Edition & rpmKey_r )
872 std::string keyRelease( rpmKey_r.
release() );
873 int comp = _release.compare( keyRelease );
877 _release.swap( keyRelease );
878 _inRpmKeys = &rpmKey_r;
879 _inZyppKeys =
nullptr;
880 if ( !keyRelease.empty() )
881 DBG <<
"Old key in Z: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
883 else if ( comp == 0 )
887 _inRpmKeys = &rpmKey_r;
891 DBG <<
"Old key in R: gpg-pubkey-" << rpmKey_r.
version() <<
"-" << keyRelease << endl;
894 void updateIf(
const PublicKeyData & zyppKey_r )
896 std::string keyRelease( zyppKey_r.gpgPubkeyRelease() );
897 int comp = _release.compare( keyRelease );
901 _release.swap( keyRelease );
902 _inRpmKeys =
nullptr;
903 _inZyppKeys = &zyppKey_r;
904 if ( !keyRelease.empty() )
905 DBG <<
"Old key in R: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() <<
"-" << keyRelease << endl;
907 else if ( comp == 0 )
911 _inZyppKeys = &zyppKey_r;
915 DBG <<
"Old key in Z: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() <<
"-" << keyRelease << endl;
918 std::string _release;
919 const Edition * _inRpmKeys;
920 const PublicKeyData * _inZyppKeys;
925 std::map<std::string,Key> _keymap;
927 for_( it, rpmKeys_r.begin(), rpmKeys_r.end() )
929 _keymap[(*it).version()].updateIf( *it );
932 for_( it, zyppKeys_r.begin(), zyppKeys_r.end() )
934 _keymap[(*it).gpgPubkeyVersion()].updateIf( *it );
938 std::set<Edition> rpmKeys;
939 std::list<PublicKeyData> zyppKeys;
940 for_( it, _keymap.begin(), _keymap.end() )
942 DBG <<
"gpg-pubkey-" << (*it).first <<
"-" << (*it).second._release <<
" "
943 << ( (*it).second._inRpmKeys ?
"R" :
"_" )
944 << ( (*it).second._inZyppKeys ?
"Z" :
"_" ) << endl;
945 if ( ! (*it).second._inRpmKeys )
947 zyppKeys.push_back( *(*it).second._inZyppKeys );
949 if ( ! (*it).second._inZyppKeys )
951 rpmKeys.insert( *(*it).second._inRpmKeys );
954 rpmKeys_r.swap( rpmKeys );
955 zyppKeys_r.swap( zyppKeys );
962 MIL <<
"Going to sync trusted keys..." << endl;
964 std::list<PublicKeyData> zyppKeys( getZYpp()->keyRing()->trustedPublicKeyData() );
965 computeKeyRingSync( rpmKeys, zyppKeys );
966 MIL << (mode_r &
SYNC_TO_KEYRING ?
"" :
"(skip) ") <<
"Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl;
967 MIL << (mode_r &
SYNC_FROM_KEYRING ?
"" :
"(skip) ") <<
"Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl;
973 MIL <<
"Exporting rpm keyring into zypp trusted keyring" <<endl;
978 TmpFile tmpfile( getZYpp()->tmpPath() );
980 std::ofstream tmpos( tmpfile.
path().
c_str() );
981 for_( it, rpmKeys.begin(), rpmKeys.end() )
985 getData(
"gpg-pubkey", *it, result );
986 tmpos << result->tag_description() << endl;
991 getZYpp()->keyRing()->multiKeyImport( tmpfile.
path(),
true );
995 ERR <<
"Could not import keys into in zypp keyring" << endl;
1003 MIL <<
"Importing zypp trusted keyring" << std::endl;
1004 for_( it, zyppKeys.begin(), zyppKeys.end() )
1008 importPubkey( getZYpp()->keyRing()->exportTrustedPublicKey( *it ) );
1016 MIL <<
"Trusted keys synced." << endl;
1038 WAR <<
"Key " << pubkey_r <<
" can not be imported. (READONLY MODE)" << endl;
1045 bool hasOldkeys =
false;
1047 for_( it, rpmKeys.begin(), rpmKeys.end() )
1054 if ( keyEd == *it && !pubkey_r.
hasSubkeys() )
1056 MIL <<
"Key " << pubkey_r <<
" is already in the rpm trusted keyring. (skip import)" << endl;
1060 if ( keyEd.version() != (*it).version() )
1063 if ( keyEd.release() < (*it).release() )
1065 MIL <<
"Key " << pubkey_r <<
" is older than one in the rpm trusted keyring. (skip import)" << endl;
1073 MIL <<
"Key " << pubkey_r <<
" will be imported into the rpm trusted keyring." << (hasOldkeys?
"(update)":
"(new)") << endl;
1079 std::string keyName(
"gpg-pubkey-" + keyEd.version() );
1081 opts.push_back (
"-e" );
1082 opts.push_back (
"--allmatches" );
1083 opts.push_back (
"--" );
1084 opts.push_back ( keyName.c_str() );
1097 ERR <<
"Failed to remove key " << pubkey_r <<
" from RPM trusted keyring (ignored)" << endl;
1101 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
1107 opts.push_back (
"--import" );
1108 opts.push_back (
"--" );
1109 std::string pubkeypath( pubkey_r.
path().asString() );
1110 opts.push_back ( pubkeypath.c_str() );
1117 std::vector<std::string> excplines;
1122 WAR << line << endl;
1123 excplines.push_back( std::move(line) );
1126 DBG << line << endl;
1139 MIL <<
"Key " << pubkey_r <<
" imported in rpm trusted keyring." << endl;
1156 std::set<Edition>::const_iterator found_edition = rpm_keys.end();
1159 for_( it, rpm_keys.begin(), rpm_keys.end() )
1161 if ( (*it).version() == pubkeyVersion )
1169 if (found_edition == rpm_keys.end())
1171 WAR <<
"Key " << pubkey_r.
id() <<
" is not in rpm db" << endl;
1175 std::string rpm_name(
"gpg-pubkey-" + found_edition->asString());
1178 opts.push_back (
"-e" );
1179 opts.push_back (
"--" );
1180 opts.push_back ( rpm_name.c_str() );
1187 std::vector<std::string> excplines;
1192 WAR << line << endl;
1193 excplines.push_back( std::move(line) );
1196 DBG << line << endl;
1209 MIL <<
"Key " << pubkey_r <<
" has been removed from RPM trusted keyring" << endl;
1221 std::list<PublicKey> ret;
1224 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
1226 Edition edition = it->tag_edition();
1231 getData(
"gpg-pubkey", edition, result );
1232 TmpFile file(getZYpp()->tmpPath());
1238 os << result->tag_description();
1247 catch ( std::exception & e )
1249 ERR <<
"Could not dump key " << edition.
asString() <<
" in tmp file " << file.
path() << endl;
1259 std::set<Edition> ret;
1262 for ( it.
findByName(
"gpg-pubkey" ); *it; ++it )
1264 Edition edition = it->tag_edition();
1266 ret.insert( edition );
1283 std::list<FileInfo> result;
1318 if (!name_r.empty())
1320 res = (it->tag_name() == name_r);
1341 return it->tag_name();
1455 struct RpmlogCapture :
public std::string
1458 { rpmlog()._cap =
this; }
1461 { rpmlog()._cap =
nullptr; }
1469 rpmlogSetCallback( rpmLogCB,
this );
1470 rpmSetVerbosity( RPMLOG_INFO );
1471 _f = ::fopen(
"/dev/null",
"w");
1472 rpmlogSetFile(
_f );
1476 {
if (
_f ) ::fclose(
_f ); }
1478 static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r )
1479 {
return reinterpret_cast<Rpmlog*
>(data_r)->rpmLog( rec_r ); }
1481 int rpmLog( rpmlogRec rec_r )
1483 if (
_cap ) (*_cap) = rpmlogRecMessage( rec_r );
1484 return RPMLOG_DEFAULT;
1491 static Rpmlog & rpmlog()
1492 {
static Rpmlog _rpmlog;
return _rpmlog; }
1497 bool requireGPGSig_r,
1498 RpmDb::CheckPackageDetail & detail_r )
1501 if ( ! file.isFile() )
1503 ERR <<
"Not a file: " << file << endl;
1507 FD_t fd = ::Fopen( file.asString().c_str(),
"r.ufdio" );
1508 if ( fd == 0 || ::Ferror(fd) )
1510 ERR <<
"Can't open file for reading: " << file <<
" (" << ::Fstrerror(fd) <<
")" << endl;
1515 rpmts ts = ::rpmtsCreate();
1516 ::rpmtsSetRootDir( ts, root_r.
c_str() );
1517 ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT );
1519 rpmQVKArguments_s qva;
1520 memset( &qva, 0,
sizeof(rpmQVKArguments_s) );
1521 qva.qva_flags = (VERIFY_DIGEST|VERIFY_SIGNATURE);
1523 RpmlogCapture vresult;
1524 LocaleGuard guard( LC_ALL,
"C" );
1525 int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.
basename().c_str() );
1534 typedef std::map<std::string,RpmDb::CheckPackageResult> ResultMap;
1535 static const ResultMap resultMap {
1543 auto getresult = [](
const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type {
1544 auto it = resultMap.find( key );
1549 unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 };
1554 SawHeaderSig = (1 << 0),
1555 SawHeaderDigest = (1 << 1),
1556 SawPayloadDigest = (1 << 2),
1558 SawDigest = (1 << 4),
1560 unsigned saw = SawNone;
1562 static const str::regex rx(
"^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" );
1572 std::vector<std::string> lines;
1573 str::split( vresult, std::back_inserter(lines),
"\n" );
1575 for (
unsigned i = 1; i < lines.size(); ++i )
1577 std::string & line( lines[i] );
1582 lineres = getresult( resultMap, what[3] );
1586 if ( what[1][0] ==
'H' ) {
1587 saw |= ( what[2][0] ==
'S' ? SawHeaderSig :SawHeaderDigest );
1589 else if ( what[1][0] ==
'P' ) {
1590 if ( what[2][0] ==
'd' ) saw |= SawPayloadDigest;
1593 saw |= ( what[2][0] ==
'S' ? SawSig : SawDigest );
1598 detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, std::move(line) ) );
1620 bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) );
1621 if ( not isSigned ) {
1622 std::string message {
" " };
1623 if ( not (saw & SawHeaderSig) )
1624 message +=
_(
"Package header is not signed!");
1626 message +=
_(
"Package payload is not signed!");
1628 detail_r.push_back( RpmDb::CheckPackageDetail::value_type(
RpmDb::CHK_NOSIG, std::move(message) ) );
1629 if ( requireGPGSig_r )
1636 WAR << path_r <<
" (" << requireGPGSig_r <<
" -> " << ret <<
")" << endl;
1649 {
return doCheckPackageSig( path_r,
root(),
false, detail_r ); }
1655 {
return doCheckPackageSig( path_r,
root(),
true, detail_r ); }
1670 opts.push_back (
"-V");
1671 opts.push_back (
"--nodeps");
1672 opts.push_back (
"--noscripts");
1673 opts.push_back (
"--nomd5");
1674 opts.push_back (
"--");
1675 opts.push_back (packageName.c_str());
1696 if (line.length() > 12 &&
1697 (line[0] ==
'S' || line[0] ==
's' ||
1698 (line[0] ==
'.' && line[7] ==
'T')))
1701 std::string filename;
1703 filename.assign(line, 11, line.length() - 11);
1704 fileList.insert(filename);
1744 #if defined(WORKAROUNDRPMPWDBUG)
1745 args.push_back(
"#/");
1747 args.push_back(
"rpm");
1748 args.push_back(
"--root");
1749 args.push_back(
_root.asString().c_str());
1750 args.push_back(
"--dbpath");
1751 args.push_back(
_dbPath.asString().c_str());
1753 args.push_back(
"-vv");
1754 const char* argv[args.size() + opts.size() + 1];
1756 const char** p = argv;
1757 p =
copy (args.begin (), args.end (), p);
1758 p =
copy (opts.begin (), opts.end (), p);
1784 int inputfileFd = ::fileno( inputfile );
1790 FD_SET( inputfileFd, &rfds );
1797 int retval = select( inputfileFd+1, &rfds, NULL, NULL, &tv );
1801 ERR <<
"select error: " <<
strerror(errno) << endl;
1802 if ( errno != EINTR )
1808 static size_t linebuffer_size = 0;
1809 static char * linebuffer = 0;
1810 ssize_t nread =
getline( &linebuffer, &linebuffer_size, inputfile );
1813 if ( ::feof( inputfile ) )
1820 if ( linebuffer[nread-1] ==
'\n' )
1822 line += std::string( linebuffer, nread );
1825 if ( ! ::ferror( inputfile ) || ::feof( inputfile ) )
1828 L_DBG(
"RPM_DEBUG") << line << endl;
1832 clearerr( inputfile );
1881 void RpmDb::processConfigFiles(
const std::string& line,
const std::string& name,
const char* typemsg,
const char* difffailmsg,
const char* diffgenmsg)
1883 std::string msg = line.substr(9);
1886 std::string file1s, file2s;
1890 pos1 = msg.find (typemsg);
1893 if ( pos1 == std::string::npos )
1896 pos2 = pos1 + strlen (typemsg);
1898 if (pos2 >= msg.length() )
1901 file1 = msg.substr (0, pos1);
1902 file2 = msg.substr (pos2);
1904 file1s = file1.asString();
1905 file2s = file2.asString();
1909 file1 =
_root + file1;
1910 file2 =
_root + file2;
1914 int ret =
diffFiles (file1.asString(), file2.asString(), out, 25);
1920 ERR <<
"Could not create " << file.asString() << endl;
1924 std::ofstream notify(file.asString().c_str(), std::ios::out|std::ios::app);
1927 ERR <<
"Could not open " << file << endl;
1933 notify <<
str::form(
_(
"Changed configuration files for %s:"), name.c_str()) << endl;
1936 ERR <<
"diff failed" << endl;
1938 file1s.c_str(), file2s.c_str()) << endl;
1943 file1s.c_str(), file2s.c_str()) << endl;
1948 if (out.substr(0,4) ==
"--- ")
1950 out.replace(4, file1.asString().length(), file1s);
1953 if (pos != std::string::npos)
1955 out.replace(pos+5, file2.asString().length(), file2s);
1958 notify << out << endl;
1961 notify.open(
"/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles");
1966 WAR <<
"rpm created " << file2 <<
" but it is not different from " << file2 << endl;
1982 report->start(filename);
1997 report->finish( excpt_r );
2013 MIL <<
"RpmDb::installPackage(" << filename <<
"," << flags <<
")" << endl;
2022 ERR <<
"backup of " << filename.asString() <<
" failed" << endl;
2025 report->progress( 0 );
2031 opts.push_back(
"-i");
2033 opts.push_back(
"-U");
2035 opts.push_back(
"--percent");
2036 opts.push_back(
"--noglob");
2040 opts.push_back(
"--ignorearch");
2043 opts.push_back(
"--nodigest");
2045 opts.push_back(
"--nosignature");
2047 opts.push_back (
"--excludedocs");
2049 opts.push_back (
"--noscripts");
2051 opts.push_back (
"--force");
2053 opts.push_back (
"--nodeps");
2055 opts.push_back (
"--ignoresize");
2057 opts.push_back (
"--justdb");
2059 opts.push_back (
"--test");
2061 opts.push_back (
"--noposttrans");
2063 opts.push_back(
"--");
2066 std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) );
2067 opts.push_back ( quotedFilename.c_str() );
2074 std::vector<std::string> configwarnings;
2076 unsigned linecnt = 0;
2082 sscanf( line.c_str() + 2,
"%d", &percent );
2083 report->progress( percent );
2089 else if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2092 rpmmsg += line+
'\n';
2095 configwarnings.push_back(line);
2098 rpmmsg +=
"[truncated]\n";
2103 for (std::vector<std::string>::iterator it = configwarnings.begin();
2104 it != configwarnings.end(); ++it)
2108 _(
"rpm saved %s as %s, but it was impossible to determine the difference"),
2110 _(
"rpm saved %s as %s.\nHere are the first 25 lines of difference:\n"));
2113 _(
"rpm created %s as %s, but it was impossible to determine the difference"),
2115 _(
"rpm created %s as %s.\nHere are the first 25 lines of difference:\n"));
2118 if ( rpm_status != 0 )
2121 str::form(
"%s install failed", Pathname::basename(filename).c_str()),
2123 std::ostringstream sstr;
2124 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2125 historylog.
comment(sstr.str());
2129 else if ( ! rpmmsg.empty() )
2132 str::form(
"%s installed ok", Pathname::basename(filename).c_str()),
2134 std::ostringstream sstr;
2135 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
2136 historylog.
comment(sstr.str());
2140 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2154 +
"-" + package->edition().version()
2155 +
"-" + package->edition().release()
2156 +
"." + package->arch().asString(), flags );
2169 report->start( name_r );
2184 report->finish( excpt_r );
2201 MIL <<
"RpmDb::doRemovePackage(" << name_r <<
"," << flags <<
")" << endl;
2210 ERR <<
"backup of " << name_r <<
" failed" << endl;
2212 report->progress( 0 );
2216 report->progress( 100 );
2221 opts.push_back(
"-e");
2222 opts.push_back(
"--allmatches");
2225 opts.push_back(
"--noscripts");
2227 opts.push_back(
"--nodeps");
2229 opts.push_back(
"--justdb");
2231 opts.push_back (
"--test");
2234 WAR <<
"IGNORE OPTION: 'rpm -e' does not support '--force'" << endl;
2237 opts.push_back(
"--");
2238 opts.push_back(name_r.c_str());
2250 report->progress( 5 );
2251 unsigned linecnt = 0;
2256 else if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2258 rpmmsg += line+
'\n';
2261 rpmmsg +=
"[truncated]\n";
2262 report->progress( 50 );
2265 if ( rpm_status != 0 )
2268 str::form(
"%s remove failed", name_r.c_str()),
true );
2269 std::ostringstream sstr;
2270 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2271 historylog.
comment(sstr.str());
2275 else if ( ! rpmmsg.empty() )
2278 str::form(
"%s removed ok", name_r.c_str()),
true );
2280 std::ostringstream sstr;
2281 sstr <<
"Additional rpm output:" << endl << rpmmsg << endl;
2282 historylog.
comment(sstr.str());
2286 report->finishInfo(
str::form(
"%s:\n%s\n",
_(
"Additional rpm output"), rpmmsg.c_str() ));
2315 Pathname backupFilename;
2320 INT <<
"_backuppath empty" << endl;
2328 ERR <<
"Error while getting changed files for package " <<
2329 packageName << endl;
2333 if (fileList.size() <= 0)
2335 DBG <<
"package " << packageName <<
" not changed -> no backup" << endl;
2347 struct tm *currentLocalTime = localtime(¤tTime);
2349 int date = (currentLocalTime->tm_year + 1900) * 10000
2350 + (currentLocalTime->tm_mon + 1) * 100
2351 + currentLocalTime->tm_mday;
2357 +
str::form(
"%s-%d-%d.tar.gz",packageName.c_str(), date, num);
2360 while ( PathInfo(backupFilename).isExist() && num++ < 1000);
2362 PathInfo pi(filestobackupfile);
2363 if (pi.isExist() && !pi.isFile())
2365 ERR << filestobackupfile.asString() <<
" already exists and is no file" << endl;
2369 std::ofstream fp ( filestobackupfile.asString().c_str(), std::ios::out|std::ios::trunc );
2373 ERR <<
"could not open " << filestobackupfile.asString() << endl;
2377 for (FileList::const_iterator cit = fileList.begin();
2378 cit != fileList.end(); ++cit)
2380 std::string name = *cit;
2381 if ( name[0] ==
'/' )
2384 name = name.substr( 1 );
2386 DBG <<
"saving file "<< name << endl;
2391 const char*
const argv[] =
2396 _root.asString().c_str(),
2397 "--ignore-failed-read",
2399 backupFilename.asString().c_str(),
2401 filestobackupfile.asString().c_str(),
2417 int ret = tar.
close();
2421 ERR <<
"tar failed: " << tarmsg << endl;
2426 MIL <<
"tar backup ok" << endl;
2428 str::form(
_(
"created backup %s"), backupFilename.asString().c_str())
2447 #define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break
2449 OUTS( CHK_OK,
_(
"Signature is OK") );
2451 OUTS( CHK_NOTFOUND,
_(
"Unknown type of signature") );
2453 OUTS( CHK_FAIL,
_(
"Signature does not verify") );
2455 OUTS( CHK_NOTTRUSTED,
_(
"Signature is OK, but key is not trusted") );
2457 OUTS( CHK_NOKEY,
_(
"Signatures public key is not available") );
2459 OUTS( CHK_ERROR,
_(
"File does not exist or signature can't be checked") );
2461 OUTS( CHK_NOSIG,
_(
"File is unsigned") );
2464 return str <<
"UnknowSignatureCheckError("+
str::numstring(obj)+
")";
2469 for (
const auto & el : obj )
2470 str << el.second << endl;
std::ostream & operator<<(std::ostream &str, const librpmDb::DbDirInfo &obj)
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Interface to the rpm program.
unsigned diffFiles(const std::string file1, const std::string file2, std::string &out, int maxlines)
bool hasDbV3ToV4() const
Whether dbV3ToV4 file exists.
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).
bool hasPackage(const std::string &name_r) const
Return true if package is installed.
static unsigned blockAccess()
Blocks further access to rpmdb.
std::string basename() const
Return the last component of this path.
static std::ostream & dumpState(std::ostream &str)
Dump debug info.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
bool hasProvides(const std::string &tag_r) const
Return true if at least one package provides a certain tag.
virtual void trustedKeyAdded(const PublicKey &key)
bool kill()
Kill the program.
static ZConfig & instance()
Singleton ctor.
Pathname _root
Root directory for all operations.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
std::string release() const
Release.
void getData(const std::string &name_r, RpmHeader::constPtr &result_r) const
Get an installed packages data from rpmdb.
bool hasSubkeys() const
!<
const std::string & asString() const
String representation.
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
Collect info about what kind of rpmdb seems to be present by looking at paths and filenames...
void exportTrustedKeysInZyppKeyRing()
insert all rpm trusted keys into zypp trusted keyring
static void dbAccess()
Access the database at the current default location.
void rebuildDatabase()
Rebuild the rpm database (rpm –rebuilddb).
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
std::string asString() const
void internal_initDatabase(const Pathname &root_r, const Pathname &dbPath_r, DbStateInfoBits &info_r)
Internal helper for initDatabase.
bool findByRequiredBy(const std::string &tag_r)
Reset to iterate all packages that require a certain tag.
void modifyDatabase()
Called before the database is modified by installPackage/removePackage.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Edition represents [epoch:]version[-release]
bool relative() const
Test for a relative path.
bool running()
Return whether program is running.
bool illegalArgs() const
Whether constructor arguments were illegal.
bool hasConflicts(const std::string &tag_r) const
Return true if at least one package conflicts with a certain tag.
Provide a new empty temporary file and delete it when no longer needed.
void importZyppKeyRingTrustedKeys()
iterates through zypp keyring and import all non existant keys into rpm keyring
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
bool backupPackage(const std::string &packageName)
create tar.gz of all changed files in a Package
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 'rpm -K')
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...
#define FILEFORBACKUPFILES
Subclass to retrieve database content.
Temporarily connect a ReceiveReport then restore the previous one.
std::string gpgPubkeyVersion() const
bool hasDbV4() const
Whether dbV4 file exists.
void importPubkey(const PublicKey &pubkey_r)
Import ascii armored public key in file pubkey_r.
void systemKill()
Forcably kill the system process.
bool dbsi_has(const DbStateInfoBits &val_r, const unsigned &bits_r) const
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
void moveToHistory(TContainer &&msgc_r)
addHistory from string container types (oldest first) moving
void syncTrustedKeys(SyncTrustedKeyBits mode_r=SYNC_BOTH)
Sync trusted keys stored in rpm database and zypp trusted keyring.
#define FAILIFNOTINITIALIZED
Pathname path() const
File containig the ASCII armored key.
std::string getline(std::istream &str)
Read one line from stream.
virtual std::ostream & dumpOn(std::ostream &str) const
Dump debug info.
Store and operate on date (time_t).
Pathname _backuppath
/var/adm/backup
const PathInfo & dbV3ToV4() const
rpmV3 database backup created on conversion to rpmV4 (_dbDir/packages.rpm3)
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t")
Split line_r into words.
int exit_code
The exit code of the rpm process, or -1 if not yet known.
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 'unlink'.
std::string asString() const
shared_ptr< RpmException > dbError() const
Return any database error.
SyncTrustedKeyBits
Sync mode for syncTrustedKeys.
bool systemReadLine(std::string &line)
Read a line from the general rpm query.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
int systemStatus()
Return the exit status of the general rpm process, closing the connection if not already done...
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
const char * c_str() const
String representation.
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Detailed rpm signature check log messages A single multiline message if CHK_OK.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
static unsigned dbRelease(bool force_r=false)
If there are no outstanding references to the database (e.g.
static shared_ptr< KeyRingSignalReceiver > sKeyRingReceiver
bool hasDbV3() const
Whether dbV3 file exists.
std::string version() const
Version.
ExternalProgram * process
The connection to the rpm process.
Writing the zypp history fileReference counted signleton for writhing the zypp history file...
void doRebuildDatabase(callback::SendReport< RebuildDBReport > &report)
std::set< Edition > pubkeyEditions() const
Return the edition of all installed public keys.
bool findByFile(const std::string &file_r)
Reset to iterate all packages that own a certain file.
std::string receiveLine()
Read one line from the input stream.
const Pathname & root() const
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
Stderr_Disposition
Define symbols for different policies on the handling of stderr.
DbStateInfoBits _dbStateInfo
Internal state info.
Just inherits Exception to separate media exceptions.
FILE * inputFile() const
Return the input stream.
std::string numstring(char n, int w=0)
export rpm trusted keys into zypp trusted keyring
const IdString Solvable::retractedToken retracted patch package()" }
virtual void trustedKeyRemoved(const PublicKey &key)
bool findPackage(const std::string &name_r)
Find package by name.
static void unblockAccess()
Allow access to rpmdb e.g.
std::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
void doInstallPackage(const Pathname &filename, RpmInstFlags flags, callback::SendReport< RpmInstallReport > &report)
int close()
Wait for the progamm to complete.
void removePubkey(const PublicKey &pubkey_r)
Remove a public key from the rpm database.
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"
int copy(const Pathname &file, const Pathname &dest)
Like 'cp file dest'.
const PathInfo & dbV4() const
rpmV4 database (_dbDir/Packages)
bool _packagebackups
create package backups?
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
bool hasRequiredBy(const std::string &tag_r) const
Return true if at least one package requires a certain tag.
Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile).
void doRemovePackage(const std::string &name_r, RpmInstFlags flags, callback::SendReport< RpmRemoveReport > &report)
Base class for Exception.
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
void setBackupPath(const Pathname &path)
set path where package backups are stored
static Date now()
Return the current time.
void convertV3toV4(const Pathname &v3db_r, const librpmDb::constPtr &v4db_r)
void initDatabase(Pathname root_r=Pathname(), Pathname dbPath_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database.
std::string error_message
Error message from running rpm as external program.
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
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 ...
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Date timestamp() const
timestamp of the rpm database (last modification)
const Pathname & dbPath() const
bool findByConflicts(const std::string &tag_r)
Reset to iterate all packages that conflict with a certain tag.
Wrapper class for ::stat/::lstat.
const PathInfo & dbDir() const
database directory (unset on illegal constructor arguments)
void setBlocking(bool mode)
Set the blocking mode of the input stream.
CheckPackageResult
checkPackage result
std::list< PublicKey > pubkeys() const
Return the long ids of all installed public keys.
void dbsi_set(DbStateInfoBits &val_r, const unsigned &bits_r) const
std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
static void removeV3(const Pathname &dbdir_r, bool v3backup_r)
Remove the rpm3 database in dbdir_r.
bool queryChangedFiles(FileList &fileList, const std::string &packageName)
determine which files of an installed package have been modified.
void dbsi_clr(DbStateInfoBits &val_r, const unsigned &bits_r) const
static void removeV4(const Pathname &dbdir_r, bool v3backup_r)
Remove the rpm4 database in dbdir_r and optionally any backup created on conversion.
std::string strerror(int errno_r)
Return string describing the error_r code.
std::ostream & operator<<(std::ostream &str, const Glob &obj)
bool usableArgs() const
Whether constructor arguments were llegal and dbDir either is a directory or may be created (path doe...
const PathInfo & dbV3() const
rpmV3 database (_dbDir/packages.rpm)
intrusive_ptr< const librpmDb > constPtr
std::string gpgPubkeyRelease() const
void run_rpm(const RpmArgVec &options, ExternalProgram::Stderr_Disposition stderr_disp=ExternalProgram::Stderr_To_Stdout)
Run rpm with the specified arguments and handle stderr.
KeyRingSignalReceiver(RpmDb &rpmdb)
void restat()
Restat all paths.
TraitsType::constPtrType constPtr
#define MAXRPMMESSAGELINES
std::string whoOwnsFile(const std::string &file_r) const
Return name of package owning file or empty string if no installed package owns file.
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Pathname _dbPath
Directory that contains the rpmdb.
std::set< std::string > FileList
std::vector< const char * > RpmArgVec