X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=zypp%2Ftarget%2Frpm%2FRpmDb.cc;h=00240a47ffc6e142f5df49da0227012ba46658b4;hb=1f206940fbbd2652d4715716c16385f081df544c;hp=7203d7977fa44ceadf9a67462ac6d0f635b1254b;hpb=33218c81059225c33b2dd433214852b74bedad25;p=platform%2Fupstream%2Flibzypp.git diff --git a/zypp/target/rpm/RpmDb.cc b/zypp/target/rpm/RpmDb.cc index 7203d79..00240a4 100644 --- a/zypp/target/rpm/RpmDb.cc +++ b/zypp/target/rpm/RpmDb.cc @@ -33,11 +33,13 @@ extern "C" #include "zypp/base/String.h" #include "zypp/base/Gettext.h" #include "zypp/base/LocaleGuard.h" +#include "zypp/base/DtorReset.h" #include "zypp/Date.h" #include "zypp/Pathname.h" #include "zypp/PathInfo.h" #include "zypp/PublicKey.h" +#include "zypp/ProgressData.h" #include "zypp/target/rpm/RpmDb.h" #include "zypp/target/rpm/RpmCallbacks.h" @@ -183,37 +185,6 @@ inline std::string stringPath( const Pathname & root_r, const Pathname & sub_r ) return librpmDb::stringPath( root_r, sub_r ); } -/****************************************************************** - ** - ** - ** FUNCTION NAME : operator<< - ** FUNCTION TYPE : std::ostream & -*/ -std::ostream & operator<<( std::ostream & str, const RpmDb::DbStateInfoBits & obj ) -{ - if ( obj == RpmDb::DbSI_NO_INIT ) - { - str << "NO_INIT"; - } - else - { -#define ENUM_OUT(B,C) str << ( obj & RpmDb::B ? C : '-' ) - str << "V4("; - ENUM_OUT( DbSI_HAVE_V4, 'X' ); - ENUM_OUT( DbSI_MADE_V4, 'c' ); - ENUM_OUT( DbSI_MODIFIED_V4, 'm' ); - str << ")V3("; - ENUM_OUT( DbSI_HAVE_V3, 'X' ); - ENUM_OUT( DbSI_HAVE_V3TOV4, 'B' ); - ENUM_OUT( DbSI_MADE_V3TOV4, 'c' ); - str << ")"; -#undef ENUM_OUT - } - return str; -} - - - /////////////////////////////////////////////////////////////////// // // CLASS NAME : RpmDb @@ -231,11 +202,8 @@ std::ostream & operator<<( std::ostream & str, const RpmDb::DbStateInfoBits & ob // METHOD TYPE : Constructor // RpmDb::RpmDb() - : _dbStateInfo( DbSI_NO_INIT ) -#warning Check for obsolete memebers - , _backuppath ("/var/adm/backup") + : _backuppath ("/var/adm/backup") , _packagebackups(false) - , _warndirexists(false) { process = 0; exit_code = -1; @@ -261,23 +229,6 @@ RpmDb::~RpmDb() sKeyRingReceiver.reset(); } -Date RpmDb::timestamp() const -{ - Date ts_rpm; - - Pathname db_path; - if ( dbPath().empty() ) - db_path = "/var/lib/rpm"; - else - db_path = dbPath(); - - PathInfo rpmdb_info(root() + db_path + "/Packages"); - - if ( rpmdb_info.isExist() ) - return rpmdb_info.mtime(); - else - return Date::now(); -} /////////////////////////////////////////////////////////////////// // // @@ -286,27 +237,7 @@ Date RpmDb::timestamp() const // std::ostream & RpmDb::dumpOn( std::ostream & str ) const { - str << "RpmDb["; - - if ( _dbStateInfo == DbSI_NO_INIT ) - { - str << "NO_INIT"; - } - else - { -#define ENUM_OUT(B,C) str << ( _dbStateInfo & B ? C : '-' ) - str << "V4("; - ENUM_OUT( DbSI_HAVE_V4, 'X' ); - ENUM_OUT( DbSI_MADE_V4, 'c' ); - ENUM_OUT( DbSI_MODIFIED_V4, 'm' ); - str << ")V3("; - ENUM_OUT( DbSI_HAVE_V3, 'X' ); - ENUM_OUT( DbSI_HAVE_V3TOV4, 'B' ); - ENUM_OUT( DbSI_MADE_V3TOV4, 'c' ); - str << "): " << stringPath( _root, _dbPath ); -#undef ENUM_OUT - } - return str << "]"; + return str << "RpmDb[" << stringPath( _root, _dbPath ) << "]"; } /////////////////////////////////////////////////////////////////// @@ -315,7 +246,7 @@ std::ostream & RpmDb::dumpOn( std::ostream & str ) const // METHOD NAME : RpmDb::initDatabase // METHOD TYPE : PMError // -void RpmDb::initDatabase( Pathname root_r, Pathname dbPath_r, bool doRebuild_r ) +void RpmDb::initDatabase( Pathname root_r, bool doRebuild_r ) { /////////////////////////////////////////////////////////////////// // Check arguments @@ -325,17 +256,19 @@ void RpmDb::initDatabase( Pathname root_r, Pathname dbPath_r, bool doRebuild_r ) if ( root_r.empty() ) root_r = "/"; - if ( dbPath_r.empty() ) - dbPath_r = "/var/lib/rpm"; + // NOTE: Former argument, but now locked to "/var/lib/rpm". + // A custom dbPath is not actually needed and would only work + // reliably if libsolv also supports it. By now no further + // cleanup in the code. + const Pathname & dbPath_r { librpmDb::defaultDbPath() }; - if ( ! (root_r.absolute() && dbPath_r.absolute()) ) + if ( ! root_r.absolute() ) { ERR << "Illegal root or dbPath: " << stringPath( root_r, dbPath_r ) << endl; ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r)); } - if ( dbPath_r == "/var/lib/rpm" - && ! PathInfo( root_r/"/var/lib/rpm" ).isExist() + if ( ! PathInfo( root_r/"/var/lib/rpm" ).isExist() && PathInfo( root_r/"/usr/lib/sysimage/rpm" ).isDir() ) { WAR << "Rpm package was deleted? Injecting missing rpmdb compat symlink." << endl; @@ -372,56 +305,23 @@ void RpmDb::initDatabase( Pathname root_r, Pathname dbPath_r, bool doRebuild_r ) return; } - DbStateInfoBits info = DbSI_NO_INIT; try { - internal_initDatabase( root_r, dbPath_r, info ); + // creates dbdir and empty rpm database if not present + librpmDb::dbAccess( root_r ); } catch (const RpmException & excpt_r) { ZYPP_CAUGHT(excpt_r); librpmDb::blockAccess(); - ERR << "Cleanup on error: state " << info << endl; - - if ( dbsi_has( info, DbSI_MADE_V4 ) ) - { - // remove the newly created rpm4 database and - // any backup created on conversion. - removeV4( root_r + dbPath_r, dbsi_has( info, DbSI_MADE_V3TOV4 ) ); - } ZYPP_RETHROW(excpt_r); } - if ( dbsi_has( info, DbSI_HAVE_V3 ) ) - { - if ( root_r == "/" || dbsi_has( info, DbSI_MODIFIED_V4 ) ) - { - // Move obsolete rpm3 database beside. - MIL << "Cleanup: state " << info << endl; - removeV3( root_r + dbPath_r, dbsi_has( info, DbSI_MADE_V3TOV4 ) ); - dbsi_clr( info, DbSI_HAVE_V3 ); - } - else - { - // Performing an update: Keep the original rpm3 database - // and wait if the rpm4 database gets modified by installing - // or removing packages. Cleanup in modifyDatabase or closeDatabase. - MIL << "Update mode: Cleanup delayed until closeOldDatabase." << endl; - } - } -#warning CHECK: notify root about conversion backup. _root = root_r; _dbPath = dbPath_r; - _dbStateInfo = info; if ( doRebuild_r ) - { - if ( dbsi_has( info, DbSI_HAVE_V4 ) - && ! dbsi_has( info, DbSI_MADE_V4 ) ) - { - rebuildDatabase(); - } - } + rebuildDatabase(); MIL << "Synchronizing keys with zypp keyring" << endl; syncTrustedKeys(); @@ -438,286 +338,6 @@ void RpmDb::initDatabase( Pathname root_r, Pathname dbPath_r, bool doRebuild_r ) /////////////////////////////////////////////////////////////////// // // -// METHOD NAME : RpmDb::internal_initDatabase -// METHOD TYPE : PMError -// -void RpmDb::internal_initDatabase( const Pathname & root_r, const Pathname & dbPath_r, - DbStateInfoBits & info_r ) -{ - info_r = DbSI_NO_INIT; - - /////////////////////////////////////////////////////////////////// - // Get info about the desired database dir - /////////////////////////////////////////////////////////////////// - librpmDb::DbDirInfo dbInfo( root_r, dbPath_r ); - - if ( dbInfo.illegalArgs() ) - { - // should not happen (checked in initDatabase) - ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r)); - } - if ( ! dbInfo.usableArgs() ) - { - ERR << "Bad database directory: " << dbInfo.dbDir() << endl; - ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r)); - } - - if ( dbInfo.hasDbV4() ) - { - dbsi_set( info_r, DbSI_HAVE_V4 ); - MIL << "Found rpm4 database in " << dbInfo.dbDir() << endl; - } - else - { - MIL << "Creating new rpm4 database in " << dbInfo.dbDir() << endl; - } - - if ( dbInfo.hasDbV3() ) - { - dbsi_set( info_r, DbSI_HAVE_V3 ); - } - if ( dbInfo.hasDbV3ToV4() ) - { - dbsi_set( info_r, DbSI_HAVE_V3TOV4 ); - } - - DBG << "Initial state: " << info_r << ": " << stringPath( root_r, dbPath_r ); - librpmDb::dumpState( DBG ) << endl; - - /////////////////////////////////////////////////////////////////// - // Access database, create if needed - /////////////////////////////////////////////////////////////////// - - // creates dbdir and empty rpm4 database if not present - librpmDb::dbAccess( root_r, dbPath_r ); - - if ( ! dbInfo.hasDbV4() ) - { - dbInfo.restat(); - if ( dbInfo.hasDbV4() ) - { - dbsi_set( info_r, DbSI_HAVE_V4 | DbSI_MADE_V4 ); - } - } - - DBG << "Access state: " << info_r << ": " << stringPath( root_r, dbPath_r ); - librpmDb::dumpState( DBG ) << endl; - - /////////////////////////////////////////////////////////////////// - // Check whether to convert something. Create backup but do - // not remove anything here - /////////////////////////////////////////////////////////////////// - librpmDb::constPtr dbptr; - librpmDb::dbAccess( dbptr ); - bool dbEmpty = dbptr->empty(); - if ( dbEmpty ) - { - MIL << "Empty rpm4 database " << dbInfo.dbV4() << endl; - } - - if ( dbInfo.hasDbV3() ) - { - MIL << "Found rpm3 database " << dbInfo.dbV3() << endl; - - if ( dbEmpty ) - { - extern void convertV3toV4( const Pathname & v3db_r, const librpmDb::constPtr & v4db_r ); - convertV3toV4( dbInfo.dbV3().path(), dbptr ); - - // create a backup copy - int res = filesystem::copy( dbInfo.dbV3().path(), dbInfo.dbV3ToV4().path() ); - if ( res ) - { - WAR << "Backup converted rpm3 database failed: error(" << res << ")" << endl; - } - else - { - dbInfo.restat(); - if ( dbInfo.hasDbV3ToV4() ) - { - MIL << "Backup converted rpm3 database: " << dbInfo.dbV3ToV4() << endl; - dbsi_set( info_r, DbSI_HAVE_V3TOV4 | DbSI_MADE_V3TOV4 ); - } - } - - } - else - { - - WAR << "Non empty rpm3 and rpm4 database found: using rpm4" << endl; - // set DbSI_MODIFIED_V4 as it's not a temporary which can be removed. - dbsi_set( info_r, DbSI_MODIFIED_V4 ); - - } - - DBG << "Convert state: " << info_r << ": " << stringPath( root_r, dbPath_r ); - librpmDb::dumpState( DBG ) << endl; - } - - if ( dbInfo.hasDbV3ToV4() ) - { - MIL << "Rpm3 database backup: " << dbInfo.dbV3ToV4() << endl; - } -} - -/////////////////////////////////////////////////////////////////// -// -// -// METHOD NAME : RpmDb::removeV4 -// METHOD TYPE : void -// -void RpmDb::removeV4( const Pathname & dbdir_r, bool v3backup_r ) -{ - const char * v3backup = "packages.rpm3"; - const char * master = "Packages"; - const char * index[] = - { - "Basenames", - "Conflictname", - "Depends", - "Dirnames", - "Filemd5s", - "Group", - "Installtid", - "Name", - "Providename", - "Provideversion", - "Pubkeys", - "Requirename", - "Requireversion", - "Sha1header", - "Sigmd5", - "Triggername", - // last entry! - NULL - }; - - PathInfo pi( dbdir_r ); - if ( ! pi.isDir() ) - { - ERR << "Can't remove rpm4 database in non directory: " << dbdir_r << endl; - return; - } - - for ( const char ** f = index; *f; ++f ) - { - pi( dbdir_r + *f ); - if ( pi.isFile() ) - { - filesystem::unlink( pi.path() ); - } - } - - pi( dbdir_r + master ); - if ( pi.isFile() ) - { - MIL << "Removing rpm4 database " << pi << endl; - filesystem::unlink( pi.path() ); - } - - if ( v3backup_r ) - { - pi( dbdir_r + v3backup ); - if ( pi.isFile() ) - { - MIL << "Removing converted rpm3 database backup " << pi << endl; - filesystem::unlink( pi.path() ); - } - } -} - -/////////////////////////////////////////////////////////////////// -// -// -// METHOD NAME : RpmDb::removeV3 -// METHOD TYPE : void -// -void RpmDb::removeV3( const Pathname & dbdir_r, bool v3backup_r ) -{ - const char * master = "packages.rpm"; - const char * index[] = - { - "conflictsindex.rpm", - "fileindex.rpm", - "groupindex.rpm", - "nameindex.rpm", - "providesindex.rpm", - "requiredby.rpm", - "triggerindex.rpm", - // last entry! - NULL - }; - - PathInfo pi( dbdir_r ); - if ( ! pi.isDir() ) - { - ERR << "Can't remove rpm3 database in non directory: " << dbdir_r << endl; - return; - } - - for ( const char ** f = index; *f; ++f ) - { - pi( dbdir_r + *f ); - if ( pi.isFile() ) - { - filesystem::unlink( pi.path() ); - } - } - -#warning CHECK: compare vs existing v3 backup. notify root - pi( dbdir_r + master ); - if ( pi.isFile() ) - { - Pathname m( pi.path() ); - if ( v3backup_r ) - { - // backup was already created - filesystem::unlink( m ); - Pathname b( m.extend( "3" ) ); - pi( b ); // stat backup - } - else - { - Pathname b( m.extend( ".deleted" ) ); - pi( b ); - if ( pi.isFile() ) - { - // rempve existing backup - filesystem::unlink( b ); - } - filesystem::rename( m, b ); - pi( b ); // stat backup - } - MIL << "(Re)moved rpm3 database to " << pi << endl; - } -} - -/////////////////////////////////////////////////////////////////// -// -// -// METHOD NAME : RpmDb::modifyDatabase -// METHOD TYPE : void -// -void RpmDb::modifyDatabase() -{ - if ( ! initialized() ) - return; - - // tag database as modified - dbsi_set( _dbStateInfo, DbSI_MODIFIED_V4 ); - - // Move outdated rpm3 database beside. - if ( dbsi_has( _dbStateInfo, DbSI_HAVE_V3 ) ) - { - MIL << "Update mode: Delayed cleanup: state " << _dbStateInfo << endl; - removeV3( _root + _dbPath, dbsi_has( _dbStateInfo, DbSI_MADE_V3TOV4 ) ); - dbsi_clr( _dbStateInfo, DbSI_HAVE_V3 ); - } -} - -/////////////////////////////////////////////////////////////////// -// -// // METHOD NAME : RpmDb::closeDatabase // METHOD TYPE : PMError // @@ -736,28 +356,9 @@ void RpmDb::closeDatabase() librpmDb::blockAccess(); /////////////////////////////////////////////////////////////////// - // Check fate if old version database still present - /////////////////////////////////////////////////////////////////// - if ( dbsi_has( _dbStateInfo, DbSI_HAVE_V3 ) ) - { - MIL << "Update mode: Delayed cleanup: state " << _dbStateInfo << endl; - if ( dbsi_has( _dbStateInfo, DbSI_MODIFIED_V4 ) ) - { - // Move outdated rpm3 database beside. - removeV3( _root + _dbPath, dbsi_has( _dbStateInfo, DbSI_MADE_V3TOV4 ) ); - } - else - { - // Remove unmodified rpm4 database - removeV4( _root + _dbPath, dbsi_has( _dbStateInfo, DbSI_MADE_V3TOV4 ) ); - } - } - - /////////////////////////////////////////////////////////////////// // Uninit /////////////////////////////////////////////////////////////////// _root = _dbPath = Pathname(); - _dbStateInfo = DbSI_NO_INIT; MIL << "closeDatabase: " << *this << endl; } @@ -789,62 +390,73 @@ void RpmDb::rebuildDatabase() void RpmDb::doRebuildDatabase(callback::SendReport & report) { FAILIFNOTINITIALIZED; - MIL << "RpmDb::rebuildDatabase" << *this << endl; - // FIXME Timecount _t( "RpmDb::rebuildDatabase" ); - PathInfo dbMaster( root() + dbPath() + "Packages" ); - PathInfo dbMasterBackup( dbMaster.path().extend( ".y2backup" ) ); - - // run rpm - RpmArgVec opts; - opts.push_back("--rebuilddb"); - opts.push_back("-vv"); - - // don't call modifyDatabase because it would remove the old - // rpm3 database, if the current database is a temporary one. - run_rpm (opts, ExternalProgram::Stderr_To_Stdout); + const Pathname mydbpath { root()/dbPath() }; // the configured path used in reports + { + // For --rebuilddb take care we're using the real db directory + // and not a symlink. Otherwise rpm will rename the symlink and + // replace it with a real directory containing the converted db. + DtorReset guardRoot { _root }; + DtorReset guardDbPath{ _dbPath }; + _root = "/"; + _dbPath = filesystem::expandlink( mydbpath ); - // progress report: watch this file growing - PathInfo newMaster( root() - + dbPath().extend( str::form( "rebuilddb.%d", - process?process->getpid():0) ) - + "Packages" ); + // run rpm + RpmArgVec opts; + opts.push_back("--rebuilddb"); + opts.push_back("-vv"); + run_rpm (opts, ExternalProgram::Stderr_To_Stdout); + } - std::string line; - std::string errmsg; + // generate and report progress + ProgressData tics; + { + ProgressData::value_type hdrTotal = 0; + for ( librpmDb::db_const_iterator it; *it; ++it, ++hdrTotal ) + {;} + tics.range( hdrTotal ); + } + tics.sendTo( [&report,&mydbpath]( const ProgressData & tics_r ) -> bool { + return report->progress( tics_r.reportValue(), mydbpath ); + } ); + tics.toMin(); + std::string line; + std::string errmsg; while ( systemReadLine( line ) ) { - if ( newMaster() ) - { // file is removed at the end of rebuild. - // current size should be upper limit for new db - if ( ! report->progress( (100 * newMaster.size()) / dbMaster.size(), root() + dbPath()) ) + static const std::string debugPrefix { "D:" }; + static const std::string progressPrefix { "D: read h#" }; + static const std::string ignoreSuffix { "digest: OK" }; + + if ( ! str::startsWith( line, debugPrefix ) ) + { + if ( ! str::endsWith( line, ignoreSuffix ) ) { - WAR << "User requested abort." << endl; - systemKill(); - filesystem::recursive_rmdir( newMaster.path().dirname() ); + errmsg += line; + errmsg += '\n'; + WAR << line << endl; } } - - if ( line.compare( 0, 2, "D:" ) ) + else if ( str::startsWith( line, progressPrefix ) ) { - errmsg += line + '\n'; - // report.notify( line ); - WAR << line << endl; + if ( ! tics.incr() ) + { + WAR << "User requested abort." << endl; + systemKill(); + } } } - int rpm_status = systemStatus(); - - if ( rpm_status != 0 ) + if ( systemStatus() != 0 ) { //TranslatorExplanation after semicolon is error message ZYPP_THROW(RpmSubprocessException(std::string(_("RPM failed: ")) + (errmsg.empty() ? error_message: errmsg) ) ); } else { - report->progress( 100, root() + dbPath() ); // 100% + tics.toMax(); } } @@ -1123,8 +735,6 @@ void RpmDb::importPubkey( const PublicKey & pubkey_r ) opts.push_back ( "--allmatches" ); opts.push_back ( "--" ); opts.push_back ( keyName.c_str() ); - // don't call modifyDatabase because it would remove the old - // rpm3 database, if the current database is a temporary one. run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); std::string line; @@ -1149,9 +759,6 @@ void RpmDb::importPubkey( const PublicKey & pubkey_r ) opts.push_back ( "--" ); std::string pubkeypath( pubkey_r.path().asString() ); opts.push_back ( pubkeypath.c_str() ); - - // don't call modifyDatabase because it would remove the old - // rpm3 database, if the current database is a temporary one. run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); std::string line; @@ -1219,9 +826,6 @@ void RpmDb::removePubkey( const PublicKey & pubkey_r ) opts.push_back ( "-e" ); opts.push_back ( "--" ); opts.push_back ( rpm_name.c_str() ); - - // don't call modifyDatabase because it would remove the old - // rpm3 database, if the current database is a temporary one. run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); std::string line; @@ -2061,8 +1665,6 @@ void RpmDb::doInstallPackage( const Pathname & filename, RpmInstFlags flags, cal // rpm requires additional quoting of special chars: std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) ); opts.push_back ( quotedFilename.c_str() ); - - modifyDatabase(); // BEFORE run_rpm run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); std::string line; @@ -2232,8 +1834,6 @@ void RpmDb::doRemovePackage( const std::string & name_r, RpmInstFlags flags, cal opts.push_back("--"); opts.push_back(name_r.c_str()); - - modifyDatabase(); // BEFORE run_rpm run_rpm (opts, ExternalProgram::Stderr_To_Stdout); std::string line;